@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,99 @@
|
|
|
1
|
+
const CHANNEL_TYPES = [
|
|
2
|
+
'GCM',
|
|
3
|
+
'APNS',
|
|
4
|
+
'APNS_SANDBOX',
|
|
5
|
+
'IN_APP',
|
|
6
|
+
];
|
|
7
|
+
const OPT_OUTS = ['ALL', 'NONE'];
|
|
8
|
+
const isPlainObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
9
|
+
const isStringArray = (v) => Array.isArray(v) && v.every((x) => typeof x === 'string');
|
|
10
|
+
const isStringMap = (v) => isPlainObject(v) && Object.values(v).every((x) => isStringArray(x));
|
|
11
|
+
/**
|
|
12
|
+
* Validate the frozen identify-user request contract.
|
|
13
|
+
*
|
|
14
|
+
* Returns `{ ok: false, error }` on the first violation so the handler can map
|
|
15
|
+
* it to a 400. Identity is NOT validated here — the verified `sub` is supplied
|
|
16
|
+
* separately by the authorizer.
|
|
17
|
+
*/
|
|
18
|
+
export const validateBody = (body) => {
|
|
19
|
+
if (!isPlainObject(body)) {
|
|
20
|
+
return { ok: false, error: 'Request body must be a JSON object' };
|
|
21
|
+
}
|
|
22
|
+
if (body.userId !== undefined && typeof body.userId !== 'string') {
|
|
23
|
+
return { ok: false, error: 'userId must be a string when present' };
|
|
24
|
+
}
|
|
25
|
+
const userProfile = body.userProfile;
|
|
26
|
+
if (!isPlainObject(userProfile)) {
|
|
27
|
+
return {
|
|
28
|
+
ok: false,
|
|
29
|
+
error: 'userProfile is required and must be an object',
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
for (const key of ['name', 'email', 'plan']) {
|
|
33
|
+
if (userProfile[key] !== undefined &&
|
|
34
|
+
typeof userProfile[key] !== 'string') {
|
|
35
|
+
return { ok: false, error: `userProfile.${key} must be a string` };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (userProfile.customProperties !== undefined &&
|
|
39
|
+
!isStringMap(userProfile.customProperties)) {
|
|
40
|
+
return {
|
|
41
|
+
ok: false,
|
|
42
|
+
error: 'userProfile.customProperties must be a map of string arrays',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (userProfile.metrics !== undefined) {
|
|
46
|
+
if (!isPlainObject(userProfile.metrics) ||
|
|
47
|
+
!Object.values(userProfile.metrics).every((n) => typeof n === 'number')) {
|
|
48
|
+
return {
|
|
49
|
+
ok: false,
|
|
50
|
+
error: 'userProfile.metrics must be a map of numbers',
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const options = body.options;
|
|
55
|
+
if (options !== undefined) {
|
|
56
|
+
if (!isPlainObject(options)) {
|
|
57
|
+
return { ok: false, error: 'options must be an object when present' };
|
|
58
|
+
}
|
|
59
|
+
if (options.address !== undefined && typeof options.address !== 'string') {
|
|
60
|
+
return { ok: false, error: 'options.address must be a string' };
|
|
61
|
+
}
|
|
62
|
+
if (options.deviceId !== undefined &&
|
|
63
|
+
typeof options.deviceId !== 'string') {
|
|
64
|
+
return { ok: false, error: 'options.deviceId must be a string' };
|
|
65
|
+
}
|
|
66
|
+
if (options.previousGuestIdentityId !== undefined &&
|
|
67
|
+
(typeof options.previousGuestIdentityId !== 'string' ||
|
|
68
|
+
options.previousGuestIdentityId.trim().length === 0 ||
|
|
69
|
+
options.previousGuestIdentityId.length > 128)) {
|
|
70
|
+
return {
|
|
71
|
+
ok: false,
|
|
72
|
+
error: 'options.previousGuestIdentityId must be a non-empty string',
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (options.channelType !== undefined &&
|
|
76
|
+
!CHANNEL_TYPES.includes(options.channelType)) {
|
|
77
|
+
return {
|
|
78
|
+
ok: false,
|
|
79
|
+
error: `options.channelType must be one of ${CHANNEL_TYPES.join(', ')}`,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (options.optOut !== undefined &&
|
|
83
|
+
!OPT_OUTS.includes(options.optOut)) {
|
|
84
|
+
return {
|
|
85
|
+
ok: false,
|
|
86
|
+
error: `options.optOut must be one of ${OPT_OUTS.join(', ')}`,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (options.userAttributes !== undefined &&
|
|
90
|
+
!isStringMap(options.userAttributes)) {
|
|
91
|
+
return {
|
|
92
|
+
ok: false,
|
|
93
|
+
error: 'options.userAttributes must be a map of string arrays',
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return { ok: true, value: body };
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYW1iZGEvaWRlbnRpZnkvdmFsaWRhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxNQUFNLGFBQWEsR0FBK0I7SUFDaEQsS0FBSztJQUNMLE1BQU07SUFDTixjQUFjO0lBQ2QsUUFBUTtDQUNULENBQUM7QUFDRixNQUFNLFFBQVEsR0FBMEIsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFReEQsTUFBTSxhQUFhLEdBQUcsQ0FBQyxDQUFVLEVBQWdDLEVBQUUsQ0FDakUsT0FBTyxDQUFDLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRTNELE1BQU0sYUFBYSxHQUFHLENBQUMsQ0FBVSxFQUFpQixFQUFFLENBQ2xELEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssUUFBUSxDQUFDLENBQUM7QUFFNUQsTUFBTSxXQUFXLEdBQUcsQ0FBQyxDQUFVLEVBQWlDLEVBQUUsQ0FDaEUsYUFBYSxDQUFDLENBQUMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUV0RTs7Ozs7O0dBTUc7QUFDSCxNQUFNLENBQUMsTUFBTSxZQUFZLEdBQUcsQ0FBQyxJQUFhLEVBQW9CLEVBQUU7SUFDOUQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ3pCLE9BQU8sRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxvQ0FBb0MsRUFBRSxDQUFDO0lBQ3BF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O2FBQ3BFLENBQUM7UUFDSixDQUFDO1FBQ0QsSUFDRSxPQUFPLENBQUMsV0FBVyxLQUFLLFNBQVM7WUFDakMsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxXQUEwQixDQUFDLEVBQzNELENBQUM7WUFDRCxPQUFPO2dCQUNMLEVBQUUsRUFBRSxLQUFLO2dCQUNULEtBQUssRUFBRSxzQ0FBc0MsYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRTthQUN4RSxDQUFDO1FBQ0osQ0FBQztRQUNELElBQ0UsT0FBTyxDQUFDLE1BQU0sS0FBSyxTQUFTO1lBQzVCLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsTUFBZ0IsQ0FBQyxFQUM1QyxDQUFDO1lBQ0QsT0FBTztnQkFDTCxFQUFFLEVBQUUsS0FBSztnQkFDVCxLQUFLLEVBQUUsaUNBQWlDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7YUFDOUQsQ0FBQztRQUNKLENBQUM7UUFDRCxJQUNFLE9BQU8sQ0FBQyxjQUFjLEtBQUssU0FBUztZQUNwQyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLEVBQ3BDLENBQUM7WUFDRCxPQUFPO2dCQUNMLEVBQUUsRUFBRSxLQUFLO2dCQUNULEtBQUssRUFBRSx1REFBdUQ7YUFDL0QsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQXNDLEVBQUUsQ0FBQztBQUNyRSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFubmVsVHlwZSwgSWRlbnRpZnlVc2VyUmVxdWVzdCwgT3B0T3V0IH0gZnJvbSAnLi90eXBlcy5qcyc7XG5cbmNvbnN0IENIQU5ORUxfVFlQRVM6IFJlYWRvbmx5QXJyYXk8Q2hhbm5lbFR5cGU+ID0gW1xuICAnR0NNJyxcbiAgJ0FQTlMnLFxuICAnQVBOU19TQU5EQk9YJyxcbiAgJ0lOX0FQUCcsXG5dO1xuY29uc3QgT1BUX09VVFM6IFJlYWRvbmx5QXJyYXk8T3B0T3V0PiA9IFsnQUxMJywgJ05PTkUnXTtcblxuZXhwb3J0IHR5cGUgVmFsaWRhdGlvblJlc3VsdCA9IHtcbiAgb2s6IGJvb2xlYW47XG4gIGVycm9yPzogc3RyaW5nO1xuICB2YWx1ZT86IElkZW50aWZ5VXNlclJlcXVlc3Q7XG59O1xuXG5jb25zdCBpc1BsYWluT2JqZWN0ID0gKHY6IHVua25vd24pOiB2IGlzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0+XG4gIHR5cGVvZiB2ID09PSAnb2JqZWN0JyAmJiB2ICE9PSBudWxsICYmICFBcnJheS5pc0FycmF5KHYpO1xuXG5jb25zdCBpc1N0cmluZ0FycmF5ID0gKHY6IHVua25vd24pOiB2IGlzIHN0cmluZ1tdID0+XG4gIEFycmF5LmlzQXJyYXkodikgJiYgdi5ldmVyeSgoeCkgPT4gdHlwZW9mIHggPT09ICdzdHJpbmcnKTtcblxuY29uc3QgaXNTdHJpbmdNYXAgPSAodjogdW5rbm93bik6IHYgaXMgUmVjb3JkPHN0cmluZywgc3RyaW5nW10+ID0+XG4gIGlzUGxhaW5PYmplY3QodikgJiYgT2JqZWN0LnZhbHVlcyh2KS5ldmVyeSgoeCkgPT4gaXNTdHJpbmdBcnJheSh4KSk7XG5cbi8qKlxuICogVmFsaWRhdGUgdGhlIGZyb3plbiBpZGVudGlmeS11c2VyIHJlcXVlc3QgY29udHJhY3QuXG4gKlxuICogUmV0dXJucyBgeyBvazogZmFsc2UsIGVycm9yIH1gIG9uIHRoZSBmaXJzdCB2aW9sYXRpb24gc28gdGhlIGhhbmRsZXIgY2FuIG1hcFxuICogaXQgdG8gYSA0MDAuIElkZW50aXR5IGlzIE5PVCB2YWxpZGF0ZWQgaGVyZSDigJQgdGhlIHZlcmlmaWVkIGBzdWJgIGlzIHN1cHBsaWVkXG4gKiBzZXBhcmF0ZWx5IGJ5IHRoZSBhdXRob3JpemVyLlxuICovXG5leHBvcnQgY29uc3QgdmFsaWRhdGVCb2R5ID0gKGJvZHk6IHVua25vd24pOiBWYWxpZGF0aW9uUmVzdWx0ID0+IHtcbiAgaWYgKCFpc1BsYWluT2JqZWN0KGJvZHkpKSB7XG4gICAgcmV0dXJuIHsgb2s6IGZhbHNlLCBlcnJvcjogJ1JlcXVlc3QgYm9keSBtdXN0IGJlIGEgSlNPTiBvYmplY3QnIH07XG4gIH1cblxuICBpZiAoYm9keS51c2VySWQgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgYm9keS51c2VySWQgIT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIHsgb2s6IGZhbHNlLCBlcnJvcjogJ3VzZXJJZCBtdXN0IGJlIGEgc3RyaW5nIHdoZW4gcHJlc2VudCcgfTtcbiAgfVxuXG4gIGNvbnN0IHVzZXJQcm9maWxlID0gYm9keS51c2VyUHJvZmlsZTtcbiAgaWYgKCFpc1BsYWluT2JqZWN0KHVzZXJQcm9maWxlKSkge1xuICAgIHJldHVybiB7XG4gICAgICBvazogZmFsc2UsXG4gICAgICBlcnJvcjogJ3VzZXJQcm9maWxlIGlzIHJlcXVpcmVkIGFuZCBtdXN0IGJlIGFuIG9iamVjdCcsXG4gICAgfTtcbiAgfVxuXG4gIGZvciAoY29uc3Qga2V5IG9mIFsnbmFtZScsICdlbWFpbCcsICdwbGFuJ10gYXMgY29uc3QpIHtcbiAgICBpZiAoXG4gICAgICB1c2VyUHJvZmlsZVtrZXldICE9PSB1bmRlZmluZWQgJiZcbiAgICAgIHR5cGVvZiB1c2VyUHJvZmlsZVtrZXldICE9PSAnc3RyaW5nJ1xuICAgICkge1xuICAgICAgcmV0dXJuIHsgb2s6IGZhbHNlLCBlcnJvcjogYHVzZXJQcm9maWxlLiR7a2V5fSBtdXN0IGJlIGEgc3RyaW5nYCB9O1xuICAgIH1cbiAgfVxuXG4gIGlmIChcbiAgICB1c2VyUHJvZmlsZS5jdXN0b21Qcm9wZXJ0aWVzICE9PSB1bmRlZmluZWQgJiZcbiAgICAhaXNTdHJpbmdNYXAodXNlclByb2ZpbGUuY3VzdG9tUHJvcGVydGllcylcbiAgKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG9rOiBmYWxzZSxcbiAgICAgIGVycm9yOiAndXNlclByb2ZpbGUuY3VzdG9tUHJvcGVydGllcyBtdXN0IGJlIGEgbWFwIG9mIHN0cmluZyBhcnJheXMnLFxuICAgIH07XG4gIH1cblxuICBpZiAodXNlclByb2ZpbGUubWV0cmljcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgaWYgKFxuICAgICAgIWlzUGxhaW5PYmplY3QodXNlclByb2ZpbGUubWV0cmljcykgfHxcbiAgICAgICFPYmplY3QudmFsdWVzKHVzZXJQcm9maWxlLm1ldHJpY3MpLmV2ZXJ5KChuKSA9PiB0eXBlb2YgbiA9PT0gJ251bWJlcicpXG4gICAgKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBvazogZmFsc2UsXG4gICAgICAgIGVycm9yOiAndXNlclByb2ZpbGUubWV0cmljcyBtdXN0IGJlIGEgbWFwIG9mIG51bWJlcnMnLFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBvcHRpb25zID0gYm9keS5vcHRpb25zO1xuICBpZiAob3B0aW9ucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgaWYgKCFpc1BsYWluT2JqZWN0KG9wdGlvbnMpKSB7XG4gICAgICByZXR1cm4geyBvazogZmFsc2UsIGVycm9yOiAnb3B0aW9ucyBtdXN0IGJlIGFuIG9iamVjdCB3aGVuIHByZXNlbnQnIH07XG4gICAgfVxuICAgIGlmIChvcHRpb25zLmFkZHJlc3MgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2Ygb3B0aW9ucy5hZGRyZXNzICE9PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIHsgb2s6IGZhbHNlLCBlcnJvcjogJ29wdGlvbnMuYWRkcmVzcyBtdXN0IGJlIGEgc3RyaW5nJyB9O1xuICAgIH1cbiAgICBpZiAoXG4gICAgICBvcHRpb25zLmRldmljZUlkICE9PSB1bmRlZmluZWQgJiZcbiAgICAgIHR5cGVvZiBvcHRpb25zLmRldmljZUlkICE9PSAnc3RyaW5nJ1xuICAgICkge1xuICAgICAgcmV0dXJuIHsgb2s6IGZhbHNlLCBlcnJvcjogJ29wdGlvbnMuZGV2aWNlSWQgbXVzdCBiZSBhIHN0cmluZycgfTtcbiAgICB9XG4gICAgaWYgKFxuICAgICAgb3B0aW9ucy5wcmV2aW91c0d1ZXN0SWRlbnRpdHlJZCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAodHlwZW9mIG9wdGlvbnMucHJldmlvdXNHdWVzdElkZW50aXR5SWQgIT09ICdzdHJpbmcnIHx8XG4gICAgICAgIG9wdGlvbnMucHJldmlvdXNHdWVzdElkZW50aXR5SWQudHJpbSgpLmxlbmd0aCA9PT0gMCB8fFxuICAgICAgICBvcHRpb25zLnByZXZpb3VzR3Vlc3RJZGVudGl0eUlkLmxlbmd0aCA+IDEyOClcbiAgICApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG9rOiBmYWxzZSxcbiAgICAgICAgZXJyb3I6ICdvcHRpb25zLnByZXZpb3VzR3Vlc3RJZGVudGl0eUlkIG11c3QgYmUgYSBub24tZW1wdHkgc3RyaW5nJyxcbiAgICAgIH07XG4gICAgfVxuICAgIGlmIChcbiAgICAgIG9wdGlvbnMuY2hhbm5lbFR5cGUgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgIUNIQU5ORUxfVFlQRVMuaW5jbHVkZXMob3B0aW9ucy5jaGFubmVsVHlwZSBhcyBDaGFubmVsVHlwZSlcbiAgICApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG9rOiBmYWxzZSxcbiAgICAgICAgZXJyb3I6IGBvcHRpb25zLmNoYW5uZWxUeXBlIG11c3QgYmUgb25lIG9mICR7Q0hBTk5FTF9UWVBFUy5qb2luKCcsICcpfWAsXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAoXG4gICAgICBvcHRpb25zLm9wdE91dCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAhT1BUX09VVFMuaW5jbHVkZXMob3B0aW9ucy5vcHRPdXQgYXMgT3B0T3V0KVxuICAgICkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgb2s6IGZhbHNlLFxuICAgICAgICBlcnJvcjogYG9wdGlvbnMub3B0T3V0IG11c3QgYmUgb25lIG9mICR7T1BUX09VVFMuam9pbignLCAnKX1gLFxuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKFxuICAgICAgb3B0aW9ucy51c2VyQXR0cmlidXRlcyAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAhaXNTdHJpbmdNYXAob3B0aW9ucy51c2VyQXR0cmlidXRlcylcbiAgICApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG9rOiBmYWxzZSxcbiAgICAgICAgZXJyb3I6ICdvcHRpb25zLnVzZXJBdHRyaWJ1dGVzIG11c3QgYmUgYSBtYXAgb2Ygc3RyaW5nIGFycmF5cycsXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7IG9rOiB0cnVlLCB2YWx1ZTogYm9keSBhcyB1bmtub3duIGFzIElkZW50aWZ5VXNlclJlcXVlc3QgfTtcbn07XG4iXX0=
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { CustomerProfilesClient } from '@aws-sdk/client-customer-profiles';
|
|
2
|
+
import { PinpointClient } from '@aws-sdk/client-pinpoint';
|
|
3
|
+
import { PushTemplateContext } from './message_template.js';
|
|
4
|
+
import { ParsedPushEvent, ProfileDeliveryResult, ProfileTarget, PushChannelType, PushDeliveryResponse, PushMessage } from './types.js';
|
|
5
|
+
/** Injected clients + resolved config for the delivery routines. */
|
|
6
|
+
export type DeliveryDeps = {
|
|
7
|
+
profiles: CustomerProfilesClient;
|
|
8
|
+
pinpoint: PinpointClient;
|
|
9
|
+
/** Customer Profiles domain to resolve devices from. */
|
|
10
|
+
domainName: string;
|
|
11
|
+
/** AWS End User Messaging / Pinpoint application id to send from. */
|
|
12
|
+
applicationId: string;
|
|
13
|
+
/**
|
|
14
|
+
* The resolved Q in Connect PUSH message template for this journey run, when
|
|
15
|
+
* one was found (see {@link resolvePushTemplateContext}). When present, each
|
|
16
|
+
* profile's copy is rendered from the template (per-platform) and takes
|
|
17
|
+
* precedence over the safe DEFAULT copy; when absent, delivery uses the
|
|
18
|
+
* DEFAULT copy for every channel.
|
|
19
|
+
*/
|
|
20
|
+
templateContext?: PushTemplateContext;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Resolve a single profile's registered devices and push the message to each
|
|
24
|
+
* via AWS End User Messaging, then clean up any device whose token was
|
|
25
|
+
* permanently rejected (stale-token cleanup).
|
|
26
|
+
*
|
|
27
|
+
* A device with an unsupported / missing channel (post-normalization) is
|
|
28
|
+
* recorded as a `SKIPPED` failure rather than being sent. A device whose
|
|
29
|
+
* delivery returns `PERMANENT_FAILURE` has its AmplifyDevice object deleted;
|
|
30
|
+
* the per-device result records whether that cleanup succeeded.
|
|
31
|
+
*
|
|
32
|
+
* `message` is the profile's fallback copy. When `perChannel` is supplied (from
|
|
33
|
+
* a rendered Q Connect template), the message for a device's channel is taken
|
|
34
|
+
* from it (falling back to `message` for any channel the template did not
|
|
35
|
+
* define), so iOS (`APNS`) and Android (`GCM`) devices can receive
|
|
36
|
+
* platform-specific copy.
|
|
37
|
+
*/
|
|
38
|
+
export declare const deliverToProfile: (deps: DeliveryDeps, target: ProfileTarget, message: PushMessage, perChannel?: Partial<Record<PushChannelType, PushMessage>>) => Promise<ProfileDeliveryResult>;
|
|
39
|
+
/**
|
|
40
|
+
* Deliver to every targeted profile, aggregating a per-profile summary. Each
|
|
41
|
+
* profile's copy is resolved as: the rendered Q Connect PUSH template (per
|
|
42
|
+
* platform), falling back to the safe DEFAULT copy (`DEFAULT_PUSH_TITLE` /
|
|
43
|
+
* `DEFAULT_PUSH_BODY`) for any channel the template did not resolve for
|
|
44
|
+
* (no template, render miss, or the unresolved-placeholder guard rejected it).
|
|
45
|
+
* Profiles are processed sequentially to keep the per-profile Customer Profiles
|
|
46
|
+
* write ordering simple; batches are typically small per Journey invocation.
|
|
47
|
+
*/
|
|
48
|
+
export declare const deliverToTargets: (deps: DeliveryDeps, parsed: ParsedPushEvent) => Promise<PushDeliveryResponse>;
|
|
49
|
+
//# sourceMappingURL=delivery.d.ts.map
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { deliverToDevice } from './eum_client.js';
|
|
4
|
+
import { deleteDevice, listDevices } from './device_lookup.js';
|
|
5
|
+
import { normalizeChannelType } from './payload.js';
|
|
6
|
+
import { renderProfileChannelMessages, } from './message_template.js';
|
|
7
|
+
/**
|
|
8
|
+
* Resolve a single profile's registered devices and push the message to each
|
|
9
|
+
* via AWS End User Messaging, then clean up any device whose token was
|
|
10
|
+
* permanently rejected (stale-token cleanup).
|
|
11
|
+
*
|
|
12
|
+
* A device with an unsupported / missing channel (post-normalization) is
|
|
13
|
+
* recorded as a `SKIPPED` failure rather than being sent. A device whose
|
|
14
|
+
* delivery returns `PERMANENT_FAILURE` has its AmplifyDevice object deleted;
|
|
15
|
+
* the per-device result records whether that cleanup succeeded.
|
|
16
|
+
*
|
|
17
|
+
* `message` is the profile's fallback copy. When `perChannel` is supplied (from
|
|
18
|
+
* a rendered Q Connect template), the message for a device's channel is taken
|
|
19
|
+
* from it (falling back to `message` for any channel the template did not
|
|
20
|
+
* define), so iOS (`APNS`) and Android (`GCM`) devices can receive
|
|
21
|
+
* platform-specific copy.
|
|
22
|
+
*/
|
|
23
|
+
export const deliverToProfile = async (deps, target, message, perChannel) => {
|
|
24
|
+
const { profiles, pinpoint, domainName, applicationId } = deps;
|
|
25
|
+
const devices = await listDevices(profiles, domainName, target.profileId);
|
|
26
|
+
const results = [];
|
|
27
|
+
let delivered = 0;
|
|
28
|
+
let failed = 0;
|
|
29
|
+
let cleaned = 0;
|
|
30
|
+
for (const device of devices) {
|
|
31
|
+
const channelType = normalizeChannelType(device.channelType);
|
|
32
|
+
if (!channelType) {
|
|
33
|
+
failed += 1;
|
|
34
|
+
results.push({
|
|
35
|
+
deviceToken: device.deviceToken,
|
|
36
|
+
channelType: 'GCM',
|
|
37
|
+
objectUniqueKey: device.objectUniqueKey,
|
|
38
|
+
status: 'SKIPPED',
|
|
39
|
+
delivered: false,
|
|
40
|
+
stale: false,
|
|
41
|
+
statusMessage: `Unsupported or missing channelType: ${device.channelType ?? '(none)'}`,
|
|
42
|
+
});
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const channelMessage = perChannel?.[channelType] ?? message;
|
|
46
|
+
const outcome = await deliverToDevice(pinpoint, applicationId, device.deviceToken, channelType, channelMessage);
|
|
47
|
+
outcome.objectUniqueKey = device.objectUniqueKey;
|
|
48
|
+
results.push(outcome);
|
|
49
|
+
if (outcome.delivered) {
|
|
50
|
+
delivered += 1;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
failed += 1;
|
|
54
|
+
}
|
|
55
|
+
if (outcome.stale) {
|
|
56
|
+
// Cleanup decision only — no profile id or device token. `objectUniqueKey`
|
|
57
|
+
// is an opaque service-generated key needed to correlate the delete.
|
|
58
|
+
console.log('[push] cleanup.delete', JSON.stringify({
|
|
59
|
+
objectUniqueKey: device.objectUniqueKey,
|
|
60
|
+
channelType,
|
|
61
|
+
reason: outcome.statusMessage ?? outcome.status,
|
|
62
|
+
}));
|
|
63
|
+
const deletedOk = await deleteDevice(profiles, domainName, target.profileId, device.objectUniqueKey);
|
|
64
|
+
if (deletedOk) {
|
|
65
|
+
cleaned += 1;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
profileId: target.profileId,
|
|
71
|
+
delivered,
|
|
72
|
+
failed,
|
|
73
|
+
cleaned,
|
|
74
|
+
devices: results,
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Deliver to every targeted profile, aggregating a per-profile summary. Each
|
|
79
|
+
* profile's copy is resolved as: the rendered Q Connect PUSH template (per
|
|
80
|
+
* platform), falling back to the safe DEFAULT copy (`DEFAULT_PUSH_TITLE` /
|
|
81
|
+
* `DEFAULT_PUSH_BODY`) for any channel the template did not resolve for
|
|
82
|
+
* (no template, render miss, or the unresolved-placeholder guard rejected it).
|
|
83
|
+
* Profiles are processed sequentially to keep the per-profile Customer Profiles
|
|
84
|
+
* write ordering simple; batches are typically small per Journey invocation.
|
|
85
|
+
*/
|
|
86
|
+
export const deliverToTargets = async (deps, parsed) => {
|
|
87
|
+
const results = [];
|
|
88
|
+
for (const target of parsed.targets) {
|
|
89
|
+
// The safe DEFAULT copy is the ONLY fallback: real journeys carry no
|
|
90
|
+
// per-profile or event-level message copy, so personalized copy comes
|
|
91
|
+
// solely from the rendered template below.
|
|
92
|
+
const fallback = parsed.message;
|
|
93
|
+
// When a Q Connect PUSH template was resolved for this journey run, render
|
|
94
|
+
// it per profile to get personalized, per-platform (APNS / GCM) copy that
|
|
95
|
+
// takes precedence over the default fallback. A render miss/failure (or a
|
|
96
|
+
// placeholder-guard rejection) leaves `perChannel` undefined so delivery
|
|
97
|
+
// uses the default copy.
|
|
98
|
+
let perChannel;
|
|
99
|
+
if (deps.templateContext) {
|
|
100
|
+
perChannel = await renderProfileChannelMessages(deps.templateContext, target);
|
|
101
|
+
}
|
|
102
|
+
// Operational signal only: whether a template applied and which channels it
|
|
103
|
+
// resolved copy for. The rendered / default title and body are NOT logged
|
|
104
|
+
// (they echo personalized customer copy); enable debug logging on the
|
|
105
|
+
// template renderer if the actual copy must be inspected.
|
|
106
|
+
console.log('[push] resolveMessage', JSON.stringify({
|
|
107
|
+
templateApplied: Boolean(perChannel),
|
|
108
|
+
channelsResolved: perChannel ? Object.keys(perChannel) : [],
|
|
109
|
+
}));
|
|
110
|
+
results.push(await deliverToProfile(deps, target, fallback, perChannel));
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
profilesProcessed: results.length,
|
|
114
|
+
totalDelivered: results.reduce((n, r) => n + r.delivered, 0),
|
|
115
|
+
totalFailed: results.reduce((n, r) => n + r.failed, 0),
|
|
116
|
+
totalCleaned: results.reduce((n, r) => n + r.cleaned, 0),
|
|
117
|
+
results,
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVsaXZlcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGFtYmRhL3B1c2gvZGVsaXZlcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEscUVBQXFFO0FBQ3JFLHNDQUFzQztBQUt0QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDbEQsT0FBTyxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMvRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDcEQsT0FBTyxFQUVMLDRCQUE0QixHQUM3QixNQUFNLHVCQUF1QixDQUFDO0FBNkIvQjs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSCxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxLQUFLLEVBQ25DLElBQWtCLEVBQ2xCLE1BQXFCLEVBQ3JCLE9BQW9CLEVBQ3BCLFVBQTBELEVBQzFCLEVBQUU7SUFDbEMsTUFBTSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLGFBQWEsRUFBRSxHQUFHLElBQUksQ0FBQztJQUMvRCxNQUFNLE9BQU8sR0FBRyxNQUFNLFdBQVcsQ0FBQyxRQUFRLEVBQUUsVUFBVSxFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUUxRSxNQUFNLE9BQU8sR0FBMkIsRUFBRSxDQUFDO0lBQzNDLElBQUksU0FBUyxHQUFHLENBQUMsQ0FBQztJQUNsQixJQUFJLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDZixJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUM7SUFFaEIsS0FBSyxNQUFNLE1BQU0sSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUM3QixNQUFNLFdBQVcsR0FBRyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDN0QsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ2pCLE1BQU0sSUFBSSxDQUFDLENBQUM7WUFDWixPQUFPLENB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QyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7U0FDNUQsQ0FBQyxDQUNILENBQUM7UUFDRixPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sZ0JBQWdCLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUMzRSxDQUFDO0lBRUQsT0FBTztRQUNMLGlCQUFpQixFQUFFLE9BQU8sQ0FBQyxNQUFNO1FBQ2pDLGNBQWMsRUFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDO1FBQzVELFdBQVcsRUFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3RELFlBQVksRUFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQ3hELE9BQU87S0FDUixDQUFDO0FBQ0osQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBDdXN0b21lclByb2ZpbGVzQ2xpZW50IH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWN1c3RvbWVyLXByb2ZpbGVzJztcbmltcG9ydCB7IFBpbnBvaW50Q2xpZW50IH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXBpbnBvaW50JztcblxuaW1wb3J0IHsgZGVsaXZlclRvRGV2aWNlIH0gZnJvbSAnLi9ldW1fY2xpZW50LmpzJztcbmltcG9ydCB7IGRlbGV0ZURldmljZSwgbGlzdERldmljZXMgfSBmcm9tICcuL2RldmljZV9sb29rdXAuanMnO1xuaW1wb3J0IHsgbm9ybWFsaXplQ2hhbm5lbFR5cGUgfSBmcm9tICcuL3BheWxvYWQuanMnO1xuaW1wb3J0IHtcbiAgUHVzaFRlbXBsYXRlQ29udGV4dCxcbiAgcmVuZGVyUHJvZmlsZUNoYW5uZWxNZXNzYWdlcyxcbn0gZnJvbSAnLi9tZXNzYWdlX3RlbXBsYXRlLmpzJztcbmltcG9ydCB7XG4gIERldmljZURlbGl2ZXJ5UmVzdWx0LFxuICBQYXJzZWRQdXNoRXZlbnQsXG4gIFByb2ZpbGVEZWxpdmVyeVJlc3VsdCxcbiAgUHJvZmlsZVRhcmdldCxcbiAgUHVzaENoYW5uZWxUeXBlLFxuICBQdXNoRGVsaXZlcnlSZXNwb25zZSxcbiAgUHVzaE1lc3NhZ2UsXG59IGZyb20gJy4vdHlwZXMuanMnO1xuXG4vKiogSW5qZWN0ZWQgY2xpZW50cyArIHJlc29sdmVkIGNvbmZpZyBmb3IgdGhlIGRlbGl2ZXJ5IHJvdXRpbmVzLiAqL1xuZXhwb3J0IHR5cGUgRGVsaXZlcnlEZXBzID0ge1xuICBwcm9maWxlczogQ3VzdG9tZXJQcm9maWxlc0NsaWVudDtcbiAgcGlucG9pbnQ6IFBpbnBvaW50Q2xpZW50O1xuICAvKiogQ3VzdG9tZXIgUHJvZmlsZXMgZG9tYWluIHRvIHJlc29sdmUgZGV2aWNlcyBmcm9tLiAqL1xuICBkb21haW5OYW1lOiBzdHJpbmc7XG4gIC8qKiBBV1MgRW5kIFVzZXIgTWVzc2FnaW5nIC8gUGlucG9pbnQgYXBwbGljYXRpb24gaWQgdG8gc2VuZCBmcm9tLiAqL1xuICBhcHBsaWNhdGlvbklkOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgcmVzb2x2ZWQgUSBpbiBDb25uZWN0IFBVU0ggbWVzc2FnZSB0ZW1wbGF0ZSBmb3IgdGhpcyBqb3VybmV5IHJ1biwgd2hlblxuICAgKiBvbmUgd2FzIGZvdW5kIChzZWUge0BsaW5rIHJlc29sdmVQdXNoVGVtcGxhdGVDb250ZXh0fSkuIFdoZW4gcHJlc2VudCwgZWFjaFxuICAgKiBwcm9maWxlJ3MgY29weSBpcyByZW5kZXJlZCBmcm9tIHRoZSB0ZW1wbGF0ZSAocGVyLXBsYXRmb3JtKSBhbmQgdGFrZXNcbiAgICogcHJlY2VkZW5jZSBvdmVyIHRoZSBzYWZlIERFRkFVTFQgY29weTsgd2hlbiBhYnNlbnQsIGRlbGl2ZXJ5IHVzZXMgdGhlXG4gICAqIERFRkFVTFQgY29weSBmb3IgZXZlcnkgY2hhbm5lbC5cbiAgICovXG4gIHRlbXBsYXRlQ29udGV4dD86IFB1c2hUZW1wbGF0ZUNvbnRleHQ7XG59O1xuXG4vKipcbiAqIFJlc29sdmUgYSBzaW5nbGUgcHJvZmlsZSdzIHJlZ2lzdGVyZWQgZGV2aWNlcyBhbmQgcHVzaCB0aGUgbWVzc2FnZSB0byBlYWNoXG4gKiB2aWEgQVdTIEVuZCBVc2VyIE1lc3NhZ2luZywgdGhlbiBjbGVhbiB1cCBhbnkgZGV2aWNlIHdob3NlIHRva2VuIHdhc1xuICogcGVybWFuZW50bHkgcmVqZWN0ZWQgKHN0YWxlLXRva2VuIGNsZWFudXApLlxuICpcbiAqIEEgZGV2aWNlIHdpdGggYW4gdW5zdXBwb3J0ZWQgLyBtaXNzaW5nIGNoYW5uZWwgKHBvc3Qtbm9ybWFsaXphdGlvbikgaXNcbiAqIHJlY29yZGVkIGFzIGEgYFNLSVBQRURgIGZhaWx1cmUgcmF0aGVyIHRoYW4gYmVpbmcgc2VudC4gQSBkZXZpY2Ugd2hvc2VcbiAqIGRlbGl2ZXJ5IHJldHVybnMgYFBFUk1BTkVOVF9GQUlMVVJFYCBoYXMgaXRzIEFtcGxpZnlEZXZpY2Ugb2JqZWN0IGRlbGV0ZWQ7XG4gKiB0aGUgcGVyLWRldmljZSByZXN1bHQgcmVjb3JkcyB3aGV0aGVyIHRoYXQgY2xlYW51cCBzdWNjZWVkZWQuXG4gKlxuICogYG1lc3NhZ2VgIGlzIHRoZSBwcm9maWxlJ3MgZmFsbGJhY2sgY29weS4gV2hlbiBgcGVyQ2hhbm5lbGAgaXMgc3VwcGxpZWQgKGZyb21cbiAqIGEgcmVuZGVyZWQgUSBDb25uZWN0IHRlbXBsYXRlKSwgdGhlIG1lc3NhZ2UgZm9yIGEgZGV2aWNlJ3MgY2hhbm5lbCBpcyB0YWtlblxuICogZnJvbSBpdCAoZmFsbGluZyBiYWNrIHRvIGBtZXNzYWdlYCBmb3IgYW55IGNoYW5uZWwgdGhlIHRlbXBsYXRlIGRpZCBub3RcbiAqIGRlZmluZSksIHNvIGlPUyAoYEFQTlNgKSBhbmQgQW5kcm9pZCAoYEdDTWApIGRldmljZXMgY2FuIHJlY2VpdmVcbiAqIHBsYXRmb3JtLXNwZWNpZmljIGNvcHkuXG4gKi9cbmV4cG9ydCBjb25zdCBkZWxpdmVyVG9Qcm9maWxlID0gYXN5bmMgKFxuICBkZXBzOiBEZWxpdmVyeURlcHMsXG4gIHRhcmdldDogUHJvZmlsZVRhcmdldCxcbiAgbWVzc2FnZTogUHVzaE1lc3NhZ2UsXG4gIHBlckNoYW5uZWw/OiBQYXJ0aWFsPFJlY29yZDxQdXNoQ2hhbm5lbFR5cGUsIFB1c2hNZXNzYWdlPj4sXG4pOiBQcm9taXNlPFByb2ZpbGVEZWxpdmVyeVJlc3VsdD4gPT4ge1xuICBjb25zdCB7IHByb2ZpbGVzLCBwaW5wb2ludCwgZG9tYWluTmFtZSwgYXBwbGljYXRpb25JZCB9ID0gZGVwcztcbiAgY29uc3QgZGV2aWNlcyA9IGF3YWl0IGxpc3REZXZpY2VzKHByb2ZpbGVzLCBkb21haW5OYW1lLCB0YXJnZXQucHJvZmlsZUlkKTtcblxuICBjb25zdCByZXN1bHRzOiBEZXZpY2VEZWxpdmVyeVJlc3VsdFtdID0gW107XG4gIGxldCBkZWxpdmVyZWQgPSAwO1xuICBsZXQgZmFpbGVkID0gMDtcbiAgbGV0IGNsZWFuZWQgPSAwO1xuXG4gIGZvciAoY29uc3QgZGV2aWNlIG9mIGRldmljZXMpIHtcbiAgICBjb25zdCBjaGFubmVsVHlwZSA9IG5vcm1hbGl6ZUNoYW5uZWxUeXBlKGRldmljZS5jaGFubmVsVHlwZSk7XG4gICAgaWYgKCFjaGFubmVsVHlwZSkge1xuICAgICAgZmFpbGVkICs9IDE7XG4gICAgICByZXN1bHRzLnB1c2goe1xuICAgICAgICBkZXZpY2VUb2tlbjogZGV2aWNlLmRldmljZVRva2VuLFxuICAgICAgICBjaGFubmVsVHlwZTogJ0dDTScsXG4gICAgICAgIG9iamVjdFVuaXF1ZUtleTogZGV2aWNlLm9iamVjdFVuaXF1ZUtleSxcbiAgICAgICAgc3RhdHVzOiAnU0tJUFBFRCcsXG4gICAgICAgIGRlbGl2ZXJlZDogZmFsc2UsXG4gICAgICAgIHN0YWxlOiBmYWxzZSxcbiAgICAgICAgc3RhdHVzTWVzc2FnZTogYFVuc3VwcG9ydGVkIG9yIG1pc3NpbmcgY2hhbm5lbFR5cGU6ICR7XG4gICAgICAgICAgZGV2aWNlLmNoYW5uZWxUeXBlID8/ICcobm9uZSknXG4gICAgICAgIH1gLFxuICAgICAgfSk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBjb25zdCBjaGFubmVsTWVzc2FnZSA9IHBlckNoYW5uZWw/LltjaGFubmVsVHlwZV0gPz8gbWVzc2FnZTtcbiAgICBjb25zdCBvdXRjb21lID0gYXdhaXQgZGVsaXZlclRvRGV2aWNlKFxuICAgICAgcGlucG9pbnQsXG4gICAgICBhcHBsaWNhdGlvbklkLFxuICAgICAgZGV2aWNlLmRldmljZVRva2VuLFxuICAgICAgY2hhbm5lbFR5cGUsXG4gICAgICBjaGFubmVsTWVzc2FnZSxcbiAgICApO1xuICAgIG91dGNvbWUub2JqZWN0VW5pcXVlS2V5ID0gZGV2aWNlLm9iamVjdFVuaXF1ZUtleTtcbiAgICByZXN1bHRzLnB1c2gob3V0Y29tZSk7XG5cbiAgICBpZiAob3V0Y29tZS5kZWxpdmVyZWQpIHtcbiAgICAgIGRlbGl2ZXJlZCArPSAxO1xuICAgIH0gZWxzZSB7XG4gICAgICBmYWlsZWQgKz0gMTtcbiAgICB9XG5cbiAgICBpZiAob3V0Y29tZS5zdGFsZSkge1xuICAgICAgLy8gQ2xlYW51cCBkZWNpc2lvbiBvbmx5IOKAlCBubyBwcm9maWxlIGlkIG9yIGRldmljZSB0b2tlbi4gYG9iamVjdFVuaXF1ZUtleWBcbiAgICAgIC8vIGlzIGFuIG9wYXF1ZSBzZXJ2aWNlLWdlbmVyYXRlZCBrZXkgbmVlZGVkIHRvIGNvcnJlbGF0ZSB0aGUgZGVsZXRlLlxuICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICdbcHVzaF0gY2xlYW51cC5kZWxldGUnLFxuICAgICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgb2JqZWN0VW5pcXVlS2V5OiBkZXZpY2Uub2JqZWN0VW5pcXVlS2V5LFxuICAgICAgICAgIGNoYW5uZWxUeXBlLFxuICAgICAgICAgIHJlYXNvbjogb3V0Y29tZS5zdGF0dXNNZXNzYWdlID8/IG91dGNvbWUuc3RhdHVzLFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgICBjb25zdCBkZWxldGVkT2sgPSBhd2FpdCBkZWxldGVEZXZpY2UoXG4gICAgICAgIHByb2ZpbGVzLFxuICAgICAgICBkb21haW5OYW1lLFxuICAgICAgICB0YXJnZXQucHJvZmlsZUlkLFxuICAgICAgICBkZXZpY2Uub2JqZWN0VW5pcXVlS2V5LFxuICAgICAgKTtcbiAgICAgIGlmIChkZWxldGVkT2spIHtcbiAgICAgICAgY2xlYW5lZCArPSAxO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgcHJvZmlsZUlkOiB0YXJnZXQucHJvZmlsZUlkLFxuICAgIGRlbGl2ZXJlZCxcbiAgICBmYWlsZWQsXG4gICAgY2xlYW5lZCxcbiAgICBkZXZpY2VzOiByZXN1bHRzLFxuICB9O1xufTtcblxuLyoqXG4gKiBEZWxpdmVyIHRvIGV2ZXJ5IHRhcmdldGVkIHByb2ZpbGUsIGFnZ3JlZ2F0aW5nIGEgcGVyLXByb2ZpbGUgc3VtbWFyeS4gRWFjaFxuICogcHJvZmlsZSdzIGNvcHkgaXMgcmVzb2x2ZWQgYXM6IHRoZSByZW5kZXJlZCBRIENvbm5lY3QgUFVTSCB0ZW1wbGF0ZSAocGVyXG4gKiBwbGF0Zm9ybSksIGZhbGxpbmcgYmFjayB0byB0aGUgc2FmZSBERUZBVUxUIGNvcHkgKGBERUZBVUxUX1BVU0hfVElUTEVgIC9cbiAqIGBERUZBVUxUX1BVU0hfQk9EWWApIGZvciBhbnkgY2hhbm5lbCB0aGUgdGVtcGxhdGUgZGlkIG5vdCByZXNvbHZlIGZvclxuICogKG5vIHRlbXBsYXRlLCByZW5kZXIgbWlzcywgb3IgdGhlIHVucmVzb2x2ZWQtcGxhY2Vob2xkZXIgZ3VhcmQgcmVqZWN0ZWQgaXQpLlxuICogUHJvZmlsZXMgYXJlIHByb2Nlc3NlZCBzZXF1ZW50aWFsbHkgdG8ga2VlcCB0aGUgcGVyLXByb2ZpbGUgQ3VzdG9tZXIgUHJvZmlsZXNcbiAqIHdyaXRlIG9yZGVyaW5nIHNpbXBsZTsgYmF0Y2hlcyBhcmUgdHlwaWNhbGx5IHNtYWxsIHBlciBKb3VybmV5IGludm9jYXRpb24uXG4gKi9cbmV4cG9ydCBjb25zdCBkZWxpdmVyVG9UYXJnZXRzID0gYXN5bmMgKFxuICBkZXBzOiBEZWxpdmVyeURlcHMsXG4gIHBhcnNlZDogUGFyc2VkUHVzaEV2ZW50LFxuKTogUHJvbWlzZTxQdXNoRGVsaXZlcnlSZXNwb25zZT4gPT4ge1xuICBjb25zdCByZXN1bHRzOiBQcm9maWxlRGVsaXZlcnlSZXN1bHRbXSA9IFtdO1xuICBmb3IgKGNvbnN0IHRhcmdldCBvZiBwYXJzZWQudGFyZ2V0cykge1xuICAgIC8vIFRoZSBzYWZlIERFRkFVTFQgY29weSBpcyB0aGUgT05MWSBmYWxsYmFjazogcmVhbCBqb3VybmV5cyBjYXJyeSBub1xuICAgIC8vIHBlci1wcm9maWxlIG9yIGV2ZW50LWxldmVsIG1lc3NhZ2UgY29weSwgc28gcGVyc29uYWxpemVkIGNvcHkgY29tZXNcbiAgICAvLyBzb2xlbHkgZnJvbSB0aGUgcmVuZGVyZWQgdGVtcGxhdGUgYmVsb3cuXG4gICAgY29uc3QgZmFsbGJhY2sgPSBwYXJzZWQubWVzc2FnZTtcblxuICAgIC8vIFdoZW4gYSBRIENvbm5lY3QgUFVTSCB0ZW1wbGF0ZSB3YXMgcmVzb2x2ZWQgZm9yIHRoaXMgam91cm5leSBydW4sIHJlbmRlclxuICAgIC8vIGl0IHBlciBwcm9maWxlIHRvIGdldCBwZXJzb25hbGl6ZWQsIHBlci1wbGF0Zm9ybSAoQVBOUyAvIEdDTSkgY29weSB0aGF0XG4gICAgLy8gdGFrZXMgcHJlY2VkZW5jZSBvdmVyIHRoZSBkZWZhdWx0IGZhbGxiYWNrLiBBIHJlbmRlciBtaXNzL2ZhaWx1cmUgKG9yIGFcbiAgICAvLyBwbGFjZWhvbGRlci1ndWFyZCByZWplY3Rpb24pIGxlYXZlcyBgcGVyQ2hhbm5lbGAgdW5kZWZpbmVkIHNvIGRlbGl2ZXJ5XG4gICAgLy8gdXNlcyB0aGUgZGVmYXVsdCBjb3B5LlxuICAgIGxldCBwZXJDaGFubmVsOiBQYXJ0aWFsPFJlY29yZDxQdXNoQ2hhbm5lbFR5cGUsIFB1c2hNZXNzYWdlPj4gfCB1bmRlZmluZWQ7XG4gICAgaWYgKGRlcHMudGVtcGxhdGVDb250ZXh0KSB7XG4gICAgICBwZXJDaGFubmVsID0gYXdhaXQgcmVuZGVyUHJvZmlsZUNoYW5uZWxNZXNzYWdlcyhcbiAgICAgICAgZGVwcy50ZW1wbGF0ZUNvbnRleHQsXG4gICAgICAgIHRhcmdldCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gT3BlcmF0aW9uYWwgc2lnbmFsIG9ubHk6IHdoZXRoZXIgYSB0ZW1wbGF0ZSBhcHBsaWVkIGFuZCB3aGljaCBjaGFubmVscyBpdFxuICAgIC8vIHJlc29sdmVkIGNvcHkgZm9yLiBUaGUgcmVuZGVyZWQgLyBkZWZhdWx0IHRpdGxlIGFuZCBib2R5IGFyZSBOT1QgbG9nZ2VkXG4gICAgLy8gKHRoZXkgZWNobyBwZXJzb25hbGl6ZWQgY3VzdG9tZXIgY29weSk7IGVuYWJsZSBkZWJ1ZyBsb2dnaW5nIG9uIHRoZVxuICAgIC8vIHRlbXBsYXRlIHJlbmRlcmVyIGlmIHRoZSBhY3R1YWwgY29weSBtdXN0IGJlIGluc3BlY3RlZC5cbiAgICBjb25zb2xlLmxvZyhcbiAgICAgICdbcHVzaF0gcmVzb2x2ZU1lc3NhZ2UnLFxuICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICB0ZW1wbGF0ZUFwcGxpZWQ6IEJvb2xlYW4ocGVyQ2hhbm5lbCksXG4gICAgICAgIGNoYW5uZWxzUmVzb2x2ZWQ6IHBlckNoYW5uZWwgPyBPYmplY3Qua2V5cyhwZXJDaGFubmVsKSA6IFtdLFxuICAgICAgfSksXG4gICAgKTtcbiAgICByZXN1bHRzLnB1c2goYXdhaXQgZGVsaXZlclRvUHJvZmlsZShkZXBzLCB0YXJnZXQsIGZhbGxiYWNrLCBwZXJDaGFubmVsKSk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHByb2ZpbGVzUHJvY2Vzc2VkOiByZXN1bHRzLmxlbmd0aCxcbiAgICB0b3RhbERlbGl2ZXJlZDogcmVzdWx0cy5yZWR1Y2UoKG4sIHIpID0+IG4gKyByLmRlbGl2ZXJlZCwgMCksXG4gICAgdG90YWxGYWlsZWQ6IHJlc3VsdHMucmVkdWNlKChuLCByKSA9PiBuICsgci5mYWlsZWQsIDApLFxuICAgIHRvdGFsQ2xlYW5lZDogcmVzdWx0cy5yZWR1Y2UoKG4sIHIpID0+IG4gKyByLmNsZWFuZWQsIDApLFxuICAgIHJlc3VsdHMsXG4gIH07XG59O1xuIl19
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { CustomerProfilesClient } from '@aws-sdk/client-customer-profiles';
|
|
2
|
+
/** A registered device resolved from the profile's AmplifyDevice objects. */
|
|
3
|
+
export type ResolvedDevice = {
|
|
4
|
+
/** The mutable push token / endpoint address. */
|
|
5
|
+
deviceToken: string;
|
|
6
|
+
/** The stored channel identifier (raw, pre-normalization). */
|
|
7
|
+
channelType?: string;
|
|
8
|
+
/** The stable device id, if present (for logging / diagnostics). */
|
|
9
|
+
deviceId?: string;
|
|
10
|
+
/**
|
|
11
|
+
* The service-generated ProfileObjectUniqueKey — required to delete the
|
|
12
|
+
* object during stale-token cleanup.
|
|
13
|
+
*/
|
|
14
|
+
objectUniqueKey: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Resolve every registered device for a profile by paging through its
|
|
18
|
+
* AmplifyDevice objects (ListProfileObjects) and extracting the push token +
|
|
19
|
+
* channel + the ProfileObjectUniqueKey (needed for deletion).
|
|
20
|
+
*
|
|
21
|
+
* Device objects missing a token are skipped. Malformed stored objects are
|
|
22
|
+
* ignored rather than aborting the whole profile. Wrapped in
|
|
23
|
+
* {@link withTransientRetry} so transient throttling is retried with backoff.
|
|
24
|
+
*/
|
|
25
|
+
export declare const listDevices: (profiles: CustomerProfilesClient, domainName: string, profileId: string) => Promise<ResolvedDevice[]>;
|
|
26
|
+
/**
|
|
27
|
+
* Delete a single AmplifyDevice object (stale-token cleanup) after its token
|
|
28
|
+
* was permanently rejected. Best-effort: a failed delete is swallowed so it
|
|
29
|
+
* never masks the delivery result — the object simply lingers until the next
|
|
30
|
+
* cleanup or its TTL expiry.
|
|
31
|
+
*
|
|
32
|
+
* Returns `true` when the delete succeeded, `false` otherwise.
|
|
33
|
+
*/
|
|
34
|
+
export declare const deleteDevice: (profiles: CustomerProfilesClient, domainName: string, profileId: string, objectUniqueKey: string) => Promise<boolean>;
|
|
35
|
+
//# sourceMappingURL=device_lookup.d.ts.map
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { DeleteProfileObjectCommand, ListProfileObjectsCommand, } from '@aws-sdk/client-customer-profiles';
|
|
4
|
+
import { OBJECT_TYPE_DEVICE } from '../../constants.js';
|
|
5
|
+
import { withTransientRetry } from '../shared/retry.js';
|
|
6
|
+
/**
|
|
7
|
+
* Resolve every registered device for a profile by paging through its
|
|
8
|
+
* AmplifyDevice objects (ListProfileObjects) and extracting the push token +
|
|
9
|
+
* channel + the ProfileObjectUniqueKey (needed for deletion).
|
|
10
|
+
*
|
|
11
|
+
* Device objects missing a token are skipped. Malformed stored objects are
|
|
12
|
+
* ignored rather than aborting the whole profile. Wrapped in
|
|
13
|
+
* {@link withTransientRetry} so transient throttling is retried with backoff.
|
|
14
|
+
*/
|
|
15
|
+
export const listDevices = async (profiles, domainName, profileId) => {
|
|
16
|
+
const devices = [];
|
|
17
|
+
let nextToken;
|
|
18
|
+
do {
|
|
19
|
+
const res = await withTransientRetry(() => profiles.send(new ListProfileObjectsCommand({
|
|
20
|
+
DomainName: domainName,
|
|
21
|
+
ObjectTypeName: OBJECT_TYPE_DEVICE,
|
|
22
|
+
ProfileId: profileId,
|
|
23
|
+
NextToken: nextToken,
|
|
24
|
+
})));
|
|
25
|
+
for (const item of res.Items ?? []) {
|
|
26
|
+
const uniqueKey = item.ProfileObjectUniqueKey;
|
|
27
|
+
if (!item.Object || !uniqueKey) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
let parsed;
|
|
31
|
+
try {
|
|
32
|
+
parsed = JSON.parse(item.Object);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const deviceToken = typeof parsed.deviceToken === 'string' ? parsed.deviceToken : undefined;
|
|
38
|
+
if (!deviceToken) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
devices.push({
|
|
42
|
+
deviceToken,
|
|
43
|
+
channelType: typeof parsed.channelType === 'string'
|
|
44
|
+
? parsed.channelType
|
|
45
|
+
: undefined,
|
|
46
|
+
deviceId: typeof parsed.deviceId === 'string' ? parsed.deviceId : undefined,
|
|
47
|
+
objectUniqueKey: uniqueKey,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
nextToken = res.NextToken;
|
|
51
|
+
} while (nextToken);
|
|
52
|
+
// Operational signal only: how many devices resolved and their channel types
|
|
53
|
+
// (non-personal). Profile id, device ids and tokens are NOT logged.
|
|
54
|
+
console.log('[push] devices.resolved', JSON.stringify({
|
|
55
|
+
count: devices.length,
|
|
56
|
+
channelTypes: devices.map((d) => d.channelType ?? '(none)'),
|
|
57
|
+
}));
|
|
58
|
+
return devices;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Delete a single AmplifyDevice object (stale-token cleanup) after its token
|
|
62
|
+
* was permanently rejected. Best-effort: a failed delete is swallowed so it
|
|
63
|
+
* never masks the delivery result — the object simply lingers until the next
|
|
64
|
+
* cleanup or its TTL expiry.
|
|
65
|
+
*
|
|
66
|
+
* Returns `true` when the delete succeeded, `false` otherwise.
|
|
67
|
+
*/
|
|
68
|
+
export const deleteDevice = async (profiles, domainName, profileId, objectUniqueKey) => {
|
|
69
|
+
try {
|
|
70
|
+
await withTransientRetry(() => profiles.send(new DeleteProfileObjectCommand({
|
|
71
|
+
DomainName: domainName,
|
|
72
|
+
ProfileId: profileId,
|
|
73
|
+
ObjectTypeName: OBJECT_TYPE_DEVICE,
|
|
74
|
+
ProfileObjectUniqueKey: objectUniqueKey,
|
|
75
|
+
})));
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
// Log the failure name / object key only — no profile id and no raw error
|
|
80
|
+
// object (which can carry request content).
|
|
81
|
+
console.error('[push] cleanup.deleteFailed', JSON.stringify({
|
|
82
|
+
objectUniqueKey,
|
|
83
|
+
error: err instanceof Error ? err.name : 'unknown',
|
|
84
|
+
}));
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV2aWNlX2xvb2t1cC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sYW1iZGEvcHVzaC9kZXZpY2VfbG9va3VwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHFFQUFxRTtBQUNyRSxzQ0FBc0M7QUFFdEMsT0FBTyxFQUVMLDBCQUEwQixFQUMxQix5QkFBeUIsR0FDMUIsTUFBTSxtQ0FBbUMsQ0FBQztBQUUzQyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQWlCeEQ7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsTUFBTSxXQUFXLEdBQUcsS0FBSyxFQUM5QixRQUFnQyxFQUNoQyxVQUFrQixFQUNsQixTQUFpQixFQUNVLEVBQUU7SUFDN0IsTUFBTSxPQUFPLEdBQXFCLEVBQUUsQ0FBQztJQUNyQyxJQUFJLFNBQTZCLENBQUM7SUFFbEMsR0FBRyxDQUFDO1FBQ0YsTUFBTSxHQUFHLEdBQUcsTUFBTSxrQkFBa0IsQ0FBQyxHQUFHLEVBQUUsQ0FDeEMsUUFBUSxDQUFDLElBQUksQ0FDWCxJQUFJLHlCQUF5QixDQUFDO1lBQzVCLFVBQVUsRUFBRSxVQUFVO1lBQ3RCLGNBQWMsRUFBRSxrQkFBa0I7WUFDbEMsU0FBUyxFQUFFLFNBQVM7WUFDcEIsU0FBUyxFQUFFLFNBQVM7U0FDckIsQ0FBQyxDQUNILENBQ0YsQ0FBQztRQUVGLEtBQUssTUFBTSxJQUFJLElBQUksR0FBRyxDQUFDLEtBQUssSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUNuQyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsc0JBQXNCLENBQUM7WUFDOUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDL0IsU0FBUztZQUNYLENBQUM7WUFDRCxJQUFJLE1BQStCLENBQUM7WUFDcEMsSUFBSSxDQUFDO2dCQUNILE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQTRCLENBQUM7WUFDOUQsQ0FBQztZQUFDLE1BQU0sQ0FBQztnQkFDUCxTQUFTO1lBQ1gsQ0FBQztZQUNELE1BQU0sV0FBVyxHQUNmLE9BQU8sTUFBTSxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztZQUMxRSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBQ2pCLFNBQVM7WUFDWCxDQUFDO1lBQ0QsT0FBTyxDQUFDLElBQUksQ0FBQztnQkFDWCxXQUFXO2dCQUNYLFdBQVcsRUFDVCxPQUFPLE1BQU0sQ0FBQyxXQUFXLEtBQUssUUFBUTtvQkFDcEMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxXQUFXO29CQUNwQixDQUFDLENBQUMsU0FBUztnQkFDZixRQUFRLEVBQ04sT0FBTyxNQUFNLENBQUMsUUFBUSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUztnQkFDbkUsZUFBZSxFQUFFLFNBQVM7YUFDM0IsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUNELFNBQVMsR0FBRyxHQUFHLENBQUMsU0FBUyxDQUFDO0lBQzVCLENBQUMsUUFBUSxTQUFTLEVBQUU7SUFFcEIsNkVBQTZFO0lBQzdFLG9FQUFvRTtJQUNwRSxPQUFPLENBQUMsR0FBRyxDQUNULHlCQUF5QixFQUN6QixJQUFJLENBQUMsU0FBUyxDQUFDO1FBQ2IsS0FBSyxFQUFFLE9BQU8sQ0FBQyxNQUFNO1FBQ3JCLFlBQVksRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxJQUFJLFFBQVEsQ0FBQztLQUM1RCxDQUFDLENBQ0gsQ0FBQztJQUVGLE9BQU8sT0FBTyxDQUFDO0FBQ2pCLENBQUMsQ0FBQztBQUVGOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLENBQUMsTUFBTSxZQUFZLEdBQUcsS0FBSyxFQUMvQixRQUFnQyxFQUNoQyxVQUFrQixFQUNsQixTQUFpQixFQUNqQixlQUF1QixFQUNMLEVBQUU7SUFDcEIsSUFBSSxDQUFDO1FBQ0gsTUFBTSxrQkFBa0IsQ0FBQyxHQUFHLEVBQUUsQ0FDNUIsUUFBUSxDQUFDLElBQUksQ0FDWCxJQUFJLDBCQUEwQixDQUFDO1lBQzdCLFVBQVUsRUFBRSxVQUFVO1lBQ3RCLFNBQVMsRUFBRSxTQUFTO1lBQ3BCLGNBQWMsRUFBRSxrQkFBa0I7WUFDbEMsc0JBQXNCLEVBQUUsZUFBZTtTQUN4QyxDQUFDLENBQ0gsQ0FDRixDQUFDO1FBQ0YsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNiLDBFQUEwRTtRQUMxRSw0Q0FBNEM7UUFDNUMsT0FBTyxDQUFDLEtBQUssQ0FDWCw2QkFBNkIsRUFDN0IsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUNiLGVBQWU7WUFDZixLQUFLLEVBQUUsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsU0FBUztTQUNuRCxDQUFDLENBQ0gsQ0FBQztRQUNGLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztBQUNILENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHtcbiAgQ3VzdG9tZXJQcm9maWxlc0NsaWVudCxcbiAgRGVsZXRlUHJvZmlsZU9iamVjdENvbW1hbmQsXG4gIExpc3RQcm9maWxlT2JqZWN0c0NvbW1hbmQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1jdXN0b21lci1wcm9maWxlcyc7XG5cbmltcG9ydCB7IE9CSkVDVF9UWVBFX0RFVklDRSB9IGZyb20gJy4uLy4uL2NvbnN0YW50cy5qcyc7XG5pbXBvcnQgeyB3aXRoVHJhbnNpZW50UmV0cnkgfSBmcm9tICcuLi9zaGFyZWQvcmV0cnkuanMnO1xuXG4vKiogQSByZWdpc3RlcmVkIGRldmljZSByZXNvbHZlZCBmcm9tIHRoZSBwcm9maWxlJ3MgQW1wbGlmeURldmljZSBvYmplY3RzLiAqL1xuZXhwb3J0IHR5cGUgUmVzb2x2ZWREZXZpY2UgPSB7XG4gIC8qKiBUaGUgbXV0YWJsZSBwdXNoIHRva2VuIC8gZW5kcG9pbnQgYWRkcmVzcy4gKi9cbiAgZGV2aWNlVG9rZW46IHN0cmluZztcbiAgLyoqIFRoZSBzdG9yZWQgY2hhbm5lbCBpZGVudGlmaWVyIChyYXcsIHByZS1ub3JtYWxpemF0aW9uKS4gKi9cbiAgY2hhbm5lbFR5cGU/OiBzdHJpbmc7XG4gIC8qKiBUaGUgc3RhYmxlIGRldmljZSBpZCwgaWYgcHJlc2VudCAoZm9yIGxvZ2dpbmcgLyBkaWFnbm9zdGljcykuICovXG4gIGRldmljZUlkPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIHNlcnZpY2UtZ2VuZXJhdGVkIFByb2ZpbGVPYmplY3RVbmlxdWVLZXkg4oCUIHJlcXVpcmVkIHRvIGRlbGV0ZSB0aGVcbiAgICogb2JqZWN0IGR1cmluZyBzdGFsZS10b2tlbiBjbGVhbnVwLlxuICAgKi9cbiAgb2JqZWN0VW5pcXVlS2V5OiBzdHJpbmc7XG59O1xuXG4vKipcbiAqIFJlc29sdmUgZXZlcnkgcmVnaXN0ZXJlZCBkZXZpY2UgZm9yIGEgcHJvZmlsZSBieSBwYWdpbmcgdGhyb3VnaCBpdHNcbiAqIEFtcGxpZnlEZXZpY2Ugb2JqZWN0cyAoTGlzdFByb2ZpbGVPYmplY3RzKSBhbmQgZXh0cmFjdGluZyB0aGUgcHVzaCB0b2tlbiArXG4gKiBjaGFubmVsICsgdGhlIFByb2ZpbGVPYmplY3RVbmlxdWVLZXkgKG5lZWRlZCBmb3IgZGVsZXRpb24pLlxuICpcbiAqIERldmljZSBvYmplY3RzIG1pc3NpbmcgYSB0b2tlbiBhcmUgc2tpcHBlZC4gTWFsZm9ybWVkIHN0b3JlZCBvYmplY3RzIGFyZVxuICogaWdub3JlZCByYXRoZXIgdGhhbiBhYm9ydGluZyB0aGUgd2hvbGUgcHJvZmlsZS4gV3JhcHBlZCBpblxuICoge0BsaW5rIHdpdGhUcmFuc2llbnRSZXRyeX0gc28gdHJhbnNpZW50IHRocm90dGxpbmcgaXMgcmV0cmllZCB3aXRoIGJhY2tvZmYuXG4gKi9cbmV4cG9ydCBjb25zdCBsaXN0RGV2aWNlcyA9IGFzeW5jIChcbiAgcHJvZmlsZXM6IEN1c3RvbWVyUHJvZmlsZXNDbGllbnQsXG4gIGRvbWFpbk5hbWU6IHN0cmluZyxcbiAgcHJvZmlsZUlkOiBzdHJpbmcsXG4pOiBQcm9taXNlPFJlc29sdmVkRGV2aWNlW10+ID0+IHtcbiAgY29uc3QgZGV2aWNlczogUmVzb2x2ZWREZXZpY2VbXSA9IFtdO1xuICBsZXQgbmV4dFRva2VuOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgZG8ge1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHdpdGhUcmFuc2llbnRSZXRyeSgoKSA9PlxuICAgICAgcHJvZmlsZXMuc2VuZChcbiAgICAgICAgbmV3IExpc3RQcm9maWxlT2JqZWN0c0NvbW1hbmQoe1xuICAgICAgICAgIERvbWFpbk5hbWU6IGRvbWFpbk5hbWUsXG4gICAgICAgICAgT2JqZWN0VHlwZU5hbWU6IE9CSkVDVF9UWVBFX0RFVklDRSxcbiAgICAgICAgICBQcm9maWxlSWQ6IHByb2ZpbGVJZCxcbiAgICAgICAgICBOZXh0VG9rZW46IG5leHRUb2tlbixcbiAgICAgICAgfSksXG4gICAgICApLFxuICAgICk7XG5cbiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgcmVzLkl0ZW1zID8/IFtdKSB7XG4gICAgICBjb25zdCB1bmlxdWVLZXkgPSBpdGVtLlByb2ZpbGVPYmplY3RVbmlxdWVLZXk7XG4gICAgICBpZiAoIWl0ZW0uT2JqZWN0IHx8ICF1bmlxdWVLZXkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBsZXQgcGFyc2VkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgIHRyeSB7XG4gICAgICAgIHBhcnNlZCA9IEpTT04ucGFyc2UoaXRlbS5PYmplY3QpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgZGV2aWNlVG9rZW4gPVxuICAgICAgICB0eXBlb2YgcGFyc2VkLmRldmljZVRva2VuID09PSAnc3RyaW5nJyA/IHBhcnNlZC5kZXZpY2VUb2tlbiA6IHVuZGVmaW5lZDtcbiAgICAgIGlmICghZGV2aWNlVG9rZW4pIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBkZXZpY2VzLnB1c2goe1xuICAgICAgICBkZXZpY2VUb2tlbixcbiAgICAgICAgY2hhbm5lbFR5cGU6XG4gICAgICAgICAgdHlwZW9mIHBhcnNlZC5jaGFubmVsVHlwZSA9PT0gJ3N0cmluZydcbiAgICAgICAgICAgID8gcGFyc2VkLmNoYW5uZWxUeXBlXG4gICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgZGV2aWNlSWQ6XG4gICAgICAgICAgdHlwZW9mIHBhcnNlZC5kZXZpY2VJZCA9PT0gJ3N0cmluZycgPyBwYXJzZWQuZGV2aWNlSWQgOiB1bmRlZmluZWQsXG4gICAgICAgIG9iamVjdFVuaXF1ZUtleTogdW5pcXVlS2V5LFxuICAgICAgfSk7XG4gICAgfVxuICAgIG5leHRUb2tlbiA9IHJlcy5OZXh0VG9rZW47XG4gIH0gd2hpbGUgKG5leHRUb2tlbik7XG5cbiAgLy8gT3BlcmF0aW9uYWwgc2lnbmFsIG9ubHk6IGhvdyBtYW55IGRldmljZXMgcmVzb2x2ZWQgYW5kIHRoZWlyIGNoYW5uZWwgdHlwZXNcbiAgLy8gKG5vbi1wZXJzb25hbCkuIFByb2ZpbGUgaWQsIGRldmljZSBpZHMgYW5kIHRva2VucyBhcmUgTk9UIGxvZ2dlZC5cbiAgY29uc29sZS5sb2coXG4gICAgJ1twdXNoXSBkZXZpY2VzLnJlc29sdmVkJyxcbiAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICBjb3VudDogZGV2aWNlcy5sZW5ndGgsXG4gICAgICBjaGFubmVsVHlwZXM6IGRldmljZXMubWFwKChkKSA9PiBkLmNoYW5uZWxUeXBlID8/ICcobm9uZSknKSxcbiAgICB9KSxcbiAgKTtcblxuICByZXR1cm4gZGV2aWNlcztcbn07XG5cbi8qKlxuICogRGVsZXRlIGEgc2luZ2xlIEFtcGxpZnlEZXZpY2Ugb2JqZWN0IChzdGFsZS10b2tlbiBjbGVhbnVwKSBhZnRlciBpdHMgdG9rZW5cbiAqIHdhcyBwZXJtYW5lbnRseSByZWplY3RlZC4gQmVzdC1lZmZvcnQ6IGEgZmFpbGVkIGRlbGV0ZSBpcyBzd2FsbG93ZWQgc28gaXRcbiAqIG5ldmVyIG1hc2tzIHRoZSBkZWxpdmVyeSByZXN1bHQg4oCUIHRoZSBvYmplY3Qgc2ltcGx5IGxpbmdlcnMgdW50aWwgdGhlIG5leHRcbiAqIGNsZWFudXAgb3IgaXRzIFRUTCBleHBpcnkuXG4gKlxuICogUmV0dXJucyBgdHJ1ZWAgd2hlbiB0aGUgZGVsZXRlIHN1Y2NlZWRlZCwgYGZhbHNlYCBvdGhlcndpc2UuXG4gKi9cbmV4cG9ydCBjb25zdCBkZWxldGVEZXZpY2UgPSBhc3luYyAoXG4gIHByb2ZpbGVzOiBDdXN0b21lclByb2ZpbGVzQ2xpZW50LFxuICBkb21haW5OYW1lOiBzdHJpbmcsXG4gIHByb2ZpbGVJZDogc3RyaW5nLFxuICBvYmplY3RVbmlxdWVLZXk6IHN0cmluZyxcbik6IFByb21pc2U8Ym9vbGVhbj4gPT4ge1xuICB0cnkge1xuICAgIGF3YWl0IHdpdGhUcmFuc2llbnRSZXRyeSgoKSA9PlxuICAgICAgcHJvZmlsZXMuc2VuZChcbiAgICAgICAgbmV3IERlbGV0ZVByb2ZpbGVPYmplY3RDb21tYW5kKHtcbiAgICAgICAgICBEb21haW5OYW1lOiBkb21haW5OYW1lLFxuICAgICAgICAgIFByb2ZpbGVJZDogcHJvZmlsZUlkLFxuICAgICAgICAgIE9iamVjdFR5cGVOYW1lOiBPQkpFQ1RfVFlQRV9ERVZJQ0UsXG4gICAgICAgICAgUHJvZmlsZU9iamVjdFVuaXF1ZUtleTogb2JqZWN0VW5pcXVlS2V5LFxuICAgICAgICB9KSxcbiAgICAgICksXG4gICAgKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgLy8gTG9nIHRoZSBmYWlsdXJlIG5hbWUgLyBvYmplY3Qga2V5IG9ubHkg4oCUIG5vIHByb2ZpbGUgaWQgYW5kIG5vIHJhdyBlcnJvclxuICAgIC8vIG9iamVjdCAod2hpY2ggY2FuIGNhcnJ5IHJlcXVlc3QgY29udGVudCkuXG4gICAgY29uc29sZS5lcnJvcihcbiAgICAgICdbcHVzaF0gY2xlYW51cC5kZWxldGVGYWlsZWQnLFxuICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICBvYmplY3RVbmlxdWVLZXksXG4gICAgICAgIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5uYW1lIDogJ3Vua25vd24nLFxuICAgICAgfSksXG4gICAgKTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn07XG4iXX0=
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { PinpointClient } from '@aws-sdk/client-pinpoint';
|
|
2
|
+
import { DeviceDeliveryResult, PushChannelType, PushMessage } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Decide whether a per-address delivery failure represents a permanently
|
|
5
|
+
* invalid TOKEN (safe to delete) versus a channel / app misconfiguration or
|
|
6
|
+
* transient error (keep the token).
|
|
7
|
+
*
|
|
8
|
+
* Conservative by design: returns `true` ONLY for a `PERMANENT_FAILURE` whose
|
|
9
|
+
* `StatusMessage` matches a known invalid-token indicator. The default for any
|
|
10
|
+
* ambiguous or unknown failure is `false` (keep the device).
|
|
11
|
+
*/
|
|
12
|
+
export declare const isInvalidTokenFailure: (status: string, statusMessage: string | undefined) => boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Deliver a single push to one device via AWS End User Messaging (Pinpoint
|
|
15
|
+
* `SendMessages`), addressing the message to the device token on its channel.
|
|
16
|
+
*
|
|
17
|
+
* Returns a structured per-device result classifying the Pinpoint
|
|
18
|
+
* `DeliveryStatus` into delivered / failed and flagging ONLY a genuinely
|
|
19
|
+
* invalid token as `stale` (via {@link isInvalidTokenFailure}) so the caller
|
|
20
|
+
* can delete its device object. A thrown call (e.g. the channel is not
|
|
21
|
+
* configured on the EUM app) is caught and reported as `status: 'ERROR'`
|
|
22
|
+
* (failed, NOT stale — the token itself may be fine).
|
|
23
|
+
*
|
|
24
|
+
* Emits greppable `[push] send.response` / `[push] classify` log lines carrying
|
|
25
|
+
* the request channel and the per-address response (DeliveryStatus /
|
|
26
|
+
* StatusCode / StatusMessage) plus the keep-vs-delete decision, so a failed
|
|
27
|
+
* send can be diagnosed as channel-not-enabled vs invalid-token from the logs.
|
|
28
|
+
* These carry NO device token, profile id, or message copy.
|
|
29
|
+
*/
|
|
30
|
+
export declare const deliverToDevice: (pinpoint: PinpointClient, applicationId: string, deviceToken: string, channelType: PushChannelType, message: PushMessage) => Promise<DeviceDeliveryResult>;
|
|
31
|
+
//# sourceMappingURL=eum_client.d.ts.map
|