@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,270 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { DescribeCampaignCommand, } from '@aws-sdk/client-connectcampaignsv2';
|
|
4
|
+
import { ListIntegrationAssociationsCommand, } from '@aws-sdk/client-connect';
|
|
5
|
+
import { GetMessageTemplateCommand, ListMessageTemplatesCommand, RenderMessageTemplateCommand, } from '@aws-sdk/client-qconnect';
|
|
6
|
+
import { ACTIVE_VERSION_QUALIFIER, PUSH_CHANNEL_SUBTYPE, Q_MESSAGE_TEMPLATES_INTEGRATION_TYPE, } from '../../constants.js';
|
|
7
|
+
/** Max length of a single Q Connect render attribute value. */
|
|
8
|
+
const MAX_ATTRIBUTE_LENGTH = 32767;
|
|
9
|
+
/**
|
|
10
|
+
* Per-container cache of `campaignId -> knowledgeBaseId`. KB discovery
|
|
11
|
+
* (DescribeCampaign + ListIntegrationAssociations) is stable for a campaign's
|
|
12
|
+
* lifetime, so warm Lambda invocations skip the two lookups.
|
|
13
|
+
*
|
|
14
|
+
* TODO(prod): unbounded (one entry per distinct campaignId per container) — cap
|
|
15
|
+
* or TTL this before GA if a single container fronts many campaigns.
|
|
16
|
+
*/
|
|
17
|
+
const kbIdByCampaign = new Map();
|
|
18
|
+
/**
|
|
19
|
+
* Discover the Q in Connect knowledge base backing a campaign's Connect
|
|
20
|
+
* instance, caching per container:
|
|
21
|
+
*
|
|
22
|
+
* CampaignId -> connectcampaignsv2 DescribeCampaign -> campaign.connectInstanceId
|
|
23
|
+
* -> connect ListIntegrationAssociations(Q_MESSAGE_TEMPLATES)
|
|
24
|
+
* -> IntegrationArn (arn:aws:wisdom:...:knowledge-base/<kbId>) -> kbId
|
|
25
|
+
*
|
|
26
|
+
* Returns `undefined` (never throws) when the instance id or the KB integration
|
|
27
|
+
* cannot be resolved — the caller then falls back to non-templated copy. If
|
|
28
|
+
* DescribeCampaign does not carry `connectInstanceId`, that is logged so the
|
|
29
|
+
* real shape can be inspected.
|
|
30
|
+
*/
|
|
31
|
+
export const discoverKnowledgeBaseId = async (clients, campaignId) => {
|
|
32
|
+
const cached = kbIdByCampaign.get(campaignId);
|
|
33
|
+
if (cached) {
|
|
34
|
+
return cached;
|
|
35
|
+
}
|
|
36
|
+
const describe = await clients.campaigns.send(new DescribeCampaignCommand({ id: campaignId }));
|
|
37
|
+
const instanceId = describe.campaign?.connectInstanceId;
|
|
38
|
+
if (!instanceId) {
|
|
39
|
+
console.warn('[push] kb.discover.noInstanceId', JSON.stringify({
|
|
40
|
+
campaignId,
|
|
41
|
+
campaignKeys: Object.keys(describe.campaign ?? {}),
|
|
42
|
+
}));
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
const assoc = await clients.connect.send(new ListIntegrationAssociationsCommand({
|
|
46
|
+
InstanceId: instanceId,
|
|
47
|
+
IntegrationType: Q_MESSAGE_TEMPLATES_INTEGRATION_TYPE,
|
|
48
|
+
}));
|
|
49
|
+
// A Connect instance has at most one Q_MESSAGE_TEMPLATES binding, so page 1
|
|
50
|
+
// always carries it and we don't paginate. Surface a NextToken if that ever
|
|
51
|
+
// stops holding so the edge case is observable rather than a silent miss.
|
|
52
|
+
if (assoc.NextToken) {
|
|
53
|
+
console.warn('[push] kb.discover.multiplePages', JSON.stringify({ campaignId, instanceId }));
|
|
54
|
+
}
|
|
55
|
+
const integrationArn = assoc.IntegrationAssociationSummaryList?.find((a) => a.IntegrationArn)?.IntegrationArn;
|
|
56
|
+
// Only trust a well-formed Q in Connect knowledge-base ARN
|
|
57
|
+
// (arn:aws:wisdom:...:knowledge-base/<kbId>); anything else yields a garbage
|
|
58
|
+
// id that would fail three calls later at render time.
|
|
59
|
+
const kbId = integrationArn?.includes('knowledge-base/')
|
|
60
|
+
? integrationArn.split('/').pop()
|
|
61
|
+
: undefined;
|
|
62
|
+
if (!kbId) {
|
|
63
|
+
console.warn('[push] kb.discover.noKnowledgeBase', JSON.stringify({ campaignId, instanceId, integrationArn }));
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
console.log('[push] kb.discover', JSON.stringify({ campaignId, instanceId, knowledgeBaseId: kbId }));
|
|
67
|
+
kbIdByCampaign.set(campaignId, kbId);
|
|
68
|
+
return kbId;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Find the PUSH message template in `knowledgeBaseId` whose name equals the
|
|
72
|
+
* journey `actionId` (the Custom-action block name). Pages ListMessageTemplates
|
|
73
|
+
* and filters client-side to `channelSubtype === PUSH`. Returns the matching
|
|
74
|
+
* template id, or `undefined` when none matches.
|
|
75
|
+
*/
|
|
76
|
+
const findPushTemplateId = async (qconnect, knowledgeBaseId, actionId) => {
|
|
77
|
+
let nextToken;
|
|
78
|
+
do {
|
|
79
|
+
const res = await qconnect.send(new ListMessageTemplatesCommand({
|
|
80
|
+
knowledgeBaseId,
|
|
81
|
+
maxResults: 100,
|
|
82
|
+
nextToken,
|
|
83
|
+
}));
|
|
84
|
+
const match = res.messageTemplateSummaries?.find((s) => s.channelSubtype === PUSH_CHANNEL_SUBTYPE && s.name === actionId);
|
|
85
|
+
if (match?.messageTemplateId) {
|
|
86
|
+
return match.messageTemplateId;
|
|
87
|
+
}
|
|
88
|
+
nextToken = res.nextToken;
|
|
89
|
+
} while (nextToken);
|
|
90
|
+
return undefined;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Resolve the PUSH message template for a journey run: discover the knowledge
|
|
94
|
+
* base from the campaign, find the PUSH template whose name == the ActionId,
|
|
95
|
+
* and confirm it has an ACTIVE version. Returns `undefined` (never throws) when
|
|
96
|
+
* anything is missing — no campaign metadata, no KB integration, no matching
|
|
97
|
+
* template — so the caller falls back to the non-templated per-profile copy.
|
|
98
|
+
*/
|
|
99
|
+
export const resolvePushTemplateContext = async (clients, campaign) => {
|
|
100
|
+
const campaignId = campaign.campaignId;
|
|
101
|
+
const actionId = campaign.actionId;
|
|
102
|
+
if (!campaignId || !actionId) {
|
|
103
|
+
console.log('[push] template.skip', JSON.stringify({
|
|
104
|
+
reason: 'missing campaignId or actionId',
|
|
105
|
+
campaignId: campaignId ?? null,
|
|
106
|
+
actionId: actionId ?? null,
|
|
107
|
+
}));
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
const knowledgeBaseId = await discoverKnowledgeBaseId(clients, campaignId);
|
|
112
|
+
if (!knowledgeBaseId) {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
const messageTemplateId = await findPushTemplateId(clients.qconnect, knowledgeBaseId, actionId);
|
|
116
|
+
if (!messageTemplateId) {
|
|
117
|
+
console.warn('[push] template.noMatch', JSON.stringify({ knowledgeBaseId, actionId }));
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
// Confirm an ACTIVE (published) version exists; if not, still render the
|
|
121
|
+
// latest content (GetMessageTemplate is diagnostic here, not a gate).
|
|
122
|
+
try {
|
|
123
|
+
await clients.qconnect.send(new GetMessageTemplateCommand({
|
|
124
|
+
knowledgeBaseId,
|
|
125
|
+
messageTemplateId: `${messageTemplateId}:${ACTIVE_VERSION_QUALIFIER}`,
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
console.warn('[push] template.noActiveVersion', JSON.stringify({
|
|
130
|
+
knowledgeBaseId,
|
|
131
|
+
messageTemplateId,
|
|
132
|
+
error: err instanceof Error ? err.message : 'unknown',
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
console.log('[push] template.resolved', JSON.stringify({ knowledgeBaseId, messageTemplateId, actionId }));
|
|
136
|
+
return {
|
|
137
|
+
qconnect: clients.qconnect,
|
|
138
|
+
knowledgeBaseId,
|
|
139
|
+
messageTemplateId,
|
|
140
|
+
templateName: actionId,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
console.warn('[push] template.resolveError', JSON.stringify({
|
|
145
|
+
campaignId,
|
|
146
|
+
actionId,
|
|
147
|
+
error: err instanceof Error ? err.message : 'unknown',
|
|
148
|
+
}));
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* Flatten a profile's `CustomerData` into a flat `customAttributes` map for
|
|
154
|
+
* RenderMessageTemplate. Empirically only `{{Attributes.<flatKey>}}` variables
|
|
155
|
+
* interpolate (from `customAttributes`); the `{{Customer.*}}` namespace does not
|
|
156
|
+
* resolve here — so the profile's `firstName` and every `attributes.*` entry are
|
|
157
|
+
* passed as flat custom attributes (templates reference e.g.
|
|
158
|
+
* `{{Attributes.firstName}}`). Nested objects (`address`, `attributes`) are not
|
|
159
|
+
* added directly; `attributes` is merged one level deep. Non-string / empty
|
|
160
|
+
* values are dropped and values are capped at the render attribute-length limit.
|
|
161
|
+
*/
|
|
162
|
+
export const buildCustomAttributes = (customerData) => {
|
|
163
|
+
const out = {};
|
|
164
|
+
if (!customerData) {
|
|
165
|
+
return out;
|
|
166
|
+
}
|
|
167
|
+
const add = (key, value) => {
|
|
168
|
+
if (typeof value === 'string' && value.length > 0) {
|
|
169
|
+
out[key] = value.slice(0, MAX_ATTRIBUTE_LENGTH);
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
for (const [key, value] of Object.entries(customerData)) {
|
|
173
|
+
if (key === 'attributes' || key === 'address') {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
add(key, value);
|
|
177
|
+
}
|
|
178
|
+
const attributes = customerData.attributes;
|
|
179
|
+
if (attributes &&
|
|
180
|
+
typeof attributes === 'object' &&
|
|
181
|
+
!Array.isArray(attributes)) {
|
|
182
|
+
// attributes sub-keys overwrite top-level keys on collision (attributes is
|
|
183
|
+
// the authoritative custom-attribute store).
|
|
184
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
185
|
+
add(key, value);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return out;
|
|
189
|
+
};
|
|
190
|
+
/**
|
|
191
|
+
* Detects a Handlebars placeholder the renderer left unresolved, e.g. a
|
|
192
|
+
* `{{Attributes.firstName}}` var for a profile that has no `firstName`. Q Connect
|
|
193
|
+
* leaves such vars LITERAL in the output (and lists them in
|
|
194
|
+
* `attributesNotInterpolated`); shipping that raw text to a device is a bug, so
|
|
195
|
+
* copy that still contains one is rejected and the caller falls back to default.
|
|
196
|
+
*/
|
|
197
|
+
const hasUnresolvedPlaceholder = (value) => /\{\{.*?\}\}/.test(value);
|
|
198
|
+
const toMessage = (content) => {
|
|
199
|
+
const title = content?.title;
|
|
200
|
+
const body = content?.body?.content;
|
|
201
|
+
if (typeof title === 'string' &&
|
|
202
|
+
title.length > 0 &&
|
|
203
|
+
typeof body === 'string' &&
|
|
204
|
+
body.length > 0 &&
|
|
205
|
+
!hasUnresolvedPlaceholder(title) &&
|
|
206
|
+
!hasUnresolvedPlaceholder(body)) {
|
|
207
|
+
return { title, body };
|
|
208
|
+
}
|
|
209
|
+
return undefined;
|
|
210
|
+
};
|
|
211
|
+
/**
|
|
212
|
+
* Render the resolved PUSH template for ONE profile and map the per-platform
|
|
213
|
+
* copy to push channels:
|
|
214
|
+
* - `push.apns` -> `APNS` (+ `APNS_SANDBOX`)
|
|
215
|
+
* - `push.fcm` -> `GCM`
|
|
216
|
+
*
|
|
217
|
+
* The profile's `CustomerData` is passed as flat `customAttributes` so
|
|
218
|
+
* `{{Attributes.<key>}}` variables personalize. Returns a partial per-channel
|
|
219
|
+
* map (only channels the template defines both a title and body for), or
|
|
220
|
+
* `undefined` (never throws) when there is no push content or the render fails —
|
|
221
|
+
* the caller then falls back to the non-templated copy for that profile.
|
|
222
|
+
*/
|
|
223
|
+
export const renderProfileChannelMessages = async (ctx, target) => {
|
|
224
|
+
const customAttributes = buildCustomAttributes(target.customerData);
|
|
225
|
+
let res;
|
|
226
|
+
try {
|
|
227
|
+
res = await ctx.qconnect.send(new RenderMessageTemplateCommand({
|
|
228
|
+
knowledgeBaseId: ctx.knowledgeBaseId,
|
|
229
|
+
// Render the PUBLISHED version explicitly (verified: RenderMessageTemplate
|
|
230
|
+
// accepts the `:$ACTIVE_VERSION` qualifier) so a later saved draft can't
|
|
231
|
+
// silently change production copy.
|
|
232
|
+
messageTemplateId: `${ctx.messageTemplateId}:${ACTIVE_VERSION_QUALIFIER}`,
|
|
233
|
+
attributes: { customAttributes },
|
|
234
|
+
}));
|
|
235
|
+
}
|
|
236
|
+
catch (err) {
|
|
237
|
+
console.warn('[push] template.renderError', JSON.stringify({
|
|
238
|
+
templateName: ctx.templateName,
|
|
239
|
+
error: err instanceof Error ? err.message : 'unknown',
|
|
240
|
+
}));
|
|
241
|
+
return undefined;
|
|
242
|
+
}
|
|
243
|
+
const content = res.content;
|
|
244
|
+
const push = content?.push;
|
|
245
|
+
if (!push) {
|
|
246
|
+
return undefined;
|
|
247
|
+
}
|
|
248
|
+
const apns = toMessage(push.apns);
|
|
249
|
+
const fcm = toMessage(push.fcm);
|
|
250
|
+
const perChannel = {};
|
|
251
|
+
if (apns) {
|
|
252
|
+
perChannel.APNS = apns;
|
|
253
|
+
perChannel.APNS_SANDBOX = apns;
|
|
254
|
+
}
|
|
255
|
+
if (fcm) {
|
|
256
|
+
perChannel.GCM = fcm;
|
|
257
|
+
}
|
|
258
|
+
// Operational signal only: which channels the template rendered usable copy
|
|
259
|
+
// for, plus any template variables the renderer left un-interpolated (these
|
|
260
|
+
// are template-author-defined variable names, e.g. `Attributes.firstName`,
|
|
261
|
+
// not customer values). The rendered title/body are never logged.
|
|
262
|
+
console.log('[push] template.render', JSON.stringify({
|
|
263
|
+
templateName: ctx.templateName,
|
|
264
|
+
apnsRendered: Boolean(apns),
|
|
265
|
+
gcmRendered: Boolean(fcm),
|
|
266
|
+
attributesNotInterpolated: res.attributesNotInterpolated ?? [],
|
|
267
|
+
}));
|
|
268
|
+
return Object.keys(perChannel).length > 0 ? perChannel : undefined;
|
|
269
|
+
};
|
|
270
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVzc2FnZV90ZW1wbGF0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYW1iZGEvcHVzaC9tZXNzYWdlX3RlbXBsYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHFFQUFxRTtBQUNyRSxzQ0FBc0M7QUFFdEMsT0FBTyxFQUVMLHVCQUF1QixHQUN4QixNQUFNLG9DQUFvQyxDQUFDO0FBQzVDLE9BQU8sRUFFTCxrQ0FBa0MsR0FDbkMsTUFBTSx5QkFBeUIsQ0FBQztBQUNqQyxPQUFPLEVBQ0wseUJBQXlCLEVBQ3pCLDJCQUEyQixFQUUzQiw0QkFBNEIsR0FDN0IsTUFBTSwwQkFBMEIsQ0FBQztBQUVsQyxPQUFPLEVBQ0wsd0JBQXdCLEVBQ3hCLG9CQUFvQixFQUNwQixvQ0FBb0MsR0FDckMsTUFBTSxvQkFBb0IsQ0FBQztBQVE1QiwrREFBK0Q7QUFDL0QsTUFBTSxvQkFBb0IsR0FBRyxLQUFLLENBQUM7QUF5Qm5DOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLGNBQWMsR0FBRyxJQUFJLEdBQUcsRUFBa0IsQ0FBQztBQVFqRDs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBRyxLQUFLLEVBQzFDLE9BQXVELEVBQ3ZELFVBQWtCLEVBQ1csRUFBRTtJQUMvQixNQUFNLE1BQU0sR0FBRyxjQUFjLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzlDLElBQUksTUFBTSxFQUFFLENBQUM7UUFDWCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRUQsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksQ0FDM0MsSUFBSSx1QkFBdUIsQ0FBQyxFQUFFLEVBQUUsRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUNoRCxDQUFDO0lBQ0YsTUFBTSxVQUFVLEdBQUcsUUFBUSxDQUFDLFFBQVEsRUFBRSxpQkFBaUIsQ0FBQztJQUN4RCxJQUFJLENBQUMsVUFBVSxF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QUFJLEVBQUU7S0FDL0QsQ0FBQyxDQUNILENBQUM7SUFFRixPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDckUsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQge1xuICBDb25uZWN0Q2FtcGFpZ25zVjJDbGllbnQsXG4gIERlc2NyaWJlQ2FtcGFpZ25Db21tYW5kLFxufSBmcm9tICdAYXdzLXNkay9jbGllbnQtY29ubmVjdGNhbXBhaWduc3YyJztcbmltcG9ydCB7XG4gIENvbm5lY3RDbGllbnQsXG4gIExpc3RJbnRlZ3JhdGlvbkFzc29jaWF0aW9uc0NvbW1hbmQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1jb25uZWN0JztcbmltcG9ydCB7XG4gIEdldE1lc3NhZ2VUZW1wbGF0ZUNvbW1hbmQsXG4gIExpc3RNZXNzYWdlVGVtcGxhdGVzQ29tbWFuZCxcbiAgUUNvbm5lY3RDbGllbnQsXG4gIFJlbmRlck1lc3NhZ2VUZW1wbGF0ZUNvbW1hbmQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1xY29ubmVjdCc7XG5cbmltcG9ydCB7XG4gIEFDVElWRV9WRVJTSU9OX1FVQUxJRklFUixcbiAgUFVTSF9DSEFOTkVMX1NVQlRZUEUsXG4gIFFfTUVTU0FHRV9URU1QTEFURVNfSU5URUdSQVRJT05fVFlQRSxcbn0gZnJvbSAnLi4vLi4vY29uc3RhbnRzLmpzJztcbmltcG9ydCB7XG4gIENhbXBhaWduQ29udGV4dCxcbiAgUHJvZmlsZVRhcmdldCxcbiAgUHVzaENoYW5uZWxUeXBlLFxuICBQdXNoTWVzc2FnZSxcbn0gZnJvbSAnLi90eXBlcy5qcyc7XG5cbi8qKiBNYXggbGVuZ3RoIG9mIGEgc2luZ2xlIFEgQ29ubmVjdCByZW5kZXIgYXR0cmlidXRlIHZhbHVlLiAqL1xuY29uc3QgTUFYX0FUVFJJQlVURV9MRU5HVEggPSAzMjc2NztcblxuLyoqIFRoZSBBV1MgY2xpZW50cyB0aGUgdGVtcGxhdGUgcmVzb2x2ZXIgbmVlZHMuICovXG5leHBvcnQgdHlwZSBUZW1wbGF0ZUNsaWVudHMgPSB7XG4gIGNhbXBhaWduczogQ29ubmVjdENhbXBhaWduc1YyQ2xpZW50O1xuICBjb25uZWN0OiBDb25uZWN0Q2xpZW50O1xuICBxY29ubmVjdDogUUNvbm5lY3RDbGllbnQ7XG59O1xuXG4vKipcbiAqIEEgcmVzb2x2ZWQgUSBpbiBDb25uZWN0IFBVU0ggbWVzc2FnZSB0ZW1wbGF0ZSBmb3Igb25lIGpvdXJuZXkgcnVuOiB0aGVcbiAqIGtub3dsZWRnZSBiYXNlICsgdGhlIHNwZWNpZmljIHRlbXBsYXRlIGlkIHRvIHJlbmRlciBwZXIgcHJvZmlsZS4gUHJvZHVjZWQgYnlcbiAqIHtAbGluayByZXNvbHZlUHVzaFRlbXBsYXRlQ29udGV4dH0gYW5kIGNhcnJpZWQgb24gdGhlIGRlbGl2ZXJ5IGRlcHMgc29cbiAqIHtAbGluayByZW5kZXJQcm9maWxlQ2hhbm5lbE1lc3NhZ2VzfSBjYW4gcmVuZGVyIHBlcnNvbmFsaXplZCBjb3B5IHBlciBwcm9maWxlLlxuICovXG5leHBvcnQgdHlwZSBQdXNoVGVtcGxhdGVDb250ZXh0ID0ge1xuICBxY29ubmVjdDogUUNvbm5lY3RDbGllbnQ7XG4gIC8qKiBUaGUgZGlzY292ZXJlZCBRIGluIENvbm5lY3Qga25vd2xlZGdlIGJhc2UgaWQuICovXG4gIGtub3dsZWRnZUJhc2VJZDogc3RyaW5nO1xuICAvKiogVGhlIFBVU0ggbWVzc2FnZSB0ZW1wbGF0ZSBpZCB3aG9zZSBuYW1lIG1hdGNoZWQgdGhlIGpvdXJuZXkgQWN0aW9uSWQuICovXG4gIG1lc3NhZ2VUZW1wbGF0ZUlkOiBzdHJpbmc7XG4gIC8qKiBUaGUgdGVtcGxhdGUgbmFtZSAoPT0gdGhlIEN1c3RvbS1hY3Rpb24gYmxvY2sgbmFtZSAvIEFjdGlvbklkKS4gKi9cbiAgdGVtcGxhdGVOYW1lOiBzdHJpbmc7XG59O1xuXG4vKipcbiAqIFBlci1jb250YWluZXIgY2FjaGUgb2YgYGNhbXBhaWduSWQgLT4ga25vd2xlZGdlQmFzZUlkYC4gS0IgZGlzY292ZXJ5XG4gKiAoRGVzY3JpYmVDYW1wYWlnbiArIExpc3RJbnRlZ3JhdGlvbkFzc29jaWF0aW9ucykgaXMgc3RhYmxlIGZvciBhIGNhbXBhaWduJ3NcbiAqIGxpZmV0aW1lLCBzbyB3YXJtIExhbWJkYSBpbnZvY2F0aW9ucyBza2lwIHRoZSB0d28gbG9va3Vwcy5cbiAqXG4gKiBUT0RPKHByb2QpOiB1bmJvdW5kZWQgKG9uZSBlbnRyeSBwZXIgZGlzdGluY3QgY2FtcGFpZ25JZCBwZXIgY29udGFpbmVyKSDigJQgY2FwXG4gKiBvciBUVEwgdGhpcyBiZWZvcmUgR0EgaWYgYSBzaW5nbGUgY29udGFpbmVyIGZyb250cyBtYW55IGNhbXBhaWducy5cbiAqL1xuY29uc3Qga2JJZEJ5Q2FtcGFpZ24gPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuXG4vKiogVGhlIHNoYXBlIHdlIHJlYWQgb3V0IG9mIGEgUSBDb25uZWN0IFBVU0ggdGVtcGxhdGUgcGxhdGZvcm0gZW50cnkuICovXG50eXBlIFBsYXRmb3JtQ29udGVudCA9IHtcbiAgdGl0bGU/OiBzdHJpbmc7XG4gIGJvZHk/OiB7IGNvbnRlbnQ/OiBzdHJpbmcgfTtcbn07XG5cbi8qKlxuICogRGlzY292ZXIgdGhlIFEgaW4gQ29ubmVjdCBrbm93bGVkZ2UgYmFzZSBiYWNraW5nIGEgY2FtcGFpZ24ncyBDb25uZWN0XG4gKiBpbnN0YW5jZSwgY2FjaGluZyBwZXIgY29udGFpbmVyOlxuICpcbiAqICAgQ2FtcGFpZ25JZCAtPiBjb25uZWN0Y2FtcGFpZ25zdjIgRGVzY3JpYmVDYW1wYWlnbiAtPiBjYW1wYWlnbi5jb25uZWN0SW5zdGFuY2VJZFxuICogICAgICAgICAgICAgIC0+IGNvbm5lY3QgTGlzdEludGVncmF0aW9uQXNzb2NpYXRpb25zKFFfTUVTU0FHRV9URU1QTEFURVMpXG4gKiAgICAgICAgICAgICAgLT4gSW50ZWdyYXRpb25Bcm4gKGFybjphd3M6d2lzZG9tOi4uLjprbm93bGVkZ2UtYmFzZS88a2JJZD4pIC0+IGtiSWRcbiAqXG4gKiBSZXR1cm5zIGB1bmRlZmluZWRgIChuZXZlciB0aHJvd3MpIHdoZW4gdGhlIGluc3RhbmNlIGlkIG9yIHRoZSBLQiBpbnRlZ3JhdGlvblxuICogY2Fubm90IGJlIHJlc29sdmVkIOKAlCB0aGUgY2FsbGVyIHRoZW4gZmFsbHMgYmFjayB0byBub24tdGVtcGxhdGVkIGNvcHkuIElmXG4gKiBEZXNjcmliZUNhbXBhaWduIGRvZXMgbm90IGNhcnJ5IGBjb25uZWN0SW5zdGFuY2VJZGAsIHRoYXQgaXMgbG9nZ2VkIHNvIHRoZVxuICogcmVhbCBzaGFwZSBjYW4gYmUgaW5zcGVjdGVkLlxuICovXG5leHBvcnQgY29uc3QgZGlzY292ZXJLbm93bGVkZ2VCYXNlSWQgPSBhc3luYyAoXG4gIGNsaWVudHM6IFBpY2s8VGVtcGxhdGVDbGllbnRzLCAnY2FtcGFpZ25zJyB8ICdjb25uZWN0Jz4sXG4gIGNhbXBhaWduSWQ6IHN0cmluZyxcbik6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiA9PiB7XG4gIGNvbnN0IGNhY2hlZCA9IGtiSWRCeUNhbXBhaWduLmdldChjYW1wYWlnbklkKTtcbiAgaWYgKGNhY2hlZCkge1xuICAgIHJldHVybiBjYWNoZWQ7XG4gIH1cblxuICBjb25zdCBkZXNjcmliZSA9IGF3YWl0IGNsaWVudHMuY2FtcGFpZ25zLnNlbmQoXG4gICAgbmV3IERlc2NyaWJlQ2FtcGFpZ25Db21tYW5kKHsgaWQ6IGNhbXBhaWduSWQgfSksXG4gICk7XG4gIGNvbnN0IGluc3RhbmNlSWQgPSBkZXNjcmliZS5jYW1wYWlnbj8uY29ubmVjdEluc3RhbmNlSWQ7XG4gIGlmICghaW5zdGFuY2VJZCkge1xuICAgIGNvbnNvbGUud2FybihcbiAgICAgICdbcHVzaF0ga2IuZGlzY292ZXIubm9JbnN0YW5jZUlkJyxcbiAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgY2FtcGFpZ25JZCxcbiAgICAgICAgY2FtcGFpZ25LZXlzOiBPYmplY3Qua2V5cyhkZXNjcmliZS5jYW1wYWlnbiA/PyB7fSksXG4gICAgICB9KSxcbiAgICApO1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBhc3NvYyA9IGF3YWl0IGNsaWVudHMuY29ubmVjdC5zZW5kKFxuICAgIG5ldyBMaXN0SW50ZWdyYXRpb25Bc3NvY2lhdGlvbnNDb21tYW5kKHtcbiAgICAgIEluc3RhbmNlSWQ6IGluc3RhbmNlSWQsXG4gICAgICBJbnRlZ3JhdGlvblR5cGU6IFFfTUVTU0FHRV9URU1QTEFURVNfSU5URUdSQVRJT05fVFlQRSxcbiAgICB9KSxcbiAgKTtcbiAgLy8gQSBDb25uZWN0IGluc3RhbmNlIGhhcyBhdCBtb3N0IG9uZSBRX01FU1NBR0VfVEVNUExBVEVTIGJpbmRpbmcsIHNvIHBhZ2UgMVxuICAvLyBhbHdheXMgY2FycmllcyBpdCBhbmQgd2UgZG9uJ3QgcGFnaW5hdGUuIFN1cmZhY2UgYSBOZXh0VG9rZW4gaWYgdGhhdCBldmVyXG4gIC8vIHN0b3BzIGhvbGRpbmcgc28gdGhlIGVkZ2UgY2FzZSBpcyBvYnNlcnZhYmxlIHJhdGhlciB0aGFuIGEgc2lsZW50IG1pc3MuXG4gIGlmIChhc3NvYy5OZXh0VG9rZW4pIHtcbiAgICBjb25zb2xlLndhcm4oXG4gICAgICAnW3B1c2hdIGtiLmRpc2NvdmVyLm11bHRpcGxlUGFnZXMnLFxuICAgICAgSlNPTi5zdHJpbmdpZnkoeyBjYW1wYWlnbklkLCBpbnN0YW5jZUlkIH0pLFxuICAgICk7XG4gIH1cbiAgY29uc3QgaW50ZWdyYXRpb25Bcm4gPSBhc3NvYy5JbnRlZ3JhdGlvbkFzc29jaWF0aW9uU3VtbWFyeUxpc3Q/LmZpbmQoXG4gICAgKGEpID0+IGEuSW50ZWdyYXRpb25Bcm4sXG4gICk/LkludGVncmF0aW9uQXJuO1xuICAvLyBPbmx5IHRydXN0IGEgd2VsbC1mb3JtZWQgUSBpbiBDb25uZWN0IGtub3dsZWRnZS1iYXNlIEFSTlxuICAvLyAoYXJuOmF3czp3aXNkb206Li4uOmtub3dsZWRnZS1iYXNlLzxrYklkPik7IGFueXRoaW5nIGVsc2UgeWllbGRzIGEgZ2FyYmFnZVxuICAvLyBpZCB0aGF0IHdvdWxkIGZhaWwgdGhyZWUgY2FsbHMgbGF0ZXIgYXQgcmVuZGVyIHRpbWUuXG4gIGNvbnN0IGtiSWQgPSBpbnRlZ3JhdGlvbkFybj8uaW5jbHVkZXMoJ2tub3dsZWRnZS1iYXNlLycpXG4gICAgPyBpbnRlZ3JhdGlvbkFybi5zcGxpdCgnLycpLnBvcCgpXG4gICAgOiB1bmRlZmluZWQ7XG5cbiAgaWYgKCFrYklkKSB7XG4gICAgY29uc29sZS53YXJuKFxuICAgICAgJ1twdXNoXSBrYi5kaXNjb3Zlci5ub0tub3dsZWRnZUJhc2UnLFxuICAgICAgSlNPTi5zdHJpbmdpZnkoeyBjYW1wYWlnbklkLCBpbnN0YW5jZUlkLCBpbnRlZ3JhdGlvbkFybiB9KSxcbiAgICApO1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zb2xlLmxvZyhcbiAgICAnW3B1c2hdIGtiLmRpc2NvdmVyJyxcbiAgICBKU09OLnN0cmluZ2lmeSh7IGNhbXBhaWduSWQsIGluc3RhbmNlSWQsIGtub3dsZWRnZUJhc2VJZDoga2JJZCB9KSxcbiAgKTtcbiAga2JJZEJ5Q2FtcGFpZ24uc2V0KGNhbXBhaWduSWQsIGtiSWQpO1xuICByZXR1cm4ga2JJZDtcbn07XG5cbi8qKlxuICogRmluZCB0aGUgUFVTSCBtZXNzYWdlIHRlbXBsYXRlIGluIGBrbm93bGVkZ2VCYXNlSWRgIHdob3NlIG5hbWUgZXF1YWxzIHRoZVxuICogam91cm5leSBgYWN0aW9uSWRgICh0aGUgQ3VzdG9tLWFjdGlvbiBibG9jayBuYW1lKS4gUGFnZXMgTGlzdE1lc3NhZ2VUZW1wbGF0ZXNcbiAqIGFuZCBmaWx0ZXJzIGNsaWVudC1zaWRlIHRvIGBjaGFubmVsU3VidHlwZSA9PT0gUFVTSGAuIFJldHVybnMgdGhlIG1hdGNoaW5nXG4gKiB0ZW1wbGF0ZSBpZCwgb3IgYHVuZGVmaW5lZGAgd2hlbiBub25lIG1hdGNoZXMuXG4gKi9cbmNvbnN0IGZpbmRQdXNoVGVtcGxhdGVJZCA9IGFzeW5jIChcbiAgcWNvbm5lY3Q6IFFDb25uZWN0Q2xpZW50LFxuICBrbm93bGVkZ2VCYXNlSWQ6IHN0cmluZyxcbiAgYWN0aW9uSWQ6IHN0cmluZyxcbik6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiA9PiB7XG4gIGxldCBuZXh0VG9rZW46IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgZG8ge1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHFjb25uZWN0LnNlbmQoXG4gICAgICBuZXcgTGlzdE1lc3NhZ2VUZW1wbGF0ZXNDb21tYW5kKHtcbiAgICAgICAga25vd2xlZGdlQmFzZUlkLFxuICAgICAgICBtYXhSZXN1bHRzOiAxMDAsXG4gICAgICAgIG5leHRUb2tlbixcbiAgICAgIH0pLFxuICAgICk7XG4gICAgY29uc3QgbWF0Y2ggPSByZXMubWVzc2FnZVRlbXBsYXRlU3VtbWFyaWVzPy5maW5kKFxuICAgICAgKHMpID0+IHMuY2hhbm5lbFN1YnR5cGUgPT09IFBVU0hfQ0hBTk5FTF9TVUJUWVBFICYmIHMubmFtZSA9PT0gYWN0aW9uSWQsXG4gICAgKTtcbiAgICBpZiAobWF0Y2g/Lm1lc3NhZ2VUZW1wbGF0ZUlkKSB7XG4gICAgICByZXR1cm4gbWF0Y2gubWVzc2FnZVRlbXBsYXRlSWQ7XG4gICAgfVxuICAgIG5leHRUb2tlbiA9IHJlcy5uZXh0VG9rZW47XG4gIH0gd2hpbGUgKG5leHRUb2tlbik7XG4gIHJldHVybiB1bmRlZmluZWQ7XG59O1xuXG4vKipcbiAqIFJlc29sdmUgdGhlIFBVU0ggbWVzc2FnZSB0ZW1wbGF0ZSBmb3IgYSBqb3VybmV5IHJ1bjogZGlzY292ZXIgdGhlIGtub3dsZWRnZVxuICogYmFzZSBmcm9tIHRoZSBjYW1wYWlnbiwgZmluZCB0aGUgUFVTSCB0ZW1wbGF0ZSB3aG9zZSBuYW1lID09IHRoZSBBY3Rpb25JZCxcbiAqIGFuZCBjb25maXJtIGl0IGhhcyBhbiBBQ1RJVkUgdmVyc2lvbi4gUmV0dXJucyBgdW5kZWZpbmVkYCAobmV2ZXIgdGhyb3dzKSB3aGVuXG4gKiBhbnl0aGluZyBpcyBtaXNzaW5nIOKAlCBubyBjYW1wYWlnbiBtZXRhZGF0YSwgbm8gS0IgaW50ZWdyYXRpb24sIG5vIG1hdGNoaW5nXG4gKiB0ZW1wbGF0ZSDigJQgc28gdGhlIGNhbGxlciBmYWxscyBiYWNrIHRvIHRoZSBub24tdGVtcGxhdGVkIHBlci1wcm9maWxlIGNvcHkuXG4gKi9cbmV4cG9ydCBjb25zdCByZXNvbHZlUHVzaFRlbXBsYXRlQ29udGV4dCA9IGFzeW5jIChcbiAgY2xpZW50czogVGVtcGxhdGVDbGllbnRzLFxuICBjYW1wYWlnbjogQ2FtcGFpZ25Db250ZXh0LFxuKTogUHJvbWlzZTxQdXNoVGVtcGxhdGVDb250ZXh0IHwgdW5kZWZpbmVkPiA9PiB7XG4gIGNvbnN0IGNhbXBhaWduSWQgPSBjYW1wYWlnbi5jYW1wYWlnbklkO1xuICBjb25zdCBhY3Rpb25JZCA9IGNhbXBhaWduLmFjdGlvbklkO1xuICBpZiAoIWNhbXBhaWduSWQgfHwgIWFjdGlvbklkKSB7XG4gICAgY29uc29sZS5sb2coXG4gICAgICAnW3B1c2hdIHRlbXBsYXRlLnNraXAnLFxuICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICByZWFzb246ICdtaXNzaW5nIGNhbXBhaWduSWQgb3IgYWN0aW9uSWQnLFxuICAgICAgICBjYW1wYWlnbklkOiBjYW1wYWlnbklkID8/IG51bGwsXG4gICAgICAgIGFjdGlvbklkOiBhY3Rpb25JZCA/PyBudWxsLFxuICAgICAgfSksXG4gICAgKTtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBrbm93bGVkZ2VCYXNlSWQgPSBhd2FpdCBkaXNjb3Zlcktub3dsZWRnZUJhc2VJZChjbGllbnRzLCBjYW1wYWlnbklkKTtcbiAgICBpZiAoIWtub3dsZWRnZUJhc2VJZCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBjb25zdCBtZXNzYWdlVGVtcGxhdGVJZCA9IGF3YWl0IGZpbmRQdXNoVGVtcGxhdGVJZChcbiAgICAgIGNsaWVudHMucWNvbm5lY3QsXG4gICAgICBrbm93bGVkZ2VCYXNlSWQsXG4gICAgICBhY3Rpb25JZCxcbiAgICApO1xuICAgIGlmICghbWVzc2FnZVRlbXBsYXRlSWQpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgJ1twdXNoXSB0ZW1wbGF0ZS5ub01hdGNoJyxcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoeyBrbm93bGVkZ2VCYXNlSWQsIGFjdGlvbklkIH0pLFxuICAgICAgKTtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLy8gQ29uZmlybSBhbiBBQ1RJVkUgKHB1Ymxpc2hlZCkgdmVyc2lvbiBleGlzdHM7IGlmIG5vdCwgc3RpbGwgcmVuZGVyIHRoZVxuICAgIC8vIGxhdGVzdCBjb250ZW50IChHZXRNZXNzYWdlVGVtcGxhdGUgaXMgZGlhZ25vc3RpYyBoZXJlLCBub3QgYSBnYXRlKS5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgY2xpZW50cy5xY29ubmVjdC5zZW5kKFxuICAgICAgICBuZXcgR2V0TWVzc2FnZVRlbXBsYXRlQ29tbWFuZCh7XG4gICAgICAgICAga25vd2xlZGdlQmFzZUlkLFxuICAgICAgICAgIG1lc3NhZ2VUZW1wbGF0ZUlkOiBgJHttZXNzYWdlVGVtcGxhdGVJZH06JHtBQ1RJVkVfVkVSU0lPTl9RVUFMSUZJRVJ9YCxcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAnW3B1c2hdIHRlbXBsYXRlLm5vQWN0aXZlVmVyc2lvbicsXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICBrbm93bGVkZ2VCYXNlSWQsXG4gICAgICAgICAgbWVzc2FnZVRlbXBsYXRlSWQsXG4gICAgICAgICAgZXJyb3I6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiAndW5rbm93bicsXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zb2xlLmxvZyhcbiAgICAgICdbcHVzaF0gdGVtcGxhdGUucmVzb2x2ZWQnLFxuICAgICAgSlNPTi5zdHJpbmdpZnkoeyBrbm93bGVkZ2VCYXNlSWQsIG1lc3NhZ2VUZW1wbGF0ZUlkLCBhY3Rpb25JZCB9KSxcbiAgICApO1xuICAgIHJldHVybiB7XG4gICAgICBxY29ubmVjdDogY2xpZW50cy5xY29ubmVjdCxcbiAgICAgIGtub3dsZWRnZUJhc2VJZCxcbiAgICAgIG1lc3NhZ2VUZW1wbGF0ZUlkLFxuICAgICAgdGVtcGxhdGVOYW1lOiBhY3Rpb25JZCxcbiAgICB9O1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBjb25zb2xlLndhcm4oXG4gICAgICAnW3B1c2hdIHRlbXBsYXRlLnJlc29sdmVFcnJvcicsXG4gICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIGNhbXBhaWduSWQsXG4gICAgICAgIGFjdGlvbklkLFxuICAgICAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6ICd1bmtub3duJyxcbiAgICAgIH0pLFxuICAgICk7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufTtcblxuLyoqXG4gKiBGbGF0dGVuIGEgcHJvZmlsZSdzIGBDdXN0b21lckRhdGFgIGludG8gYSBmbGF0IGBjdXN0b21BdHRyaWJ1dGVzYCBtYXAgZm9yXG4gKiBSZW5kZXJNZXNzYWdlVGVtcGxhdGUuIEVtcGlyaWNhbGx5IG9ubHkgYHt7QXR0cmlidXRlcy48ZmxhdEtleT59fWAgdmFyaWFibGVzXG4gKiBpbnRlcnBvbGF0ZSAoZnJvbSBgY3VzdG9tQXR0cmlidXRlc2ApOyB0aGUgYHt7Q3VzdG9tZXIuKn19YCBuYW1lc3BhY2UgZG9lcyBub3RcbiAqIHJlc29sdmUgaGVyZSDigJQgc28gdGhlIHByb2ZpbGUncyBgZmlyc3ROYW1lYCBhbmQgZXZlcnkgYGF0dHJpYnV0ZXMuKmAgZW50cnkgYXJlXG4gKiBwYXNzZWQgYXMgZmxhdCBjdXN0b20gYXR0cmlidXRlcyAodGVtcGxhdGVzIHJlZmVyZW5jZSBlLmcuXG4gKiBge3tBdHRyaWJ1dGVzLmZpcnN0TmFtZX19YCkuIE5lc3RlZCBvYmplY3RzIChgYWRkcmVzc2AsIGBhdHRyaWJ1dGVzYCkgYXJlIG5vdFxuICogYWRkZWQgZGlyZWN0bHk7IGBhdHRyaWJ1dGVzYCBpcyBtZXJnZWQgb25lIGxldmVsIGRlZXAuIE5vbi1zdHJpbmcgLyBlbXB0eVxuICogdmFsdWVzIGFyZSBkcm9wcGVkIGFuZCB2YWx1ZXMgYXJlIGNhcHBlZCBhdCB0aGUgcmVuZGVyIGF0dHJpYnV0ZS1sZW5ndGggbGltaXQuXG4gKi9cbmV4cG9ydCBjb25zdCBidWlsZEN1c3RvbUF0dHJpYnV0ZXMgPSAoXG4gIGN1c3RvbWVyRGF0YT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9PiB7XG4gIGNvbnN0IG91dDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICBpZiAoIWN1c3RvbWVyRGF0YSkge1xuICAgIHJldHVybiBvdXQ7XG4gIH1cbiAgY29uc3QgYWRkID0gKGtleTogc3RyaW5nLCB2YWx1ZTogdW5rbm93bik6IHZvaWQgPT4ge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIHZhbHVlLmxlbmd0aCA+IDApIHtcbiAgICAgIG91dFtrZXldID0gdmFsdWUuc2xpY2UoMCwgTUFYX0FUVFJJQlVURV9MRU5HVEgpO1xuICAgIH1cbiAgfTtcbiAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoY3VzdG9tZXJEYXRhKSkge1xuICAgIGlmIChrZXkgPT09ICdhdHRyaWJ1dGVzJyB8fCBrZXkgPT09ICdhZGRyZXNzJykge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGFkZChrZXksIHZhbHVlKTtcbiAgfVxuICBjb25zdCBhdHRyaWJ1dGVzID0gY3VzdG9tZXJEYXRhLmF0dHJpYnV0ZXM7XG4gIGlmIChcbiAgICBhdHRyaWJ1dGVzICYmXG4gICAgdHlwZW9mIGF0dHJpYnV0ZXMgPT09ICdvYmplY3QnICYmXG4gICAgIUFycmF5LmlzQXJyYXkoYXR0cmlidXRlcylcbiAgKSB7XG4gICAgLy8gYXR0cmlidXRlcyBzdWIta2V5cyBvdmVyd3JpdGUgdG9wLWxldmVsIGtleXMgb24gY29sbGlzaW9uIChhdHRyaWJ1dGVzIGlzXG4gICAgLy8gdGhlIGF1dGhvcml0YXRpdmUgY3VzdG9tLWF0dHJpYnV0ZSBzdG9yZSkuXG4gICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoXG4gICAgICBhdHRyaWJ1dGVzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICAgICkpIHtcbiAgICAgIGFkZChrZXksIHZhbHVlKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG91dDtcbn07XG5cbi8qKlxuICogRGV0ZWN0cyBhIEhhbmRsZWJhcnMgcGxhY2Vob2xkZXIgdGhlIHJlbmRlcmVyIGxlZnQgdW5yZXNvbHZlZCwgZS5nLiBhXG4gKiBge3tBdHRyaWJ1dGVzLmZpcnN0TmFtZX19YCB2YXIgZm9yIGEgcHJvZmlsZSB0aGF0IGhhcyBubyBgZmlyc3ROYW1lYC4gUSBDb25uZWN0XG4gKiBsZWF2ZXMgc3VjaCB2YXJzIExJVEVSQUwgaW4gdGhlIG91dHB1dCAoYW5kIGxpc3RzIHRoZW0gaW5cbiAqIGBhdHRyaWJ1dGVzTm90SW50ZXJwb2xhdGVkYCk7IHNoaXBwaW5nIHRoYXQgcmF3IHRleHQgdG8gYSBkZXZpY2UgaXMgYSBidWcsIHNvXG4gKiBjb3B5IHRoYXQgc3RpbGwgY29udGFpbnMgb25lIGlzIHJlamVjdGVkIGFuZCB0aGUgY2FsbGVyIGZhbGxzIGJhY2sgdG8gZGVmYXVsdC5cbiAqL1xuY29uc3QgaGFzVW5yZXNvbHZlZFBsYWNlaG9sZGVyID0gKHZhbHVlOiBzdHJpbmcpOiBib29sZWFuID0+XG4gIC9cXHtcXHsuKj9cXH1cXH0vLnRlc3QodmFsdWUpO1xuXG5jb25zdCB0b01lc3NhZ2UgPSAoY29udGVudD86IFBsYXRmb3JtQ29udGVudCk6IFB1c2hNZXNzYWdlIHwgdW5kZWZpbmVkID0+IHtcbiAgY29uc3QgdGl0bGUgPSBjb250ZW50Py50aXRsZTtcbiAgY29uc3QgYm9keSA9IGNvbnRlbnQ/LmJvZHk/LmNvbnRlbnQ7XG4gIGlmIChcbiAgICB0eXBlb2YgdGl0bGUgPT09ICdzdHJpbmcnICYmXG4gICAgdGl0bGUubGVuZ3RoID4gMCAmJlxuICAgIHR5cGVvZiBib2R5ID09PSAnc3RyaW5nJyAmJlxuICAgIGJvZHkubGVuZ3RoID4gMCAmJlxuICAgICFoYXNVbnJlc29sdmVkUGxhY2Vob2xkZXIodGl0bGUpICYmXG4gICAgIWhhc1VucmVzb2x2ZWRQbGFjZWhvbGRlcihib2R5KVxuICApIHtcbiAgICByZXR1cm4geyB0aXRsZSwgYm9keSB9O1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59O1xuXG4vKipcbiAqIFJlbmRlciB0aGUgcmVzb2x2ZWQgUFVTSCB0ZW1wbGF0ZSBmb3IgT05FIHByb2ZpbGUgYW5kIG1hcCB0aGUgcGVyLXBsYXRmb3JtXG4gKiBjb3B5IHRvIHB1c2ggY2hhbm5lbHM6XG4gKiAgIC0gYHB1c2guYXBuc2AgLT4gYEFQTlNgICgrIGBBUE5TX1NBTkRCT1hgKVxuICogICAtIGBwdXNoLmZjbWAgIC0+IGBHQ01gXG4gKlxuICogVGhlIHByb2ZpbGUncyBgQ3VzdG9tZXJEYXRhYCBpcyBwYXNzZWQgYXMgZmxhdCBgY3VzdG9tQXR0cmlidXRlc2Agc29cbiAqIGB7e0F0dHJpYnV0ZXMuPGtleT59fWAgdmFyaWFibGVzIHBlcnNvbmFsaXplLiBSZXR1cm5zIGEgcGFydGlhbCBwZXItY2hhbm5lbFxuICogbWFwIChvbmx5IGNoYW5uZWxzIHRoZSB0ZW1wbGF0ZSBkZWZpbmVzIGJvdGggYSB0aXRsZSBhbmQgYm9keSBmb3IpLCBvclxuICogYHVuZGVmaW5lZGAgKG5ldmVyIHRocm93cykgd2hlbiB0aGVyZSBpcyBubyBwdXNoIGNvbnRlbnQgb3IgdGhlIHJlbmRlciBmYWlscyDigJRcbiAqIHRoZSBjYWxsZXIgdGhlbiBmYWxscyBiYWNrIHRvIHRoZSBub24tdGVtcGxhdGVkIGNvcHkgZm9yIHRoYXQgcHJvZmlsZS5cbiAqL1xuZXhwb3J0IGNvbnN0IHJlbmRlclByb2ZpbGVDaGFubmVsTWVzc2FnZXMgPSBhc3luYyAoXG4gIGN0eDogUHVzaFRlbXBsYXRlQ29udGV4dCxcbiAgdGFyZ2V0OiBQcm9maWxlVGFyZ2V0LFxuKTogUHJvbWlzZTxQYXJ0aWFsPFJlY29yZDxQdXNoQ2hhbm5lbFR5cGUsIFB1c2hNZXNzYWdlPj4gfCB1bmRlZmluZWQ+ID0+IHtcbiAgY29uc3QgY3VzdG9tQXR0cmlidXRlcyA9IGJ1aWxkQ3VzdG9tQXR0cmlidXRlcyh0YXJnZXQuY3VzdG9tZXJEYXRhKTtcblxuICBsZXQgcmVzO1xuICB0cnkge1xuICAgIHJlcyA9IGF3YWl0IGN0eC5xY29ubmVjdC5zZW5kKFxuICAgICAgbmV3IFJlbmRlck1lc3NhZ2VUZW1wbGF0ZUNvbW1hbmQoe1xuICAgICAgICBrbm93bGVkZ2VCYXNlSWQ6IGN0eC5rbm93bGVkZ2VCYXNlSWQsXG4gICAgICAgIC8vIFJlbmRlciB0aGUgUFVCTElTSEVEIHZlcnNpb24gZXhwbGljaXRseSAodmVyaWZpZWQ6IFJlbmRlck1lc3NhZ2VUZW1wbGF0ZVxuICAgICAgICAvLyBhY2NlcHRzIHRoZSBgOiRBQ1RJVkVfVkVSU0lPTmAgcXVhbGlmaWVyKSBzbyBhIGxhdGVyIHNhdmVkIGRyYWZ0IGNhbid0XG4gICAgICAgIC8vIHNpbGVudGx5IGNoYW5nZSBwcm9kdWN0aW9uIGNvcHkuXG4gICAgICAgIG1lc3NhZ2VUZW1wbGF0ZUlkOiBgJHtjdHgubWVzc2FnZVRlbXBsYXRlSWR9OiR7QUNUSVZFX1ZFUlNJT05fUVVBTElGSUVSfWAsXG4gICAgICAgIGF0dHJpYnV0ZXM6IHsgY3VzdG9tQXR0cmlidXRlcyB9LFxuICAgICAgfSksXG4gICAgKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgY29uc29sZS53YXJuKFxuICAgICAgJ1twdXNoXSB0ZW1wbGF0ZS5yZW5kZXJFcnJvcicsXG4gICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIHRlbXBsYXRlTmFtZTogY3R4LnRlbXBsYXRlTmFtZSxcbiAgICAgICAgZXJyb3I6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiAndW5rbm93bicsXG4gICAgICB9KSxcbiAgICApO1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBjb250ZW50ID0gcmVzLmNvbnRlbnQgYXNcbiAgICB8IHsgcHVzaD86IHsgYXBucz86IFBsYXRmb3JtQ29udGVudDsgZmNtPzogUGxhdGZvcm1Db250ZW50IH0gfVxuICAgIHwgdW5kZWZpbmVkO1xuICBjb25zdCBwdXNoID0gY29udGVudD8ucHVzaDtcbiAgaWYgKCFwdXNoKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGNvbnN0IGFwbnMgPSB0b01lc3NhZ2UocHVzaC5hcG5zKTtcbiAgY29uc3QgZmNtID0gdG9NZXNzYWdlKHB1c2guZmNtKTtcbiAgY29uc3QgcGVyQ2hhbm5lbDogUGFydGlhbDxSZWNvcmQ8UHVzaENoYW5uZWxUeXBlLCBQdXNoTWVzc2FnZT4+ID0ge307XG4gIGlmIChhcG5zKSB7XG4gICAgcGVyQ2hhbm5lbC5BUE5TID0gYXBucztcbiAgICBwZXJDaGFubmVsLkFQTlNfU0FOREJPWCA9IGFwbnM7XG4gIH1cbiAgaWYgKGZjbSkge1xuICAgIHBlckNoYW5uZWwuR0NNID0gZmNtO1xuICB9XG5cbiAgLy8gT3BlcmF0aW9uYWwgc2lnbmFsIG9ubHk6IHdoaWNoIGNoYW5uZWxzIHRoZSB0ZW1wbGF0ZSByZW5kZXJlZCB1c2FibGUgY29weVxuICAvLyBmb3IsIHBsdXMgYW55IHRlbXBsYXRlIHZhcmlhYmxlcyB0aGUgcmVuZGVyZXIgbGVmdCB1bi1pbnRlcnBvbGF0ZWQgKHRoZXNlXG4gIC8vIGFyZSB0ZW1wbGF0ZS1hdXRob3ItZGVmaW5lZCB2YXJpYWJsZSBuYW1lcywgZS5nLiBgQXR0cmlidXRlcy5maXJzdE5hbWVgLFxuICAvLyBub3QgY3VzdG9tZXIgdmFsdWVzKS4gVGhlIHJlbmRlcmVkIHRpdGxlL2JvZHkgYXJlIG5ldmVyIGxvZ2dlZC5cbiAgY29uc29sZS5sb2coXG4gICAgJ1twdXNoXSB0ZW1wbGF0ZS5yZW5kZXInLFxuICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgIHRlbXBsYXRlTmFtZTogY3R4LnRlbXBsYXRlTmFtZSxcbiAgICAgIGFwbnNSZW5kZXJlZDogQm9vbGVhbihhcG5zKSxcbiAgICAgIGdjbVJlbmRlcmVkOiBCb29sZWFuKGZjbSksXG4gICAgICBhdHRyaWJ1dGVzTm90SW50ZXJwb2xhdGVkOiByZXMuYXR0cmlidXRlc05vdEludGVycG9sYXRlZCA/PyBbXSxcbiAgICB9KSxcbiAgKTtcblxuICByZXR1cm4gT2JqZWN0LmtleXMocGVyQ2hhbm5lbCkubGVuZ3RoID4gMCA/IHBlckNoYW5uZWwgOiB1bmRlZmluZWQ7XG59O1xuIl19
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { DirectMessageConfiguration } from '@aws-sdk/client-pinpoint';
|
|
2
|
+
import { PushChannelType, PushMessage } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Normalize a stored / event channel identifier to a Pinpoint push channel.
|
|
5
|
+
*
|
|
6
|
+
* The identify path stores whatever channel the client registered. Clients (and
|
|
7
|
+
* Firebase) use several spellings for Android push — `FCM` (the current Firebase
|
|
8
|
+
* Cloud Messaging name) is normalized to `GCM` (the Pinpoint channel that
|
|
9
|
+
* fronts FCM). Apple variants map to `APNS` / `APNS_SANDBOX`. Anything else
|
|
10
|
+
* (e.g. `IN_APP`, empty, unknown) yields `undefined` so the caller skips it.
|
|
11
|
+
*/
|
|
12
|
+
export declare const normalizeChannelType: (raw: string | undefined) => PushChannelType | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Build the Pinpoint `DirectMessageConfiguration` for a single device, carrying
|
|
15
|
+
* only the platform message matching that device's channel.
|
|
16
|
+
*
|
|
17
|
+
* - `GCM` -> `GCMMessage` (Android / FCM)
|
|
18
|
+
* - `APNS` / `APNS_SANDBOX` -> `APNSMessage` (iOS)
|
|
19
|
+
*
|
|
20
|
+
* `title` / `body` map to the platform message's `Title` / `Body`; optional
|
|
21
|
+
* `data` maps to the platform `Data` map so the client receives the custom
|
|
22
|
+
* payload alongside the notification.
|
|
23
|
+
*/
|
|
24
|
+
export declare const buildMessageConfiguration: (channelType: PushChannelType, message: PushMessage) => DirectMessageConfiguration;
|
|
25
|
+
//# sourceMappingURL=payload.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Normalize a stored / event channel identifier to a Pinpoint push channel.
|
|
5
|
+
*
|
|
6
|
+
* The identify path stores whatever channel the client registered. Clients (and
|
|
7
|
+
* Firebase) use several spellings for Android push — `FCM` (the current Firebase
|
|
8
|
+
* Cloud Messaging name) is normalized to `GCM` (the Pinpoint channel that
|
|
9
|
+
* fronts FCM). Apple variants map to `APNS` / `APNS_SANDBOX`. Anything else
|
|
10
|
+
* (e.g. `IN_APP`, empty, unknown) yields `undefined` so the caller skips it.
|
|
11
|
+
*/
|
|
12
|
+
export const normalizeChannelType = (raw) => {
|
|
13
|
+
if (!raw) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
switch (raw.trim().toUpperCase()) {
|
|
17
|
+
case 'FCM':
|
|
18
|
+
case 'GCM':
|
|
19
|
+
return 'GCM';
|
|
20
|
+
case 'APNS':
|
|
21
|
+
return 'APNS';
|
|
22
|
+
case 'APNS_SANDBOX':
|
|
23
|
+
case 'APNSSANDBOX':
|
|
24
|
+
return 'APNS_SANDBOX';
|
|
25
|
+
default:
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Build the Pinpoint `DirectMessageConfiguration` for a single device, carrying
|
|
31
|
+
* only the platform message matching that device's channel.
|
|
32
|
+
*
|
|
33
|
+
* - `GCM` -> `GCMMessage` (Android / FCM)
|
|
34
|
+
* - `APNS` / `APNS_SANDBOX` -> `APNSMessage` (iOS)
|
|
35
|
+
*
|
|
36
|
+
* `title` / `body` map to the platform message's `Title` / `Body`; optional
|
|
37
|
+
* `data` maps to the platform `Data` map so the client receives the custom
|
|
38
|
+
* payload alongside the notification.
|
|
39
|
+
*/
|
|
40
|
+
export const buildMessageConfiguration = (channelType, message) => {
|
|
41
|
+
const common = {
|
|
42
|
+
Title: message.title,
|
|
43
|
+
Body: message.body,
|
|
44
|
+
...(message.data ? { Data: message.data } : {}),
|
|
45
|
+
};
|
|
46
|
+
if (channelType === 'GCM') {
|
|
47
|
+
return { GCMMessage: { ...common, Priority: 'high' } };
|
|
48
|
+
}
|
|
49
|
+
// APNS and APNS_SANDBOX both use APNSMessage; the channel is selected per
|
|
50
|
+
// address via AddressConfiguration.ChannelType.
|
|
51
|
+
return { APNSMessage: common };
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF5bG9hZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYW1iZGEvcHVzaC9wYXlsb2FkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHFFQUFxRTtBQUNyRSxzQ0FBc0M7QUFLdEM7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxDQUNsQyxHQUF1QixFQUNNLEVBQUU7SUFDL0IsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ1QsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUNELFFBQVEsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUM7UUFDakMsS0FBSyxLQUFLLENBQUM7UUFDWCxLQUFLLEtBQUs7WUFDUixPQUFPLEtBQUssQ0FBQztRQUNmLEtBQUssTUFBTTtZQUNULE9BQU8sTUFBTSxDQUFDO1FBQ2hCLEtBQUssY0FBYyxDQUFDO1FBQ3BCLEtBQUssYUFBYTtZQUNoQixPQUFPLGNBQWMsQ0FBQztRQUN4QjtZQUNFLE9BQU8sU0FBUyxDQUFDO0lBQ3JCLENBQUM7QUFDSCxDQUFDLENBQUM7QUFFRjs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQUcsQ0FDdkMsV0FBNEIsRUFDNUIsT0FBb0IsRUFDUSxFQUFFO0lBQzlCLE1BQU0sTUFBTSxHQUFHO1FBQ2IsS0FBSyxFQUFFLE9BQU8sQ0FBQyxLQUFLO1FBQ3BCLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtRQUNsQixHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7S0FDaEQsQ0FBQztJQUVGLElBQUksV0FBVyxLQUFLLEtBQUssRUFBRSxDQUFDO1FBQzFCLE9BQU8sRUFBRSxVQUFVLEVBQUUsRUFBRSxHQUFHLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQztJQUN6RCxDQUFDO0lBQ0QsMEVBQTBFO0lBQzFFLGdEQUFnRDtJQUNoRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxDQUFDO0FBQ2pDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHR5cGUgeyBEaXJlY3RNZXNzYWdlQ29uZmlndXJhdGlvbiB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1waW5wb2ludCc7XG5pbXBvcnQgeyBQdXNoQ2hhbm5lbFR5cGUsIFB1c2hNZXNzYWdlIH0gZnJvbSAnLi90eXBlcy5qcyc7XG5cbi8qKlxuICogTm9ybWFsaXplIGEgc3RvcmVkIC8gZXZlbnQgY2hhbm5lbCBpZGVudGlmaWVyIHRvIGEgUGlucG9pbnQgcHVzaCBjaGFubmVsLlxuICpcbiAqIFRoZSBpZGVudGlmeSBwYXRoIHN0b3JlcyB3aGF0ZXZlciBjaGFubmVsIHRoZSBjbGllbnQgcmVnaXN0ZXJlZC4gQ2xpZW50cyAoYW5kXG4gKiBGaXJlYmFzZSkgdXNlIHNldmVyYWwgc3BlbGxpbmdzIGZvciBBbmRyb2lkIHB1c2gg4oCUIGBGQ01gICh0aGUgY3VycmVudCBGaXJlYmFzZVxuICogQ2xvdWQgTWVzc2FnaW5nIG5hbWUpIGlzIG5vcm1hbGl6ZWQgdG8gYEdDTWAgKHRoZSBQaW5wb2ludCBjaGFubmVsIHRoYXRcbiAqIGZyb250cyBGQ00pLiBBcHBsZSB2YXJpYW50cyBtYXAgdG8gYEFQTlNgIC8gYEFQTlNfU0FOREJPWGAuIEFueXRoaW5nIGVsc2VcbiAqIChlLmcuIGBJTl9BUFBgLCBlbXB0eSwgdW5rbm93bikgeWllbGRzIGB1bmRlZmluZWRgIHNvIHRoZSBjYWxsZXIgc2tpcHMgaXQuXG4gKi9cbmV4cG9ydCBjb25zdCBub3JtYWxpemVDaGFubmVsVHlwZSA9IChcbiAgcmF3OiBzdHJpbmcgfCB1bmRlZmluZWQsXG4pOiBQdXNoQ2hhbm5lbFR5cGUgfCB1bmRlZmluZWQgPT4ge1xuICBpZiAoIXJhdykge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgc3dpdGNoIChyYXcudHJpbSgpLnRvVXBwZXJDYXNlKCkpIHtcbiAgICBjYXNlICdGQ00nOlxuICAgIGNhc2UgJ0dDTSc6XG4gICAgICByZXR1cm4gJ0dDTSc7XG4gICAgY2FzZSAnQVBOUyc6XG4gICAgICByZXR1cm4gJ0FQTlMnO1xuICAgIGNhc2UgJ0FQTlNfU0FOREJPWCc6XG4gICAgY2FzZSAnQVBOU1NBTkRCT1gnOlxuICAgICAgcmV0dXJuICdBUE5TX1NBTkRCT1gnO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59O1xuXG4vKipcbiAqIEJ1aWxkIHRoZSBQaW5wb2ludCBgRGlyZWN0TWVzc2FnZUNvbmZpZ3VyYXRpb25gIGZvciBhIHNpbmdsZSBkZXZpY2UsIGNhcnJ5aW5nXG4gKiBvbmx5IHRoZSBwbGF0Zm9ybSBtZXNzYWdlIG1hdGNoaW5nIHRoYXQgZGV2aWNlJ3MgY2hhbm5lbC5cbiAqXG4gKiAtIGBHQ01gIC0+IGBHQ01NZXNzYWdlYCAoQW5kcm9pZCAvIEZDTSlcbiAqIC0gYEFQTlNgIC8gYEFQTlNfU0FOREJPWGAgLT4gYEFQTlNNZXNzYWdlYCAoaU9TKVxuICpcbiAqIGB0aXRsZWAgLyBgYm9keWAgbWFwIHRvIHRoZSBwbGF0Zm9ybSBtZXNzYWdlJ3MgYFRpdGxlYCAvIGBCb2R5YDsgb3B0aW9uYWxcbiAqIGBkYXRhYCBtYXBzIHRvIHRoZSBwbGF0Zm9ybSBgRGF0YWAgbWFwIHNvIHRoZSBjbGllbnQgcmVjZWl2ZXMgdGhlIGN1c3RvbVxuICogcGF5bG9hZCBhbG9uZ3NpZGUgdGhlIG5vdGlmaWNhdGlvbi5cbiAqL1xuZXhwb3J0IGNvbnN0IGJ1aWxkTWVzc2FnZUNvbmZpZ3VyYXRpb24gPSAoXG4gIGNoYW5uZWxUeXBlOiBQdXNoQ2hhbm5lbFR5cGUsXG4gIG1lc3NhZ2U6IFB1c2hNZXNzYWdlLFxuKTogRGlyZWN0TWVzc2FnZUNvbmZpZ3VyYXRpb24gPT4ge1xuICBjb25zdCBjb21tb24gPSB7XG4gICAgVGl0bGU6IG1lc3NhZ2UudGl0bGUsXG4gICAgQm9keTogbWVzc2FnZS5ib2R5LFxuICAgIC4uLihtZXNzYWdlLmRhdGEgPyB7IERhdGE6IG1lc3NhZ2UuZGF0YSB9IDoge30pLFxuICB9O1xuXG4gIGlmIChjaGFubmVsVHlwZSA9PT0gJ0dDTScpIHtcbiAgICByZXR1cm4geyBHQ01NZXNzYWdlOiB7IC4uLmNvbW1vbiwgUHJpb3JpdHk6ICdoaWdoJyB9IH07XG4gIH1cbiAgLy8gQVBOUyBhbmQgQVBOU19TQU5EQk9YIGJvdGggdXNlIEFQTlNNZXNzYWdlOyB0aGUgY2hhbm5lbCBpcyBzZWxlY3RlZCBwZXJcbiAgLy8gYWRkcmVzcyB2aWEgQWRkcmVzc0NvbmZpZ3VyYXRpb24uQ2hhbm5lbFR5cGUuXG4gIHJldHVybiB7IEFQTlNNZXNzYWdlOiBjb21tb24gfTtcbn07XG4iXX0=
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frozen contract for the push-delivery Lambda.
|
|
3
|
+
*
|
|
4
|
+
* Amazon Connect has no native mobile-push channel. Delivery is a workaround:
|
|
5
|
+
* a Connect Journey Custom-action (Invoke Lambda) block calls THIS Lambda,
|
|
6
|
+
* which resolves each targeted profile's registered devices from Customer
|
|
7
|
+
* Profiles and pushes to them via AWS End User Messaging (the Pinpoint
|
|
8
|
+
* `SendMessages` API).
|
|
9
|
+
*
|
|
10
|
+
* These types mirror the JSON shapes the Lambda accepts / returns so the
|
|
11
|
+
* handler, the parsing / payload / delivery layers, and the tests share one
|
|
12
|
+
* source of truth.
|
|
13
|
+
*/
|
|
14
|
+
/** The push channels this backend can deliver to (post-normalization). */
|
|
15
|
+
export type PushChannelType = 'GCM' | 'APNS' | 'APNS_SANDBOX';
|
|
16
|
+
/** A single push notification's content. */
|
|
17
|
+
export type PushMessage = {
|
|
18
|
+
/** Title shown above the notification. */
|
|
19
|
+
title: string;
|
|
20
|
+
/** Notification body text. */
|
|
21
|
+
body: string;
|
|
22
|
+
/**
|
|
23
|
+
* Optional opaque data payload delivered alongside the notification (added to
|
|
24
|
+
* the platform message's `Data` map, all values coerced to strings).
|
|
25
|
+
*/
|
|
26
|
+
data?: Record<string, string>;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* A single profile the Journey targeted, as surfaced to this Lambda. Mirrors a
|
|
30
|
+
* Connect Journey Custom-action `CustomerProfiles` entry: the resolved
|
|
31
|
+
* `ProfileId` plus a bag of profile fields / attributes (`CustomerData`).
|
|
32
|
+
*/
|
|
33
|
+
export type ProfileTarget = {
|
|
34
|
+
/** The Customer Profiles ProfileId to deliver to. */
|
|
35
|
+
profileId: string;
|
|
36
|
+
/**
|
|
37
|
+
* The profile's standard fields + Attributes as delivered by Connect
|
|
38
|
+
* (camelCase: `firstName`, `attributes.*`, ...). Passed as flat
|
|
39
|
+
* `customAttributes` to personalize the rendered Q Connect PUSH template (see
|
|
40
|
+
* `renderProfileChannelMessages`); real journeys carry NO message copy here.
|
|
41
|
+
* Device tokens are always resolved authoritatively via ListProfileObjects,
|
|
42
|
+
* never from here.
|
|
43
|
+
*/
|
|
44
|
+
customerData?: Record<string, unknown>;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Which envelope shape {@link parsePushEvent} matched, for observability.
|
|
48
|
+
* `canonical` — the real Connect Outbound Campaigns v2 journey envelope
|
|
49
|
+
* (`Items.CustomerProfiles[]`); `none` — no targets were resolvable.
|
|
50
|
+
*/
|
|
51
|
+
export type PushEventParsePath = 'canonical' | 'none';
|
|
52
|
+
/**
|
|
53
|
+
* The Outbound Campaigns v2 journey context carried on the real invocation
|
|
54
|
+
* envelope under `InvocationMetadata.CampaignContext`. Extracted for
|
|
55
|
+
* observability and for the upcoming message-copy-by-campaign feature (message
|
|
56
|
+
* sourcing is NOT implemented off this yet). All fields optional/defensive
|
|
57
|
+
* since direct-invoke test payloads omit them.
|
|
58
|
+
*/
|
|
59
|
+
export type CampaignContext = {
|
|
60
|
+
/** The Connect campaign / journey id. */
|
|
61
|
+
campaignId?: string;
|
|
62
|
+
/** The human-readable campaign / journey name (e.g. `journey-2`). */
|
|
63
|
+
campaignName?: string;
|
|
64
|
+
/** The journey action id (e.g. the Custom-action block name). */
|
|
65
|
+
actionId?: string;
|
|
66
|
+
/** The specific campaign run id for this invocation. */
|
|
67
|
+
runId?: string;
|
|
68
|
+
};
|
|
69
|
+
/** The normalized result of parsing a raw Journey Custom-action event. */
|
|
70
|
+
export type ParsedPushEvent = {
|
|
71
|
+
/** Every profile the event targeted (batches are flattened). */
|
|
72
|
+
targets: ProfileTarget[];
|
|
73
|
+
/**
|
|
74
|
+
* The safe DEFAULT push copy ({@link DEFAULT_PUSH_TITLE} /
|
|
75
|
+
* {@link DEFAULT_PUSH_BODY}) used as the fallback when no Q Connect template
|
|
76
|
+
* copy applies for a channel. Real journeys carry no event-level copy.
|
|
77
|
+
*/
|
|
78
|
+
message: PushMessage;
|
|
79
|
+
/**
|
|
80
|
+
* The envelope shape that produced the targets (`canonical`), or `none` when
|
|
81
|
+
* no targets were resolvable. Logged by the handler for observability.
|
|
82
|
+
*/
|
|
83
|
+
parsePath: PushEventParsePath;
|
|
84
|
+
/**
|
|
85
|
+
* The journey/campaign context from `InvocationMetadata.CampaignContext`,
|
|
86
|
+
* when present on the envelope (real Outbound Campaigns v2 journeys), else
|
|
87
|
+
* `undefined` (direct-invoke test payloads).
|
|
88
|
+
*/
|
|
89
|
+
campaign?: CampaignContext;
|
|
90
|
+
};
|
|
91
|
+
/** Delivery outcome for a single device (one `SendMessages` call). */
|
|
92
|
+
export type DeviceDeliveryResult = {
|
|
93
|
+
/** The push token the message was addressed to. */
|
|
94
|
+
deviceToken: string;
|
|
95
|
+
/** The (normalized) channel the message was sent on. */
|
|
96
|
+
channelType: PushChannelType;
|
|
97
|
+
/**
|
|
98
|
+
* The Customer Profiles ProfileObjectUniqueKey of the AmplifyDevice object
|
|
99
|
+
* this token came from — carried so a stale token can be deleted.
|
|
100
|
+
*/
|
|
101
|
+
objectUniqueKey?: string;
|
|
102
|
+
/**
|
|
103
|
+
* Pinpoint `DeliveryStatus` (`SUCCESSFUL`, `PERMANENT_FAILURE`, ...), or
|
|
104
|
+
* `ERROR` when the `SendMessages` call itself threw, or `SKIPPED` when the
|
|
105
|
+
* device could not be delivered to (e.g. unsupported / missing channel).
|
|
106
|
+
*/
|
|
107
|
+
status: string;
|
|
108
|
+
/** Whether delivery succeeded. */
|
|
109
|
+
delivered: boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Whether this represents a permanently-invalid TOKEN whose backing
|
|
112
|
+
* AmplifyDevice object should be deleted (stale-token cleanup). Set ONLY for
|
|
113
|
+
* a token-invalidity signal (see `isInvalidTokenFailure`); channel / app
|
|
114
|
+
* misconfiguration and transient failures are `false` (token kept).
|
|
115
|
+
*/
|
|
116
|
+
stale: boolean;
|
|
117
|
+
/** Pinpoint numeric status code, when available. */
|
|
118
|
+
statusCode?: number;
|
|
119
|
+
/** Human-readable status / error detail. */
|
|
120
|
+
statusMessage?: string;
|
|
121
|
+
};
|
|
122
|
+
/** Aggregated delivery outcome for a single profile. */
|
|
123
|
+
export type ProfileDeliveryResult = {
|
|
124
|
+
profileId: string;
|
|
125
|
+
/** Number of devices delivered to successfully. */
|
|
126
|
+
delivered: number;
|
|
127
|
+
/** Number of devices that failed delivery. */
|
|
128
|
+
failed: number;
|
|
129
|
+
/** Number of stale device objects deleted during cleanup. */
|
|
130
|
+
cleaned: number;
|
|
131
|
+
/** Per-device breakdown. */
|
|
132
|
+
devices: DeviceDeliveryResult[];
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* The response returned to the Connect Journey Custom-action invocation.
|
|
136
|
+
*
|
|
137
|
+
* NOTE: Connect's exact expected custom-action response envelope for the
|
|
138
|
+
* outbound-campaigns Journey batch is not publicly documented; this structured
|
|
139
|
+
* per-profile summary is a best-effort shape and is flagged for review.
|
|
140
|
+
*/
|
|
141
|
+
export type PushDeliveryResponse = {
|
|
142
|
+
/** Total profiles processed. */
|
|
143
|
+
profilesProcessed: number;
|
|
144
|
+
/** Total devices delivered to across all profiles. */
|
|
145
|
+
totalDelivered: number;
|
|
146
|
+
/** Total device deliveries that failed across all profiles. */
|
|
147
|
+
totalFailed: number;
|
|
148
|
+
/** Total stale device objects deleted across all profiles. */
|
|
149
|
+
totalCleaned: number;
|
|
150
|
+
/** Per-profile results. */
|
|
151
|
+
results: ProfileDeliveryResult[];
|
|
152
|
+
};
|
|
153
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
export {};
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGFtYmRhL3B1c2gvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEscUVBQXFFO0FBQ3JFLHNDQUFzQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuLyoqXG4gKiBGcm96ZW4gY29udHJhY3QgZm9yIHRoZSBwdXNoLWRlbGl2ZXJ5IExhbWJkYS5cbiAqXG4gKiBBbWF6b24gQ29ubmVjdCBoYXMgbm8gbmF0aXZlIG1vYmlsZS1wdXNoIGNoYW5uZWwuIERlbGl2ZXJ5IGlzIGEgd29ya2Fyb3VuZDpcbiAqIGEgQ29ubmVjdCBKb3VybmV5IEN1c3RvbS1hY3Rpb24gKEludm9rZSBMYW1iZGEpIGJsb2NrIGNhbGxzIFRISVMgTGFtYmRhLFxuICogd2hpY2ggcmVzb2x2ZXMgZWFjaCB0YXJnZXRlZCBwcm9maWxlJ3MgcmVnaXN0ZXJlZCBkZXZpY2VzIGZyb20gQ3VzdG9tZXJcbiAqIFByb2ZpbGVzIGFuZCBwdXNoZXMgdG8gdGhlbSB2aWEgQVdTIEVuZCBVc2VyIE1lc3NhZ2luZyAodGhlIFBpbnBvaW50XG4gKiBgU2VuZE1lc3NhZ2VzYCBBUEkpLlxuICpcbiAqIFRoZXNlIHR5cGVzIG1pcnJvciB0aGUgSlNPTiBzaGFwZXMgdGhlIExhbWJkYSBhY2NlcHRzIC8gcmV0dXJucyBzbyB0aGVcbiAqIGhhbmRsZXIsIHRoZSBwYXJzaW5nIC8gcGF5bG9hZCAvIGRlbGl2ZXJ5IGxheWVycywgYW5kIHRoZSB0ZXN0cyBzaGFyZSBvbmVcbiAqIHNvdXJjZSBvZiB0cnV0aC5cbiAqL1xuXG4vKiogVGhlIHB1c2ggY2hhbm5lbHMgdGhpcyBiYWNrZW5kIGNhbiBkZWxpdmVyIHRvIChwb3N0LW5vcm1hbGl6YXRpb24pLiAqL1xuZXhwb3J0IHR5cGUgUHVzaENoYW5uZWxUeXBlID0gJ0dDTScgfCAnQVBOUycgfCAnQVBOU19TQU5EQk9YJztcblxuLyoqIEEgc2luZ2xlIHB1c2ggbm90aWZpY2F0aW9uJ3MgY29udGVudC4gKi9cbmV4cG9ydCB0eXBlIFB1c2hNZXNzYWdlID0ge1xuICAvKiogVGl0bGUgc2hvd24gYWJvdmUgdGhlIG5vdGlmaWNhdGlvbi4gKi9cbiAgdGl0bGU6IHN0cmluZztcbiAgLyoqIE5vdGlmaWNhdGlvbiBib2R5IHRleHQuICovXG4gIGJvZHk6IHN0cmluZztcbiAgLyoqXG4gICAqIE9wdGlvbmFsIG9wYXF1ZSBkYXRhIHBheWxvYWQgZGVsaXZlcmVkIGFsb25nc2lkZSB0aGUgbm90aWZpY2F0aW9uIChhZGRlZCB0b1xuICAgKiB0aGUgcGxhdGZvcm0gbWVzc2FnZSdzIGBEYXRhYCBtYXAsIGFsbCB2YWx1ZXMgY29lcmNlZCB0byBzdHJpbmdzKS5cbiAgICovXG4gIGRhdGE/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xufTtcblxuLyoqXG4gKiBBIHNpbmdsZSBwcm9maWxlIHRoZSBKb3VybmV5IHRhcmdldGVkLCBhcyBzdXJmYWNlZCB0byB0aGlzIExhbWJkYS4gTWlycm9ycyBhXG4gKiBDb25uZWN0IEpvdXJuZXkgQ3VzdG9tLWFjdGlvbiBgQ3VzdG9tZXJQcm9maWxlc2AgZW50cnk6IHRoZSByZXNvbHZlZFxuICogYFByb2ZpbGVJZGAgcGx1cyBhIGJhZyBvZiBwcm9maWxlIGZpZWxkcyAvIGF0dHJpYnV0ZXMgKGBDdXN0b21lckRhdGFgKS5cbiAqL1xuZXhwb3J0IHR5cGUgUHJvZmlsZVRhcmdldCA9IHtcbiAgLyoqIFRoZSBDdXN0b21lciBQcm9maWxlcyBQcm9maWxlSWQgdG8gZGVsaXZlciB0by4gKi9cbiAgcHJvZmlsZUlkOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgcHJvZmlsZSdzIHN0YW5kYXJkIGZpZWxkcyArIEF0dHJpYnV0ZXMgYXMgZGVsaXZlcmVkIGJ5IENvbm5lY3RcbiAgICogKGNhbWVsQ2FzZTogYGZpcnN0TmFtZWAsIGBhdHRyaWJ1dGVzLipgLCAuLi4pLiBQYXNzZWQgYXMgZmxhdFxuICAgKiBgY3VzdG9tQXR0cmlidXRlc2AgdG8gcGVyc29uYWxpemUgdGhlIHJlbmRlcmVkIFEgQ29ubmVjdCBQVVNIIHRlbXBsYXRlIChzZWVcbiAgICogYHJlbmRlclByb2ZpbGVDaGFubmVsTWVzc2FnZXNgKTsgcmVhbCBqb3VybmV5cyBjYXJyeSBOTyBtZXNzYWdlIGNvcHkgaGVyZS5cbiAgICogRGV2aWNlIHRva2VucyBhcmUgYWx3YXlzIHJlc29sdmVkIGF1dGhvcml0YXRpdmVseSB2aWEgTGlzdFByb2ZpbGVPYmplY3RzLFxuICAgKiBuZXZlciBmcm9tIGhlcmUuXG4gICAqL1xuICBjdXN0b21lckRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn07XG5cbi8qKlxuICogV2hpY2ggZW52ZWxvcGUgc2hhcGUge0BsaW5rIHBhcnNlUHVzaEV2ZW50fSBtYXRjaGVkLCBmb3Igb2JzZXJ2YWJpbGl0eS5cbiAqIGBjYW5vbmljYWxgIOKAlCB0aGUgcmVhbCBDb25uZWN0IE91dGJvdW5kIENhbXBhaWducyB2MiBqb3VybmV5IGVudmVsb3BlXG4gKiAoYEl0ZW1zLkN1c3RvbWVyUHJvZmlsZXNbXWApOyBgbm9uZWAg4oCUIG5vIHRhcmdldHMgd2VyZSByZXNvbHZhYmxlLlxuICovXG5leHBvcnQgdHlwZSBQdXNoRXZlbnRQYXJzZVBhdGggPSAnY2Fub25pY2FsJyB8ICdub25lJztcblxuLyoqXG4gKiBUaGUgT3V0Ym91bmQgQ2FtcGFpZ25zIHYyIGpvdXJuZXkgY29udGV4dCBjYXJyaWVkIG9uIHRoZSByZWFsIGludm9jYXRpb25cbiAqIGVudmVsb3BlIHVuZGVyIGBJbnZvY2F0aW9uTWV0YWRhdGEuQ2FtcGFpZ25Db250ZXh0YC4gRXh0cmFjdGVkIGZvclxuICogb2JzZXJ2YWJpbGl0eSBhbmQgZm9yIHRoZSB1cGNvbWluZyBtZXNzYWdlLWNvcHktYnktY2FtcGFpZ24gZmVhdHVyZSAobWVzc2FnZVxuICogc291cmNpbmcgaXMgTk9UIGltcGxlbWVudGVkIG9mZiB0aGlzIHlldCkuIEFsbCBmaWVsZHMgb3B0aW9uYWwvZGVmZW5zaXZlXG4gKiBzaW5jZSBkaXJlY3QtaW52b2tlIHRlc3QgcGF5bG9hZHMgb21pdCB0aGVtLlxuICovXG5leHBvcnQgdHlwZSBDYW1wYWlnbkNvbnRleHQgPSB7XG4gIC8qKiBUaGUgQ29ubmVjdCBjYW1wYWlnbiAvIGpvdXJuZXkgaWQuICovXG4gIGNhbXBhaWduSWQ/OiBzdHJpbmc7XG4gIC8qKiBUaGUgaHVtYW4tcmVhZGFibGUgY2FtcGFpZ24gLyBqb3VybmV5IG5hbWUgKGUuZy4gYGpvdXJuZXktMmApLiAqL1xuICBjYW1wYWlnbk5hbWU/OiBzdHJpbmc7XG4gIC8qKiBUaGUgam91cm5leSBhY3Rpb24gaWQgKGUuZy4gdGhlIEN1c3RvbS1hY3Rpb24gYmxvY2sgbmFtZSkuICovXG4gIGFjdGlvbklkPzogc3RyaW5nO1xuICAvKiogVGhlIHNwZWNpZmljIGNhbXBhaWduIHJ1biBpZCBmb3IgdGhpcyBpbnZvY2F0aW9uLiAqL1xuICBydW5JZD86IHN0cmluZztcbn07XG5cbi8qKiBUaGUgbm9ybWFsaXplZCByZXN1bHQgb2YgcGFyc2luZyBhIHJhdyBKb3VybmV5IEN1c3RvbS1hY3Rpb24gZXZlbnQuICovXG5leHBvcnQgdHlwZSBQYXJzZWRQdXNoRXZlbnQgPSB7XG4gIC8qKiBFdmVyeSBwcm9maWxlIHRoZSBldmVudCB0YXJnZXRlZCAoYmF0Y2hlcyBhcmUgZmxhdHRlbmVkKS4gKi9cbiAgdGFyZ2V0czogUHJvZmlsZVRhcmdldFtdO1xuICAvKipcbiAgICogVGhlIHNhZmUgREVGQVVMVCBwdXNoIGNvcHkgKHtAbGluayBERUZBVUxUX1BVU0hfVElUTEV9IC9cbiAgICoge0BsaW5rIERFRkFVTFRfUFVTSF9CT0RZfSkgdXNlZCBhcyB0aGUgZmFsbGJhY2sgd2hlbiBubyBRIENvbm5lY3QgdGVtcGxhdGVcbiAgICogY29weSBhcHBsaWVzIGZvciBhIGNoYW5uZWwuIFJlYWwgam91cm5leXMgY2Fycnkgbm8gZXZlbnQtbGV2ZWwgY29weS5cbiAgICovXG4gIG1lc3NhZ2U6IFB1c2hNZXNzYWdlO1xuICAvKipcbiAgICogVGhlIGVudmVsb3BlIHNoYXBlIHRoYXQgcHJvZHVjZWQgdGhlIHRhcmdldHMgKGBjYW5vbmljYWxgKSwgb3IgYG5vbmVgIHdoZW5cbiAgICogbm8gdGFyZ2V0cyB3ZXJlIHJlc29sdmFibGUuIExvZ2dlZCBieSB0aGUgaGFuZGxlciBmb3Igb2JzZXJ2YWJpbGl0eS5cbiAgICovXG4gIHBhcnNlUGF0aDogUHVzaEV2ZW50UGFyc2VQYXRoO1xuICAvKipcbiAgICogVGhlIGpvdXJuZXkvY2FtcGFpZ24gY29udGV4dCBmcm9tIGBJbnZvY2F0aW9uTWV0YWRhdGEuQ2FtcGFpZ25Db250ZXh0YCxcbiAgICogd2hlbiBwcmVzZW50IG9uIHRoZSBlbnZlbG9wZSAocmVhbCBPdXRib3VuZCBDYW1wYWlnbnMgdjIgam91cm5leXMpLCBlbHNlXG4gICAqIGB1bmRlZmluZWRgIChkaXJlY3QtaW52b2tlIHRlc3QgcGF5bG9hZHMpLlxuICAgKi9cbiAgY2FtcGFpZ24/OiBDYW1wYWlnbkNvbnRleHQ7XG59O1xuXG4vKiogRGVsaXZlcnkgb3V0Y29tZSBmb3IgYSBzaW5nbGUgZGV2aWNlIChvbmUgYFNlbmRNZXNzYWdlc2AgY2FsbCkuICovXG5leHBvcnQgdHlwZSBEZXZpY2VEZWxpdmVyeVJlc3VsdCA9IHtcbiAgLyoqIFRoZSBwdXNoIHRva2VuIHRoZSBtZXNzYWdlIHdhcyBhZGRyZXNzZWQgdG8uICovXG4gIGRldmljZVRva2VuOiBzdHJpbmc7XG4gIC8qKiBUaGUgKG5vcm1hbGl6ZWQpIGNoYW5uZWwgdGhlIG1lc3NhZ2Ugd2FzIHNlbnQgb24uICovXG4gIGNoYW5uZWxUeXBlOiBQdXNoQ2hhbm5lbFR5cGU7XG4gIC8qKlxuICAgKiBUaGUgQ3VzdG9tZXIgUHJvZmlsZXMgUHJvZmlsZU9iamVjdFVuaXF1ZUtleSBvZiB0aGUgQW1wbGlmeURldmljZSBvYmplY3RcbiAgICogdGhpcyB0b2tlbiBjYW1lIGZyb20g4oCUIGNhcnJpZWQgc28gYSBzdGFsZSB0b2tlbiBjYW4gYmUgZGVsZXRlZC5cbiAgICovXG4gIG9iamVjdFVuaXF1ZUtleT86IHN0cmluZztcbiAgLyoqXG4gICAqIFBpbnBvaW50IGBEZWxpdmVyeVN0YXR1c2AgKGBTVUNDRVNTRlVMYCwgYFBFUk1BTkVOVF9GQUlMVVJFYCwgLi4uKSwgb3JcbiAgICogYEVSUk9SYCB3aGVuIHRoZSBgU2VuZE1lc3NhZ2VzYCBjYWxsIGl0c2VsZiB0aHJldywgb3IgYFNLSVBQRURgIHdoZW4gdGhlXG4gICAqIGRldmljZSBjb3VsZCBub3QgYmUgZGVsaXZlcmVkIHRvIChlLmcuIHVuc3VwcG9ydGVkIC8gbWlzc2luZyBjaGFubmVsKS5cbiAgICovXG4gIHN0YXR1czogc3RyaW5nO1xuICAvKiogV2hldGhlciBkZWxpdmVyeSBzdWNjZWVkZWQuICovXG4gIGRlbGl2ZXJlZDogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhpcyByZXByZXNlbnRzIGEgcGVybWFuZW50bHktaW52YWxpZCBUT0tFTiB3aG9zZSBiYWNraW5nXG4gICAqIEFtcGxpZnlEZXZpY2Ugb2JqZWN0IHNob3VsZCBiZSBkZWxldGVkIChzdGFsZS10b2tlbiBjbGVhbnVwKS4gU2V0IE9OTFkgZm9yXG4gICAqIGEgdG9rZW4taW52YWxpZGl0eSBzaWduYWwgKHNlZSBgaXNJbnZhbGlkVG9rZW5GYWlsdXJlYCk7IGNoYW5uZWwgLyBhcHBcbiAgICogbWlzY29uZmlndXJhdGlvbiBhbmQgdHJhbnNpZW50IGZhaWx1cmVzIGFyZSBgZmFsc2VgICh0b2tlbiBrZXB0KS5cbiAgICovXG4gIHN0YWxlOiBib29sZWFuO1xuICAvKiogUGlucG9pbnQgbnVtZXJpYyBzdGF0dXMgY29kZSwgd2hlbiBhdmFpbGFibGUuICovXG4gIHN0YXR1c0NvZGU/OiBudW1iZXI7XG4gIC8qKiBIdW1hbi1yZWFkYWJsZSBzdGF0dXMgLyBlcnJvciBkZXRhaWwuICovXG4gIHN0YXR1c01lc3NhZ2U/OiBzdHJpbmc7XG59O1xuXG4vKiogQWdncmVnYXRlZCBkZWxpdmVyeSBvdXRjb21lIGZvciBhIHNpbmdsZSBwcm9maWxlLiAqL1xuZXhwb3J0IHR5cGUgUHJvZmlsZURlbGl2ZXJ5UmVzdWx0ID0ge1xuICBwcm9maWxlSWQ6IHN0cmluZztcbiAgLyoqIE51bWJlciBvZiBkZXZpY2VzIGRlbGl2ZXJlZCB0byBzdWNjZXNzZnVsbHkuICovXG4gIGRlbGl2ZXJlZDogbnVtYmVyO1xuICAvKiogTnVtYmVyIG9mIGRldmljZXMgdGhhdCBmYWlsZWQgZGVsaXZlcnkuICovXG4gIGZhaWxlZDogbnVtYmVyO1xuICAvKiogTnVtYmVyIG9mIHN0YWxlIGRldmljZSBvYmplY3RzIGRlbGV0ZWQgZHVyaW5nIGNsZWFudXAuICovXG4gIGNsZWFuZWQ6IG51bWJlcjtcbiAgLyoqIFBlci1kZXZpY2UgYnJlYWtkb3duLiAqL1xuICBkZXZpY2VzOiBEZXZpY2VEZWxpdmVyeVJlc3VsdFtdO1xufTtcblxuLyoqXG4gKiBUaGUgcmVzcG9uc2UgcmV0dXJuZWQgdG8gdGhlIENvbm5lY3QgSm91cm5leSBDdXN0b20tYWN0aW9uIGludm9jYXRpb24uXG4gKlxuICogTk9URTogQ29ubmVjdCdzIGV4YWN0IGV4cGVjdGVkIGN1c3RvbS1hY3Rpb24gcmVzcG9uc2UgZW52ZWxvcGUgZm9yIHRoZVxuICogb3V0Ym91bmQtY2FtcGFpZ25zIEpvdXJuZXkgYmF0Y2ggaXMgbm90IHB1YmxpY2x5IGRvY3VtZW50ZWQ7IHRoaXMgc3RydWN0dXJlZFxuICogcGVyLXByb2ZpbGUgc3VtbWFyeSBpcyBhIGJlc3QtZWZmb3J0IHNoYXBlIGFuZCBpcyBmbGFnZ2VkIGZvciByZXZpZXcuXG4gKi9cbmV4cG9ydCB0eXBlIFB1c2hEZWxpdmVyeVJlc3BvbnNlID0ge1xuICAvKiogVG90YWwgcHJvZmlsZXMgcHJvY2Vzc2VkLiAqL1xuICBwcm9maWxlc1Byb2Nlc3NlZDogbnVtYmVyO1xuICAvKiogVG90YWwgZGV2aWNlcyBkZWxpdmVyZWQgdG8gYWNyb3NzIGFsbCBwcm9maWxlcy4gKi9cbiAgdG90YWxEZWxpdmVyZWQ6IG51bWJlcjtcbiAgLyoqIFRvdGFsIGRldmljZSBkZWxpdmVyaWVzIHRoYXQgZmFpbGVkIGFjcm9zcyBhbGwgcHJvZmlsZXMuICovXG4gIHRvdGFsRmFpbGVkOiBudW1iZXI7XG4gIC8qKiBUb3RhbCBzdGFsZSBkZXZpY2Ugb2JqZWN0cyBkZWxldGVkIGFjcm9zcyBhbGwgcHJvZmlsZXMuICovXG4gIHRvdGFsQ2xlYW5lZDogbnVtYmVyO1xuICAvKiogUGVyLXByb2ZpbGUgcmVzdWx0cy4gKi9cbiAgcmVzdWx0czogUHJvZmlsZURlbGl2ZXJ5UmVzdWx0W107XG59O1xuIl19
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Customer Profiles serializes writes to a single profile: concurrent
|
|
3
|
+
* UpdateProfile / PutProfileObject calls against the same profile fail with a
|
|
4
|
+
* `BadRequestException: Failed to update profile due to concurrent update
|
|
5
|
+
* in-progress.` This is a TRANSIENT, idempotent condition (the write is safe to
|
|
6
|
+
* repeat), so the correct handling is a short bounded retry with jittered
|
|
7
|
+
* backoff rather than surfacing a 5xx to the caller.
|
|
8
|
+
*/
|
|
9
|
+
export declare const isTransientConcurrentUpdate: (err: unknown) => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Run `fn`, retrying on transient concurrent-update / throttling errors with
|
|
12
|
+
* exponential backoff + full jitter. Non-transient errors propagate immediately.
|
|
13
|
+
*/
|
|
14
|
+
export declare const withTransientRetry: <T>(fn: () => Promise<T>, opts?: {
|
|
15
|
+
attempts?: number;
|
|
16
|
+
baseDelayMs?: number;
|
|
17
|
+
}) => Promise<T>;
|
|
18
|
+
//# sourceMappingURL=retry.d.ts.map
|