@kensio/yulin 1.21.1 → 1.21.3

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 (50) hide show
  1. package/dist/service/cloudformation/resource/factory/sim-cfn-resource-factory.type.d.ts +9 -0
  2. package/dist/service/cloudformation/resource/sim-cfn-resource.type.d.ts +11 -0
  3. package/dist/service/cloudformation/resource/update/sim-cfn-resource-update-validator.d.ts +26 -0
  4. package/dist/service/cloudformation/resource/update/sim-cfn-resource-update-validator.js +55 -0
  5. package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.d.ts +5 -0
  6. package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.js +17 -0
  7. package/dist/service/cloudformation/stack/update/sim-cfn-stack-update-plan.d.ts +7 -1
  8. package/dist/service/cloudformation/stack/update/sim-cfn-stack-update-plan.js +13 -0
  9. package/dist/service/cloudformation/stack/update/sim-cfn-stack-updater.js +1 -0
  10. package/dist/service/dynamodb/cfn/sim-cfn-dynamodb-resource-factory.d.ts +5 -0
  11. package/dist/service/dynamodb/cfn/sim-cfn-dynamodb-resource-factory.js +15 -0
  12. package/dist/service/dynamodb/cfn/table/sim-cfn-dynamodb-table-update-validator.d.ts +24 -0
  13. package/dist/service/dynamodb/cfn/table/sim-cfn-dynamodb-table-update-validator.js +38 -0
  14. package/dist/service/dynamodb/table/sim-dynamodb-index-update.js +1 -2
  15. package/dist/service/ses/command/configuration-set/sim-ses-configuration-set-commands.js +13 -5
  16. package/dist/service/ses/command/configuration-set/sim-ses-configuration-set-options.d.ts +1 -1
  17. package/dist/service/ses/command/configuration-set/sim-ses-configuration-set-options.js +9 -9
  18. package/dist/service/ses/command/send/send.command.d.ts +10 -1
  19. package/dist/service/ses/command/send/sim-ses-read-content.d.ts +2 -1
  20. package/dist/service/ses/command/send/sim-ses-send-email.js +1 -0
  21. package/dist/service/ses/command/send/sim-ses-service-send.js +1 -0
  22. package/dist/service/ses/command/send/sim-ses-simple-content.js +26 -5
  23. package/dist/service/ses/command/send/sim-ses-template-send.js +1 -0
  24. package/dist/service/ses/command/suppression/suppression.command.d.ts +3 -2
  25. package/dist/service/ses/configuration-set/sim-ses-configuration-set.d.ts +9 -10
  26. package/dist/service/ses/configuration-set/sim-ses-configuration-set.js +7 -8
  27. package/dist/service/ses/email/sim-ses-sent-email-store.d.ts +8 -0
  28. package/dist/service/ses/email/sim-ses-sent-email-store.js +17 -0
  29. package/dist/service/ses/email/sim-ses-sent-email.d.ts +18 -0
  30. package/dist/service/ses/email/sim-ses-sent-email.js +3 -0
  31. package/dist/service/ses/error/sim-ses.error.d.ts +10 -0
  32. package/dist/service/ses/error/sim-ses.error.js +10 -0
  33. package/dist/service/ses/feedback/sim-ses-feedback-recorder.d.ts +34 -0
  34. package/dist/service/ses/feedback/sim-ses-feedback-recorder.js +55 -0
  35. package/dist/service/ses/index.d.ts +3 -2
  36. package/dist/service/ses/index.js +2 -1
  37. package/dist/service/ses/sim-ses-commands.d.ts +2 -0
  38. package/dist/service/ses/sim-ses-commands.js +9 -0
  39. package/dist/service/ses/sim-ses-configuration-sets.d.ts +4 -4
  40. package/dist/service/ses/sim-ses-configuration-sets.js +4 -4
  41. package/dist/service/ses/sim-ses-suppression.d.ts +3 -2
  42. package/dist/service/ses/sim-ses-suppression.js +3 -2
  43. package/dist/service/ses/sim-ses-v2.d.ts +13 -0
  44. package/dist/service/ses/sim-ses-v2.js +13 -0
  45. package/dist/service/ses/suppression/sim-ses-suppressed-destination.d.ts +3 -4
  46. package/dist/service/ses/suppression/sim-ses-suppressed-destination.js +3 -4
  47. package/dist/service/ses/suppression/sim-ses-suppression-list.d.ts +4 -4
  48. package/dist/service/ses/suppression/sim-ses-suppression-list.js +4 -4
  49. package/docs/services/ses/README.md +164 -41
  50. package/package.json +2 -2
