wirejs-deploy-amplify-basic 0.1.172 → 0.1.173

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.
@@ -16,6 +16,7 @@ import { Table, AttributeType, BillingMode } from 'aws-cdk-lib/aws-dynamodb';
16
16
  import { AnyPrincipal, PolicyStatement } from 'aws-cdk-lib/aws-iam';
17
17
  import { Rule, RuleTargetInput, Schedule } from 'aws-cdk-lib/aws-events';
18
18
  import { LambdaFunction as LambdaFunctionTarget } from 'aws-cdk-lib/aws-events-targets';
19
+ import { SESClient, VerifyEmailIdentityCommand, GetIdentityVerificationAttributesCommand } from '@aws-sdk/client-ses';
19
20
 
20
21
  import { TableDefinition, indexName, DeploymentConfig } from 'wirejs-resources';
21
22
  import { TableIndexes } from './constructs/table-indexes';
@@ -309,4 +310,75 @@ api.addToRolePolicy(new PolicyStatement({
309
310
  }));
310
311
 
311
312
 
313
+ /**
314
+ * SES permissions for EmailSender resources
315
+ */
316
+ function isEmailSender(resource: any): resource is {
317
+ type: 'EmailSender';
318
+ options: { absoluteId: string; from: string };
319
+ } {
320
+ return resource.type === 'EmailSender';
321
+ }
322
+
323
+ const emailSenderResources = generated.filter(isEmailSender);
324
+ if (emailSenderResources.length > 0) {
325
+ const senderAddresses = emailSenderResources.map(r => r.options.from);
326
+ api.addToRolePolicy(new PolicyStatement({
327
+ actions: [
328
+ 'ses:SendEmail',
329
+ 'ses:SendRawEmail',
330
+ ],
331
+ resources: [
332
+ `arn:${backend.stack.partition}:ses:${backend.stack.region}:${backend.stack.account}:identity/*`,
333
+ ],
334
+ }));
335
+
336
+ // Initiate SES email verification for each sender address during deployment.
337
+ // This sends a verification email to each address automatically so customers
338
+ // don't need to manually trigger it from the AWS console.
339
+ const sesClient = new SESClient();
340
+ const verificationResults: { address: string; status: string }[] = [];
341
+
342
+ for (const address of senderAddresses) {
343
+ try {
344
+ // Check current verification status first
345
+ const statusResult = await sesClient.send(
346
+ new GetIdentityVerificationAttributesCommand({ Identities: [address] })
347
+ );
348
+ const currentStatus = statusResult.VerificationAttributes?.[address]?.VerificationStatus;
349
+
350
+ if (currentStatus === 'Success') {
351
+ verificationResults.push({ address, status: 'already verified ✅' });
352
+ } else {
353
+ // Trigger a (new) verification email
354
+ await sesClient.send(new VerifyEmailIdentityCommand({ EmailAddress: address }));
355
+ verificationResults.push({ address, status: 'verification email sent 📧' });
356
+ }
357
+ } catch (err: any) {
358
+ verificationResults.push({ address, status: `could not initiate automatically — ${err?.message ?? err}` });
359
+ }
360
+ }
361
+
362
+ console.log(`
363
+ ⚠️ AWS SES Email Verification
364
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
365
+ Your app uses EmailSender with the following sender address(es):
366
+
367
+ ${verificationResults.map(r => ` • ${r.address} — ${r.status}`).join('\n')}
368
+
369
+ ${verificationResults.some(r => r.status.includes('sent'))
370
+ ? 'Check your inbox and click the verification link in each email from AWS SES.'
371
+ : ''}
372
+ AWS SES starts in "sandbox" mode — you must also verify recipient addresses
373
+ or request production access to send to arbitrary recipients.
374
+
375
+ To request production (sandbox removal) access:
376
+ https://docs.aws.amazon.com/ses/latest/dg/request-production-access.html
377
+
378
+ See docs/amplify.md in your project for more details.
379
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
380
+ `);
381
+ }
382
+
383
+
312
384
  backend.addOutput({ custom: { api: apiUrl.url } });
@@ -3,6 +3,6 @@
3
3
  "dependencies": {
4
4
  "jsdom": "^25.0.1",
5
5
  "wirejs-dom": "^1.0.44",
6
- "wirejs-resources": "^0.1.172"
6
+ "wirejs-resources": "^0.1.173"
7
7
  }
