@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.
Files changed (59) hide show
  1. package/README.md +235 -0
  2. package/lib/campaign-association-asset/index.js +48413 -0
  3. package/lib/constants.d.ts +122 -0
  4. package/lib/constants.js +125 -0
  5. package/lib/construct.d.ts +283 -0
  6. package/lib/construct.js +824 -0
  7. package/lib/factory.d.ts +53 -0
  8. package/lib/factory.js +158 -0
  9. package/lib/handler-asset/index.js +530 -0
  10. package/lib/index.d.ts +7 -0
  11. package/lib/index.js +5 -0
  12. package/lib/lambda/campaign-association/handler.d.ts +29 -0
  13. package/lib/lambda/campaign-association/handler.js +80 -0
  14. package/lib/lambda/campaign-association/integration.d.ts +59 -0
  15. package/lib/lambda/campaign-association/integration.js +108 -0
  16. package/lib/lambda/campaign-association/onboarding.d.ts +25 -0
  17. package/lib/lambda/campaign-association/onboarding.js +74 -0
  18. package/lib/lambda/identify/device_resolver.d.ts +18 -0
  19. package/lib/lambda/identify/device_resolver.js +56 -0
  20. package/lib/lambda/identify/handler.d.ts +17 -0
  21. package/lib/lambda/identify/handler.js +124 -0
  22. package/lib/lambda/identify/mapping.d.ts +61 -0
  23. package/lib/lambda/identify/mapping.js +171 -0
  24. package/lib/lambda/identify/merge_resolver.d.ts +26 -0
  25. package/lib/lambda/identify/merge_resolver.js +36 -0
  26. package/lib/lambda/identify/principal.d.ts +68 -0
  27. package/lib/lambda/identify/principal.js +48 -0
  28. package/lib/lambda/identify/profile_resolver.d.ts +35 -0
  29. package/lib/lambda/identify/profile_resolver.js +65 -0
  30. package/lib/lambda/identify/types.d.ts +90 -0
  31. package/lib/lambda/identify/types.js +10 -0
  32. package/lib/lambda/identify/validation.d.ts +15 -0
  33. package/lib/lambda/identify/validation.js +99 -0
  34. package/lib/lambda/push/delivery.d.ts +49 -0
  35. package/lib/lambda/push/delivery.js +120 -0
  36. package/lib/lambda/push/device_lookup.d.ts +35 -0
  37. package/lib/lambda/push/device_lookup.js +88 -0
  38. package/lib/lambda/push/eum_client.d.ts +31 -0
  39. package/lib/lambda/push/eum_client.js +140 -0
  40. package/lib/lambda/push/event.d.ts +32 -0
  41. package/lib/lambda/push/event.js +122 -0
  42. package/lib/lambda/push/fixtures/real_journey_event.d.ts +19 -0
  43. package/lib/lambda/push/fixtures/real_journey_event.js +22 -0
  44. package/lib/lambda/push/handler.d.ts +15 -0
  45. package/lib/lambda/push/handler.js +86 -0
  46. package/lib/lambda/push/message_template.d.ts +72 -0
  47. package/lib/lambda/push/message_template.js +270 -0
  48. package/lib/lambda/push/payload.d.ts +25 -0
  49. package/lib/lambda/push/payload.js +53 -0
  50. package/lib/lambda/push/types.d.ts +153 -0
  51. package/lib/lambda/push/types.js +4 -0
  52. package/lib/lambda/shared/retry.d.ts +18 -0
  53. package/lib/lambda/shared/retry.js +45 -0
  54. package/lib/object_types.d.ts +63 -0
  55. package/lib/object_types.js +131 -0
  56. package/lib/push-handler-asset/index.js +75517 -0
  57. package/lib/types.d.ts +125 -0
  58. package/lib/types.js +2 -0
  59. 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