@@ -26,6 +26,14 @@ export declare class SimSesSentEmailStore {
26
26
  * Every message this scope has accepted, oldest first.
27
27
  */
28
28
  get all(): readonly SimSesSentEmail[];
29
+ /**
30
+ * Find an accepted message by the id SES returned for it.
31
+ */
32
+ find(messageId: string): SimSesSentEmail | undefined;
33
+ /**
34
+ * Get an accepted message by id, refusing an id this scope never issued.
35
+ */
36
+ require(messageId: string): SimSesSentEmail;
29
37
  /**
30
38
  * Keep a message SES has accepted.
31
39
  *
@@ -1,4 +1,5 @@
1
1
  import { SimAwsMessageLog } from "../../aws/message/sim-aws-message-log.js";
2
+ import { SimSesFeedbackError } from "../error/sim-ses.error.js";
2
3
  const hoursInADay = 24;
3
4
  const millisecondsInAnHour = 60 * 60 * 1000;
4
5
  /**
@@ -25,6 +26,22 @@ export class SimSesSentEmailStore {
25
26
  get all() {
26
27
  return [...this.#sent];
27
28
  }
29
+ /**
30
+ * Find an accepted message by the id SES returned for it.
31
+ */
32
+ find(messageId) {
33
+ return this.#sent.find((email) => email.messageId === messageId);
34
+ }
35
+ /**
36
+ * Get an accepted message by id, refusing an id this scope never issued.
37
+ */
38
+ require(messageId) {
39
+ const email = this.find(messageId);
40
+ if (email === undefined) {
41
+ throw new SimSesFeedbackError(`No accepted sim SES message has id ${messageId}.`);
42
+ }
43
+ return email;
44
+ }
28
45
  /**
29
46
  * Keep a message SES has accepted.
30
47
  *
@@ -19,6 +19,21 @@ export interface SimSesSentEmailBody {
19
19
  readonly text: string | undefined;
20
20
  readonly html: string | undefined;
21
21
  }
22
+ /**
23
+ * One structured attachment on a simple message.
24
+ *
25
+ * The bytes and metadata use the values from the SendEmail request. SES would
26
+ * use them to assemble MIME content after accepting the request.
27
+ */
28
+ export interface SimSesSentEmailAttachment {
29
+ readonly rawContent: Uint8Array;
30
+ readonly fileName: string;
31
+ readonly contentType: string | undefined;
32
+ readonly contentDisposition: "ATTACHMENT" | "INLINE" | undefined;
33
+ readonly contentDescription: string | undefined;
34
+ readonly contentId: string | undefined;
35
+ readonly contentTransferEncoding: "BASE64" | "QUOTED_PRINTABLE" | "SEVEN_BIT" | undefined;
36
+ }
22
37
  /**
23
38
  * A recipient the account's suppression list held back.
24
39
  *
@@ -37,6 +52,7 @@ interface SimSesSentEmailProperties {
37
52
  readonly replyToAddresses: readonly string[];
38
53
  readonly subject: string;
39
54
  readonly body: SimSesSentEmailBody;
55
+ readonly attachments: readonly SimSesSentEmailAttachment[];
40
56
  readonly templateName: string | undefined;
41
57
  readonly templateData: Readonly<Record<string, unknown>> | undefined;
42
58
  readonly configurationSetName: string | undefined;
@@ -64,6 +80,8 @@ export declare class SimSesSentEmail {
64
80
  readonly replyToAddresses: readonly string[];
65
81
  readonly subject: string;
66
82
  readonly body: SimSesSentEmailBody;
83
+ /** Structured attachments in request order. */
84
+ readonly attachments: readonly SimSesSentEmailAttachment[];
67
85
  /**
68
86
  * The template this message was rendered from, if it was rendered from a
69
87
  * stored one. A message written out in full has none, and so does one
@@ -19,6 +19,8 @@ export class SimSesSentEmail {
19
19
  replyToAddresses;
20
20
  subject;
21
21
  body;
22
+ /** Structured attachments in request order. */
23
+ attachments;
22
24
  /**
23
25
  * The template this message was rendered from, if it was rendered from a
24
26
  * stored one. A message written out in full has none, and so does one
@@ -51,6 +53,7 @@ export class SimSesSentEmail {
51
53
  this.replyToAddresses = properties.replyToAddresses;
52
54
  this.subject = properties.subject;
53
55
  this.body = properties.body;
56
+ this.attachments = properties.attachments;
54
57
  this.templateName = properties.templateName;
55
58
  this.templateData = properties.templateData;
56
59
  this.configurationSetName = properties.configurationSetName;
@@ -79,3 +79,13 @@ export declare class SimSesSendingPausedException extends SimSesError {
79
79
  readonly name = "SendingPausedException";
80
80
  constructor(message: string);
81
81
  }
82
+ /**
83
+ * A feedback event that cannot belong to the recorded message it names.
84
+ *
85
+ * This is a simulator diagnostic rather than an AWS error. A test supplies
86
+ * feedback through `recordFeedback`, and the error is raised at that call so
87
+ * an unrelated message or recipient cannot alter the suppression list.
88
+ */
89
+ export declare class SimSesFeedbackError extends SimSesError {
90
+ readonly name = "SimSesFeedbackError";
91
+ }
@@ -88,3 +88,13 @@ export class SimSesSendingPausedException extends SimSesError {
88
88
  super(message, { httpStatusCode: 400 });
89
89
  }
90
90
  }
