Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
534e034
feat(discussions): add DynamoDB storage Lambda trigger to test app
sai-ray Apr 8, 2026
71419a0
test(discussions): add activity counter test for storage DynamoDB tri…
sai-ray Apr 9, 2026
be0fe36
feat(discussions): update snapshots with storage DynamoDB trigger
sai-ray Apr 9, 2026
fbb9224
feat(cli-internal): add storage DynamoDB trigger codegen
sai-ray Apr 9, 2026
9b37248
feat(cli-internal): add storage DynamoDB trigger codegen
sai-ray Apr 9, 2026
29a9226
fix(discussions): align snapshot package names and update post-generate
sai-ray Apr 9, 2026
91f603e
fix(discussions): sanitize account IDs in refactor snapshots
sai-ray Apr 9, 2026
023aa8d
fix(discussions): restore gitignore boilerplate and clean snapshot deps
sai-ray Apr 9, 2026
8116ef2
chore(discussions): update yarn.lock for snapshot deps
sai-ray Apr 9, 2026
947c062
fix(discussions): fix post-refactor script regex and add missing fixups
sai-ray Apr 10, 2026
abe54ff
chore(discussions): sanitize app ID in refactor snapshots
sai-ray Apr 10, 2026
7745403
refactor(cli-internal): switch storage trigger detection to CFN parsing
sai-ray Apr 10, 2026
f54bc2f
fix(cli-internal): remove unnecessary fallback in fetchuseractivity
sai-ray Apr 16, 2026
31cfe17
Merge remote-tracking branch 'origin/gen2-migration' into sai/storage…
sai-ray Apr 16, 2026
6c52c8c
chore(cli-internal): update discussions snapshots and remove debug logs
sai-ray Apr 17, 2026
56ddaad
Merge remote-tracking branch 'origin/gen2-migration' into sai/storage…
sai-ray Apr 17, 2026
12eef38
fix(cli-internal): align discussions refactor snapshot after merge
sai-ray Apr 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion amplify-migration-apps/discussions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,30 @@ https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.Core
✔ Do you want to add a sort key to your global secondary index? (Y/n) · yes
✔ Choose sort key for the GSI · timestamp
✔ Do you want to add more global secondary indexes to your table? (Y/n) · no
✔ Do you want to add a Lambda Trigger for your Table? (y/N) · no
✔ Do you want to add a Lambda Trigger for your Table? (y/N) · yes
✔ Select from the following options · Create a new function

✔ Do you want to edit the local activityTriggerXXXXXX lambda function now? (y/N) · no
```

Then grant the trigger function write access to the activity table:

```console
amplify update function
```

```console
? Select the Lambda function you want to update activityTriggerXXXXXX
? Which setting do you want to update? Resource access permissions
? Select the categories you want this function to have access to. storage
? Storage has 6 resources in this project. Select the one you would like your Lambda to access activity
? Select the operations you want to permit on activity create, read, update, delete