8
8
  }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from 'wirejs-resources';
2
2
  export { FileService } from './services/file.js';
3
3
  export { AuthenticationService } from './services/authentication.js';
4
+ export { EmailSender } from './services/email-sender.js';
4
5
  export { LLM } from './services/llm.js';
5
6
  export { DistributedTable } from './resources/distributed-table.js';
6
7
  export { RealtimeService } from './services/realtime.js';
package/dist/index.js CHANGED
@@ -6,6 +6,8 @@ import { FileService } from './services/file.js';
6
6
  export { FileService } from './services/file.js';
7
7
  import { AuthenticationService } from './services/authentication.js';
8
8
  export { AuthenticationService } from './services/authentication.js';
9
+ import { EmailSender } from './services/email-sender.js';
10
+ export { EmailSender } from './services/email-sender.js';
9
11
  import { LLM } from './services/llm.js';
10
12
  export { LLM } from './services/llm.js';
11
13
  import { DistributedTable } from './resources/distributed-table.js';
@@ -23,6 +25,7 @@ overrides.AuthenticationService = AuthenticationService;
23
25
  overrides.BackgroundJob = BackgroundJob;
24
26
  overrides.CronJob = CronJob;
25
27
  overrides.DistributedTable = DistributedTable;
28
+ overrides.EmailSender = EmailSender;
26
29
  overrides.Endpoint = Endpoint;
27
30
  overrides.FileService = FileService;
28
31
  overrides.LLM = LLM;
@@ -0,0 +1,7 @@
1
+ import { Resource, EmailSender as BaseEmailSender, EmailMessage } from 'wirejs-resources';
2
+ export declare class EmailSender extends BaseEmailSender {
3
+ constructor(scope: Resource | string, id: string, options: {
4
+ from: string;
5
+ });
6
+ send(message: EmailMessage): Promise<void>;
7
+ }
@@ -0,0 +1,24 @@
1
+ import { SESClient, SendEmailCommand, } from '@aws-sdk/client-ses';
2
+ import { EmailSender as BaseEmailSender, } from 'wirejs-resources';
3
+ import { addResource } from '../resource-collector.js';
4
+ const ses = new SESClient();
5
+ export class EmailSender extends BaseEmailSender {
6
+ constructor(scope, id, options) {
7
+ super(scope, id, options);
8
+ addResource('EmailSender', { absoluteId: this.absoluteId, from: options.from });
9
+ }
10
+ async send(message) {
11
+ const toAddresses = Array.isArray(message.to) ? message.to : [message.to];
12
+ await ses.send(new SendEmailCommand({
13
+ Source: this.from,
14
+ Destination: { ToAddresses: toAddresses },
15
+ Message: {
16
+ Subject: { Data: message.subject },
17
+ Body: {
18
+ Text: { Data: message.body },
19
+ ...(message.html !== undefined ? { Html: { Data: message.html } } : {}),
20
+ },
21
+ },
22
+ }));
23
+ }
24
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wirejs-deploy-amplify-basic",
3
- "version": "0.1.172",
3
+ "version": "0.1.173",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -32,6 +32,7 @@
32
32
  "@aws-sdk/client-cognito-identity-provider": "^3.741.0",
33
33
  "@aws-sdk/client-dynamodb": "^3.774.0",
34
34
  "@aws-sdk/client-s3": "^3.738.0",
35
+ "@aws-sdk/client-ses": "^3.738.0",
35
36
  "@aws-sdk/credential-provider-node": "^3.806.0",
36
37
  "@aws-sdk/client-lambda": "3.821.0",
37
38
  "@aws-sdk/lib-dynamodb": "^3.778.0",
@@ -44,7 +45,7 @@
44
45
  "recursive-copy": "^2.0.14",
45
46
  "rimraf": "^6.0.1",
46
47
  "wirejs-dom": "^1.0.44",
47
- "wirejs-resources": "^0.1.172"
48
+ "wirejs-resources": "^0.1.173"
48
49
  },
49
50
  "devDependencies": {
50
51
  "@aws-amplify/backend": "^1.14.0",