91
+ /**
92
+ * A feedback event that cannot belong to the recorded message it names.
93
+ *
94
+ * This is a simulator diagnostic rather than an AWS error. A test supplies
95
+ * feedback through `recordFeedback`, and the error is raised at that call so
96
+ * an unrelated message or recipient cannot alter the suppression list.
97
+ */
98
+ export class SimSesFeedbackError extends SimSesError {
99
+ name = "SimSesFeedbackError";
100
+ }
@@ -0,0 +1,34 @@
1
+ import type { SimClock } from "../../../util/clock/sim-clock.js";
2
+ import type { SimSesAccount } from "../account/sim-ses-account.js";
3
+ import type { SimSesConfigurationSetStore } from "../configuration-set/sim-ses-configuration-set-store.js";
4
+ import type { SimSesSentEmailStore } from "../email/sim-ses-sent-email-store.js";
5
+ import type { SimSesSuppressionList } from "../suppression/sim-ses-suppression-list.js";
6
+ import { type SimSesSuppressionReason } from "../suppression/sim-ses-suppression-reason.js";
7
+ import type { SimSesSuppressedDestination } from "../suppression/sim-ses-suppressed-destination.js";
8
+ /** A hard bounce or complaint reported for one accepted message recipient. */
9
+ export interface SimSesFeedback {
10
+ readonly messageId: string;
11
+ readonly emailAddress: string;
12
+ readonly reason: SimSesSuppressionReason;
13
+ }
14
+ interface SimSesFeedbackRecorderProperties {
15
+ readonly sent: SimSesSentEmailStore;
16
+ readonly configurationSets: SimSesConfigurationSetStore;
17
+ readonly account: SimSesAccount;
18
+ readonly suppression: SimSesSuppressionList;
19
+ readonly clock: SimClock;
20
+ }
21
+ /** Applies explicit delivery feedback to the account suppression list. */
22
+ export declare class SimSesFeedbackRecorder {
23
+ #private;
24
+ constructor(properties: SimSesFeedbackRecorderProperties);
25
+ /**
26
+ * Record a hard bounce or complaint for one recipient of an accepted
27
+ * message.
28
+ *
29
+ * The returned entry is undefined when suppression for the feedback reason
30
+ * was inactive for this send.
31
+ */
32
+ record(feedback: SimSesFeedback): SimSesSuppressedDestination | undefined;
33
+ }
34
+ export {};
@@ -0,0 +1,55 @@
1
+ import { simSesBareAddress } from "../email/sim-ses-address.js";
2
+ import { SimSesFeedbackError } from "../error/sim-ses.error.js";
3
+ import { requiredSimSesSuppressionAddress } from "../suppression/sim-ses-suppression-address.js";
4
+ import { requiredSimSesSuppressionReason, } from "../suppression/sim-ses-suppression-reason.js";
5
+ /** Applies explicit delivery feedback to the account suppression list. */
6
+ export class SimSesFeedbackRecorder {
7
+ #sent;
8
+ #configurationSets;
9
+ #account;
10
+ #suppression;
11
+ #clock;
12
+ constructor(properties) {
13
+ this.#sent = properties.sent;
14
+ this.#configurationSets = properties.configurationSets;
15
+ this.#account = properties.account;
16
+ this.#suppression = properties.suppression;
17
+ this.#clock = properties.clock;
18
+ }
19
+ /**
20
+ * Record a hard bounce or complaint for one recipient of an accepted
21
+ * message.
22
+ *
23
+ * The returned entry is undefined when suppression for the feedback reason
24
+ * was inactive for this send.
25
+ */
26
+ record(feedback) {
27
+ const email = this.#sent.require(feedback.messageId);
28
+ const emailAddress = requiredSimSesSuppressionAddress(feedback.emailAddress);
29
+ const reason = requiredSimSesSuppressionReason(feedback.reason);
30
+ const recipient = this.#recipient(email, emailAddress);
31
+ if (!this.#isActive(email, reason)) {
32
+ return undefined;
33
+ }
34
+ return this.#suppression.put(recipient, reason, this.#clock.now());
35
+ }
36
+ #recipient(email, emailAddress) {
37
+ const wanted = emailAddress.toLowerCase();
38
+ const recipient = email.recipients
39
+ .map((address) => simSesBareAddress(address))
40
+ .find((address) => address.toLowerCase() === wanted);
41
+ if (recipient === undefined) {
42
+ throw new SimSesFeedbackError(`${emailAddress} is not a recipient of sim SES message ${email.messageId}.`);
43
+ }
44
+ return recipient;
45
+ }
46
+ #isActive(email, reason) {
47
+ if (email.configurationSetName !== undefined) {
48
+ const configurationSet = this.#configurationSets.find(email.configurationSetName);
49
+ if (configurationSet?.suppressedReasons !== undefined) {
50
+ return configurationSet.suppressedReasons.includes(reason);
51
+ }
52
+ }
53
+ return this.#account.isSuppressedFor(reason);
54
+ }
55
+ }
@@ -9,11 +9,12 @@ export { requiredSimSesIdentityName, simSesIdentityDomain, simSesIdentityKey, ty
9
9
  export { simSesArnPrefix, simSesConfigurationSetArn, simSesIdentityArn, } from "./sim-ses-arn.js";
10
10
  export { SimSesConfigurationSet, type SimSesConfigurationSetDeliveryOptions, type SimSesConfigurationSetOptions, type SimSesConfigurationSetReputationOptions, type SimSesSuppressedReason, } from "./configuration-set/sim-ses-configuration-set.js";
11
11
  export { SimSesConfigurationSetStore } from "./configuration-set/sim-ses-configuration-set-store.js";
12
- export { SimSesSentEmail, type SimSesSentEmailBody, type SimSesSentEmailDestination, type SimSesSuppressedRecipient, } from "./email/sim-ses-sent-email.js";
12
+ export { SimSesSentEmail, type SimSesSentEmailAttachment, type SimSesSentEmailBody, type SimSesSentEmailDestination, type SimSesSuppressedRecipient, } from "./email/sim-ses-sent-email.js";
13
13
  export { SimSesSentEmailStore } from "./email/sim-ses-sent-email-store.js";
14
+ export { type SimSesFeedback, SimSesFeedbackRecorder, } from "./feedback/sim-ses-feedback-recorder.js";
14
15
  export { requiredSimSesFromAddress, simSesBareAddress, } from "./email/sim-ses-address.js";
15
16
  export { SimSesSuppressedDestination } from "./suppression/sim-ses-suppressed-destination.js";
16
17
  export { SimSesSuppressionList } from "./suppression/sim-ses-suppression-list.js";
17
18
  export { requiredSimSesSuppressionReason, type SimSesSuppressionReason, } from "./suppression/sim-ses-suppression-reason.js";
18
19
  export { SimSesAccount, type SimSesAccountContactDetails, type SimSesSendQuota, } from "./account/sim-ses-account.js";
19
- export { SimSesAlreadyExistsException, SimSesBadRequestException, SimSesError, type SimSesErrorMetadata, SimSesMessageRejected, SimSesNotFoundException, SimSesSendingPausedException, SimSesUnsupportedOperationException, } from "./error/sim-ses.error.js";
20
+ export { SimSesAlreadyExistsException, SimSesBadRequestException, SimSesError, SimSesFeedbackError, type SimSesErrorMetadata, SimSesMessageRejected, SimSesNotFoundException, SimSesSendingPausedException, SimSesUnsupportedOperationException, } from "./error/sim-ses.error.js";
@@ -8,9 +8,10 @@ export { SimSesConfigurationSet, } from "./configuration-set/sim-ses-configurati
8
8
  export { SimSesConfigurationSetStore } from "./configuration-set/sim-ses-configuration-set-store.js";
9
9
  export { SimSesSentEmail, } from "./email/sim-ses-sent-email.js";
10
10
  export { SimSesSentEmailStore } from "./email/sim-ses-sent-email-store.js";
11
+ export { SimSesFeedbackRecorder, } from "./feedback/sim-ses-feedback-recorder.js";
11
12
  export { requiredSimSesFromAddress, simSesBareAddress, } from "./email/sim-ses-address.js";
12
13
  export { SimSesSuppressedDestination } from "./suppression/sim-ses-suppressed-destination.js";
13
14
  export { SimSesSuppressionList } from "./suppression/sim-ses-suppression-list.js";
14
15
  export { requiredSimSesSuppressionReason, } from "./suppression/sim-ses-suppression-reason.js";
15
16
  export { SimSesAccount, } from "./account/sim-ses-account.js";
16
- export { SimSesAlreadyExistsException, SimSesBadRequestException, SimSesError, SimSesMessageRejected, SimSesNotFoundException, SimSesSendingPausedException, SimSesUnsupportedOperationException, } from "./error/sim-ses.error.js";
17
+ export { SimSesAlreadyExistsException, SimSesBadRequestException, SimSesError, SimSesFeedbackError, SimSesMessageRejected, SimSesNotFoundException, SimSesSendingPausedException, SimSesUnsupportedOperationException, } from "./error/sim-ses.error.js";
@@ -11,6 +11,7 @@ import { SimSesServiceSend } from "./command/send/sim-ses-service-send.js";
11
11
  import { SimSesSuppressionCommands } from "./command/suppression/sim-ses-suppression-commands.js";
12
12
  import { SimSesSuppressionList } from "./suppression/sim-ses-suppression-list.js";
13
13
  import { SimSesSentEmailStore } from "./email/sim-ses-sent-email-store.js";
14
+ import { SimSesFeedbackRecorder } from "./feedback/sim-ses-feedback-recorder.js";
14
15
  import { SimSesConfigurationSetStore } from "./configuration-set/sim-ses-configuration-set-store.js";
15
16
  import { SimSesIdentityStore } from "./identity/sim-ses-identity-store.js";
16
17
  import { SimSesTemplateCommands } from "./command/template/sim-ses-template-commands.js";
@@ -43,6 +44,7 @@ export declare class SimSesCommands {
43
44
  readonly templateCommands: SimSesTemplateCommands;
44
45
  readonly configurationSetCommands: SimSesConfigurationSetCommands;
45
46
  readonly sendEmail: SimSesSendEmail;
47
+ readonly feedback: SimSesFeedbackRecorder;
46
48
  /**
47
49
  * The way another simulated service reaches this SES, which is the send
48
50
  * without the IAM authorization a caller's request goes through.
@@ -16,6 +16,7 @@ import { SimSesVerifiedIdentityCheck } from "./command/send/sim-ses-verified-ide
16
16
  import { SimSesSuppressionCommands } from "./command/suppression/sim-ses-suppression-commands.js";
17
17
  import { SimSesSuppressionList } from "./suppression/sim-ses-suppression-list.js";
18
18
  import { SimSesSentEmailStore } from "./email/sim-ses-sent-email-store.js";
19
+ import { SimSesFeedbackRecorder } from "./feedback/sim-ses-feedback-recorder.js";
19
20
  import { SimSesConfigurationSetStore } from "./configuration-set/sim-ses-configuration-set-store.js";
20
21
  import { SimSesIdentityStore } from "./identity/sim-ses-identity-store.js";
21
22
  import { SimSesTemplateCommands } from "./command/template/sim-ses-template-commands.js";
@@ -39,6 +40,7 @@ export class SimSesCommands {
39
40
  templateCommands;
40
41
  configurationSetCommands;
41
42
  sendEmail;
43
+ feedback;
42
44
  /**
43
45
  * The way another simulated service reaches this SES, which is the send
44
46
  * without the IAM authorization a caller's request goes through.
@@ -103,6 +105,13 @@ export class SimSesCommands {
103
105
  authorizer,
104
106
  clock: background,
105
107
  });
108
+ this.feedback = new SimSesFeedbackRecorder({
109
+ sent,
110
+ configurationSets,
111
+ account,
112
+ suppression,
113
+ clock: background,
114
+ });
106
115
  this.serviceSend = new SimSesServiceSend({
107
116
  sent,
108
117
  identityCheck,
@@ -10,10 +10,10 @@ import { SimSesSuppression } from "./sim-ses-suppression.js";
10
10
  * separate classes because one class holding every SES operation grows by a
11
11
  * method with each one added.
12
12
  *
13
- * A configuration set here is state and no behaviour. Its suppression reasons,
14
- * sending switch, delivery options and reputation switch are all held and read
15
- * back, and nothing acts on any of them. A send naming a set keeps the name on
16
- * its record and goes no further.
13
+ * A configuration set holds suppression reasons, the sending switch, delivery
14
+ * options and the reputation switch. The sending switch acts on acceptance.
15
+ * Suppression reasons act when feedback is recorded for an accepted message.
16
+ * The remaining options are held for a test to read back.
17
17
  */
18
18
  export declare abstract class SimSesConfigurationSets extends SimSesSuppression {
19
19
  /**
@@ -7,10 +7,10 @@ import { SimSesSuppression } from "./sim-ses-suppression.js";
7
7
  * separate classes because one class holding every SES operation grows by a
8
8
  * method with each one added.
9
9
  *
10
- * A configuration set here is state and no behaviour. Its suppression reasons,
11
- * sending switch, delivery options and reputation switch are all held and read
12
- * back, and nothing acts on any of them. A send naming a set keeps the name on
13
- * its record and goes no further.
10
+ * A configuration set holds suppression reasons, the sending switch, delivery
11
+ * options and the reputation switch. The sending switch acts on acceptance.
12
+ * Suppression reasons act when feedback is recorded for an accepted message.
13
+ * The remaining options are held for a test to read back.
14
14
  */
15
15
  export class SimSesConfigurationSets extends SimSesSuppression {
16
16
  /**
@@ -13,8 +13,9 @@ interface SimSesSuppressionProperties {
13
13
  * SES operation grows by a method with each one added, and the suppression
14
14
  * commands are the part of the API a reader can take in on their own.
15
15
  *
16
- * Real SES fills this list from hard bounces and complaints. Nothing bounces
17
- * here, so every address on it was put there by a caller.
16
+ * Real SES fills this list from hard bounces and complaints. A test supplies
17
+ * that feedback explicitly, and callers may also manage entries through the
18
+ * suppression commands.
18
19
  */
19
20
  export declare abstract class SimSesSuppression {
20
21
  protected readonly commands: SimSesCommands;
@@ -6,8 +6,9 @@
6
6
  * SES operation grows by a method with each one added, and the suppression
7
7
  * commands are the part of the API a reader can take in on their own.
8
8
  *
9
- * Real SES fills this list from hard bounces and complaints. Nothing bounces
10
- * here, so every address on it was put there by a caller.
9
+ * Real SES fills this list from hard bounces and complaints. A test supplies
10
+ * that feedback explicitly, and callers may also manage entries through the
11
+ * suppression commands.
11
12
  */
12
13
  export class SimSesSuppression {
13
14
  commands;
@@ -3,6 +3,8 @@ import type * as simSesCommands from "./command/sim-ses-command.types.js";
3
3
  import type { SimSesRequestOptions } from "./command/sim-ses-request-options.js";
4
4
  import type * as simSesServiceSend from "./command/send/sim-ses-service-send.js";
5
5
  import type { SimSesSentEmail } from "./email/sim-ses-sent-email.js";
6
+ import type { SimSesFeedback } from "./feedback/sim-ses-feedback-recorder.js";
7
+ import type { SimSesSuppressedDestination } from "./suppression/sim-ses-suppressed-destination.js";
6
8
  import type { SimSesIdentity } from "./identity/sim-ses-identity.js";
7
9
  import type { SimSesTemplate } from "./template/sim-ses-template.js";
8
10
  import { SimSesCfnResourceFactory } from "./cfn/sim-ses-cfn-resource-factory.js";
@@ -39,6 +41,17 @@ export declare class SimSesV2 extends SimSesConfigurationSets {
39
41
  * account keeps no such record, which is exactly why a test needs one.
40
42
  */
41
43
  sentEmails(): readonly SimSesSentEmail[];
44
+ /**
45
+ * Record a hard bounce or complaint for one recipient of an accepted
46
+ * message.
47
+ *
48
+ * Real feedback happens after SES hands a message to a mail system. A test
49
+ * process cannot observe that exchange, so this simulator-side operation
50
+ * supplies the feedback explicitly. Active feedback adds or updates the
51
+ * account suppression entry at the current simulated time. Inactive
52
+ * feedback returns undefined and leaves the list unchanged.
53
+ */
54
+ recordFeedback(feedback: SimSesFeedback): SimSesSuppressedDestination | undefined;
42
55
  /**
43
56
  * Find an identity by the address or domain it names.
44
57
  *
@@ -38,6 +38,19 @@ export class SimSesV2 extends SimSesConfigurationSets {
38
38
  sentEmails() {
39
39
  return this.commands.sent.all;
40
40
  }
41
+ /**
42
+ * Record a hard bounce or complaint for one recipient of an accepted
43
+ * message.
44
+ *
45
+ * Real feedback happens after SES hands a message to a mail system. A test
46
+ * process cannot observe that exchange, so this simulator-side operation
47
+ * supplies the feedback explicitly. Active feedback adds or updates the
48
+ * account suppression entry at the current simulated time. Inactive
49
+ * feedback returns undefined and leaves the list unchanged.
50
+ */
51
+ recordFeedback(feedback) {
52
+ return this.commands.feedback.record(feedback);
53
+ }
41
54
  /**
42
55
  * Find an identity by the address or domain it names.
43
56
  *
@@ -7,10 +7,9 @@ interface SimSesSuppressedDestinationProperties {
7
7
  /**
8
8
  * One address on an account's suppression list.
9
9
  *
10
- * Real SES also reports a `MessageId` and a `FeedbackId` on the address it put
11
- * there itself, describing the bounce or complaint that did it. Nothing
12
- * bounces here, so every address on this list was put there by hand and there
13
- * is no feedback event to point at.
10
+ * Real SES also reports a `MessageId` and a `FeedbackId` on an address added by
11
+ * delivery feedback. This simulation records the reason and time only. It
12
+ * does not publish or retain a feedback event.
14
13
  */
15
14
  export declare class SimSesSuppressedDestination {
16
15
  /** The address as it was given, case and all. */
@@ -1,10 +1,9 @@
1
1
  /**
2
2
  * One address on an account's suppression list.
3
3
  *
4
- * Real SES also reports a `MessageId` and a `FeedbackId` on the address it put
5
- * there itself, describing the bounce or complaint that did it. Nothing
6
- * bounces here, so every address on this list was put there by hand and there
7
- * is no feedback event to point at.
4
+ * Real SES also reports a `MessageId` and a `FeedbackId` on an address added by
5
+ * delivery feedback. This simulation records the reason and time only. It
6
+ * does not publish or retain a feedback event.
8
7
  */
9
8
  export class SimSesSuppressedDestination {
10
9
  /** The address as it was given, case and all. */
@@ -3,10 +3,10 @@ import type { SimSesSuppressionReason } from "./sim-ses-suppression-reason.js";
3
3
  /**
4
4
  * The account-level suppression list of one simulated SES scope.
5
5
  *
6
- * Real SES fills this from hard bounces and complaints. Nothing bounces here,
7
- * so every address on it was put there by a caller, which is the point: an
8
- * application's own support tooling and operations scripts have somewhere to
9
- * run.
6
+ * Real SES fills this from hard bounces and complaints. A test supplies those
7
+ * events through the simulator's feedback operation. The ordinary suppression
8
+ * commands also manage the same entries, giving application support tooling
9
+ * and operations scripts somewhere to run.
10
10
  *
11
11
  * The list is region scoped, as identities and sends are. An address
12
12
  * suppressed in one region says nothing about another.
@@ -3,10 +3,10 @@ import { SimSesSuppressedDestination } from "./sim-ses-suppressed-destination.js
3
3
  /**
4
4
  * The account-level suppression list of one simulated SES scope.
5
5
  *
6
- * Real SES fills this from hard bounces and complaints. Nothing bounces here,
7
- * so every address on it was put there by a caller, which is the point: an
8
- * application's own support tooling and operations scripts have somewhere to
9
- * run.
6
+ * Real SES fills this from hard bounces and complaints. A test supplies those
7
+ * events through the simulator's feedback operation. The ordinary suppression
8
+ * commands also manage the same entries, giving application support tooling
9
+ * and operations scripts somewhere to run.
10
10
  *
11
11
  * The list is region scoped, as identities and sends are. An address
12
12
  * suppressed in one region says nothing about another.