You can access the following resource attributes as environment variables from your Lambda function
STORAGE_ACTIVITY_ARN
STORAGE_ACTIVITY_NAME
STORAGE_ACTIVITY_STREAMARN
? Do you want to edit the local lambda function now? No
```

#### Bookmarks Table
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { defineAuth } from '@aws-amplify/backend';
export const auth = defineAuth({
loginWith: {
email: {
verificationEmailSubject: 'Verification',
verificationEmailBody: () => 'Here is your verification code {####}',
verificationEmailSubject: 'Your verification code',
verificationEmailBody: () => 'Your verification code is {####}',
},
},
userAttributes: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { auth } from './auth/resource';
import { data } from './data/resource';
import { storage } from './storage/resource';
import { activityTrigger79c26ead } from './storage/activityTrigger79c26ead/resource';
import { fetchuseractivity } from './storage/fetchuseractivity/resource';
import { recorduseractivity } from './storage/recorduseractivity/resource';
import { DynamoEventSource } from 'aws-cdk-lib/aws-lambda-event-sources';
Expand All @@ -18,6 +19,7 @@ const backend = defineBackend({
auth,
data,
storage,
activityTrigger79c26ead,
fetchuseractivity,
recorduseractivity,
});
Expand Down Expand Up @@ -78,6 +80,47 @@ userPool.addClient('NativeAppClient', {
generateSecret: false,
});
const branchName = process.env.AWS_BRANCH ?? 'sandbox';
backend.activityTrigger79c26ead.resources.cfnResources.cfnFunction.functionName = `activityTrigger79c26ead-${branchName}`;
backend.activityTrigger79c26ead.addEnvironment(
'STORAGE_ACTIVITY_STREAMARN',
activity.tableStreamArn!
);
backend.activityTrigger79c26ead.addEnvironment(
'STORAGE_ACTIVITY_ARN',
activity.tableArn
);
backend.activityTrigger79c26ead.addEnvironment(
'STORAGE_ACTIVITY_NAME',
activity.tableName
);
activity.grant(
backend.activityTrigger79c26ead.resources.lambda,
'dynamodb:Put*',
'dynamodb:Create*',
'dynamodb:BatchWriteItem',
'dynamodb:PartiQLInsert',
'dynamodb:Get*',
'dynamodb:BatchGetItem',
'dynamodb:List*',
'dynamodb:Describe*',
'dynamodb:Scan',
'dynamodb:Query',
'dynamodb:PartiQLSelect',
'dynamodb:Update*',
'dynamodb:RestoreTable*',
'dynamodb:PartiQLUpdate',
'dynamodb:Delete*',
'dynamodb:PartiQLDelete'
);
backend.activityTrigger79c26ead.resources.lambda.addEventSource(
new DynamoEventSource(activity, { startingPosition: StartingPosition.LATEST })
);
activity.grantStreamRead(
backend.activityTrigger79c26ead.resources.lambda.role!
);
activity.grantTableListStreams(
backend.activityTrigger79c26ead.resources.lambda.role!
);
backend.fetchuseractivity.resources.cfnResources.cfnFunction.functionName = `fetchuseractivity-${branchName}`;
backend.fetchuseractivity.addEnvironment(
'STORAGE_ACTIVITY_STREAMARN',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ type Comment @model @auth(rules: [{ allow: public }]){

type Query {
fetchUserActivity(userId: ID!): [Activity] @function(name: "fetchuseractivity-${branchName}") @auth(rules: [{ allow: public }])
getActivityStats: ActivityStats @function(name: "fetchuseractivity-${branchName}") @auth(rules: [{ allow: public }])
}

type ActivityStats {
activityCount: Int! @auth(rules: [{ allow: public }])
}

type Activity {
Expand All @@ -41,9 +46,9 @@ export const data = defineData({
//The "branchname" variable needs to be the same as your deployment branch if you want to reuse your Gen1 app tables
branchName: 'x',
modelNameToTableNameMapping: {
Topic: 'Topic-xw3yrfq7mngltcua43nucy7fg4-x',
Post: 'Post-xw3yrfq7mngltcua43nucy7fg4-x',
Comment: 'Comment-xw3yrfq7mngltcua43nucy7fg4-x',
Topic: 'Topic-x6yep2wyvjefhbpic6h5h4vdji-x',
Post: 'Post-x6yep2wyvjefhbpic6h5h4vdji-x',
Comment: 'Comment-x6yep2wyvjefhbpic6h5h4vdji-x',
},
},
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"key1": "value1",
"key2": "value2",
"key3": "value3"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* Amplify Params - DO NOT EDIT
ENV
REGION
STORAGE_ACTIVITY_ARN
STORAGE_ACTIVITY_NAME
STORAGE_ACTIVITY_STREAMARN
Amplify Params - DO NOT EDIT */

const { DynamoDBClient, UpdateItemCommand } = require('@aws-sdk/client-dynamodb');

const client = new DynamoDBClient();
const TABLE_NAME = process.env.STORAGE_ACTIVITY_NAME;

exports.handler = async (event) => {
let newRecordCount = 0;

for (const record of event.Records) {
// Skip counter updates to avoid infinite loop
const keys = record.dynamodb.Keys;
if (keys.id.S.startsWith('STATS#')) continue;

if (record.eventName === 'INSERT') {
newRecordCount++;
}
}

if (newRecordCount === 0) return;

await client.send(new UpdateItemCommand({
TableName: TABLE_NAME,
Key: {
id: { S: 'STATS#global' },
userId: { S: 'COUNTER' },
},
UpdateExpression: 'ADD activityCount :inc',
ExpressionAttributeValues: {
':inc': { N: String(newRecordCount) },
},
}));

console.log(`Incremented activity count by ${newRecordCount}`);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { defineFunction } from '@aws-amplify/backend';

const branchName = process.env.AWS_BRANCH ?? 'sandbox';

export const activityTrigger79c26ead = defineFunction({
entry: './index.js',
name: `activityTrigger79c26ead-${branchName}`,
timeoutSeconds: 25,
memoryMB: 128,
environment: { ENV: `${branchName}`, REGION: 'us-east-1' },
runtime: 22,
});
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
const { DynamoDBDocumentClient, QueryCommand } = require('@aws-sdk/lib-dynamodb');
const { DynamoDBDocumentClient, QueryCommand, GetCommand } = require('@aws-sdk/lib-dynamodb');

const dynamoDB = DynamoDBDocumentClient.from(new DynamoDBClient({}));
const TABLE_NAME = process.env.STORAGE_ACTIVITY_NAME;

exports.handler = async (event) => {
console.log(`EVENT: ${JSON.stringify(event)}`);

const { userId } = event.arguments;
return await fetchUserActivity(userId);
const fieldName = event.info?.fieldName || event.fieldName;

if (fieldName === 'getActivityStats') {
return await fetchActivityStats();
}

const { userId } = event.arguments || {};
return await fetchUserActivity(userId);
};

async function fetchUserActivity(userId) {
Expand All @@ -26,3 +31,12 @@ async function fetchUserActivity(userId) {
return result.Items;

}

async function fetchActivityStats() {
const result = await dynamoDB.send(new GetCommand({
TableName: TABLE_NAME,
Key: { id: 'STATS#global', userId: 'COUNTER' },
}));

return { activityCount: result.Item?.activityCount ?? 0 };
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "us-east-1:0ab20e5d-b843-4969-94b1-c17d26af9934"
"cognito-identity.amazonaws.com:aud": "us-east-1:71501d31-e722-454c-ac1a-ccb858fb39f8"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "authenticated"
Expand Down Expand Up @@ -54,7 +54,7 @@
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "us-east-1:0ab20e5d-b843-4969-94b1-c17d26af9934"
"cognito-identity.amazonaws.com:aud": "us-east-1:71501d31-e722-454c-ac1a-ccb858fb39f8"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "unauthenticated"
Expand Down Expand Up @@ -92,7 +92,7 @@
"CDKMetadata": {
"Type": "AWS::CDK::Metadata",
"Properties": {
"Analytics": "v2:deflate64:H4sIAAAAAAAA/02LwQrCMBBEv6X3dK0BvUtPXkQqniUmq26bbqBZLRLy71Kk2tPMvJnRoDcVVIUZY2ldV3q6QjpgFHQnMbZTZoyXZMOdSQKkc8ThGIJX9Y1/fja1J2RZVn+yd8hC8p7Py9wEjzsRYx89smRFpoc0wWk4ac5ZcXAIbVy9tIb1FqqijUTl8GShHqH56gf10GUazgAAAA=="
"Analytics": "v2:deflate64:H4sIAAAAAAAA/02LwQrCMBBEv6X3dK0BP0B68iLS4llisuq26Qaa1SIh/y5Fqj3NzJsZDXpXQVWYKZbW9aWnK6QjRkHXirG9MlO8JBvuTBIgnSOOpxC8qm/884upPSHLuvqTg0MWkvdyXucmeNyLGPsYkCUrMgOkGc7DWXPOioND6OLmpTXoLVRFF4nK8clCA0Lz1Q/RUZAezgAAAA=="
},
"Metadata": {
"aws:cdk:path": "amplify-discussions-e2e-sandbox-x/auth/CDKMetadata/Default"
Expand Down Expand Up @@ -367,20 +367,20 @@
}
},
"Outputs": {
"amplifydiscussionse2esandbox11f7701e3cauthamplifyAuthUserPool78F21D47Ref": {
"Value": "us-east-1_QiMcYOBJq"
"amplifydiscussionse2esandbox70eded89e6authamplifyAuthUserPoolE62A968ERef": {
"Value": "us-east-1_hSkvuYzs4"
},
"amplifydiscussionse2esandbox11f7701e3cauthamplifyAuthUserPoolAppClientC0A8CDEFRef": {
"Value": "5fmpdjh49lauff16m1r548ug0t"
"amplifydiscussionse2esandbox70eded89e6authamplifyAuthUserPoolAppClient0977C3A8Ref": {
"Value": "50e30mj903868k89vugn5q3ul9"
},
"amplifydiscussionse2esandbox11f7701e3cauthamplifyAuthIdentityPool950F0C9ERef": {
"Value": "us-east-1:0ab20e5d-b843-4969-94b1-c17d26af9934"
"amplifydiscussionse2esandbox70eded89e6authamplifyAuthIdentityPool151D1C7ARef": {
"Value": "us-east-1:71501d31-e722-454c-ac1a-ccb858fb39f8"
},
"amplifydiscussionse2esandbox11f7701e3cauthamplifyAuthauthenticatedUserRole30DF3406Ref": {
"Value": "amplify-discussion2604142-amplifyAuthauthenticatedU-OFERj1VQgbh0"
"amplifydiscussionse2esandbox70eded89e6authamplifyAuthauthenticatedUserRole29023FD2Ref": {
"Value": "amplify-discussion2604162-amplifyAuthauthenticatedU-DpI98VU4kxL1"
},
"amplifydiscussionse2esandbox11f7701e3cauthamplifyAuthunauthenticatedUserRole937C879FRef": {
"Value": "amplify-discussion2604142-amplifyAuthunauthenticate-RegjzqZNry1w"
"amplifydiscussionse2esandbox70eded89e6authamplifyAuthunauthenticatedUserRoleBFC3E247Ref": {
"Value": "amplify-discussion2604162-amplifyAuthunauthenticate-fQoBMJqeFfIK"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
"AutoVerifiedAttributes": [
"email"
],
"EmailVerificationMessage": "Here is your verification code {####}",
"EmailVerificationSubject": "Verification",
"EmailVerificationMessage": "Your verification code is {####}",
"EmailVerificationSubject": "Your verification code",
"MfaConfiguration": "OFF",
"Policies": {
"PasswordPolicy": {
Expand Down Expand Up @@ -63,8 +63,8 @@
},
"VerificationMessageTemplate": {
"DefaultEmailOption": "CONFIRM_WITH_CODE",
"EmailMessage": "Here is your verification code {####}",
"EmailSubject": "Verification",
"EmailMessage": "Your verification code is {####}",
"EmailSubject": "Your verification code",
"SmsMessage": "The verification code to your new account is {####}"
}
},
Expand All @@ -89,7 +89,7 @@
"TokenValidityUnits": {
"RefreshToken": "minutes"
},
"UserPoolId": "us-east-1_QiMcYOBJq"
"UserPoolId": "us-east-1_hSkvuYzs4"
},
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete",
Expand Down Expand Up @@ -123,7 +123,7 @@
"SupportedIdentityProviders": [
"COGNITO"
],
"UserPoolId": "us-east-1_QiMcYOBJq"
"UserPoolId": "us-east-1_hSkvuYzs4"
},
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete",
Expand All @@ -137,7 +137,7 @@
"AllowUnauthenticatedIdentities": false,
"CognitoIdentityProviders": [
{
"ClientId": "5fmpdjh49lauff16m1r548ug0t",
"ClientId": "50e30mj903868k89vugn5q3ul9",
"ProviderName": {
"Fn::Join": [
"",
Expand All @@ -147,7 +147,7 @@
"Ref": "AWS::Region"
},
".amazonaws.com/",
"us-east-1_QiMcYOBJq"
"us-east-1_hSkvuYzs4"
]
]
}
Expand Down Expand Up @@ -178,7 +178,7 @@
"amplifyAuthIdentityPoolRoleAttachment045F17C8": {
"Type": "AWS::Cognito::IdentityPoolRoleAttachment",
"Properties": {
"IdentityPoolId": "us-east-1:0ab20e5d-b843-4969-94b1-c17d26af9934",
"IdentityPoolId": "us-east-1:71501d31-e722-454c-ac1a-ccb858fb39f8",
"RoleMappings": {
"UserPoolWebClientRoleMapping": {
"AmbiguousRoleResolution": "AuthenticatedRole",
Expand All @@ -191,18 +191,18 @@
"Ref": "AWS::Region"
},
".amazonaws.com/",
"us-east-1_QiMcYOBJq",
"us-east-1_hSkvuYzs4",
":",
"5fmpdjh49lauff16m1r548ug0t"
"50e30mj903868k89vugn5q3ul9"
]
]
},
"Type": "Token"
}
},
"Roles": {
"unauthenticated": "arn:aws:iam::123456789012:role/amplify-discussion2604142-amplifyAuthunauthenticate-RegjzqZNry1w",
"authenticated": "arn:aws:iam::123456789012:role/amplify-discussion2604142-amplifyAuthauthenticatedU-OFERj1VQgbh0"
"unauthenticated": "arn:aws:iam::123456789012:role/amplify-discussion2604162-amplifyAuthunauthenticate-fQoBMJqeFfIK",
"authenticated": "arn:aws:iam::123456789012:role/amplify-discussion2604162-amplifyAuthauthenticatedU-DpI98VU4kxL1"
}
},
"UpdateReplacePolicy": "Delete",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
{
"Source": {
"StackName": "amplify-discussions-e2e-sandbox-x-storage0EC3F24A-x",
"LogicalResourceId": "discusavatarsxgen2xBucketDA2F9CC2"
"LogicalResourceId": "discusavatarsxgen2xBucketDA2D0D6B"
},
"Destination": {
"StackName": "amplify-discussions-e2e-sandbox-x-storage0EC3F24A-x-holding",
"LogicalResourceId": "discusavatarsxgen2xBucketDA2F9CC2"
"LogicalResourceId": "discusavatarsxgen2xBucketDA2D0D6B"
}
}
]
Loading
Loading