Skip to content

feat(examples): add minimal CRUD API example backed directly by DynamoDB#264

Open
laazyj wants to merge 2 commits into
mainfrom
claude/minimal-crud-example-app-r96xph
Open

feat(examples): add minimal CRUD API example backed directly by DynamoDB#264
laazyj wants to merge 2 commits into
mainfrom
claude/minimal-crud-example-app-r96xph

Conversation

@laazyj

@laazyj laazyj commented Jul 4, 2026

Copy link
Copy Markdown
Owner

What & why

Adds ComposureCDK-CrudApiStack, a new example demonstrating the minimal possible CRUD API: API Gateway wired directly to DynamoDB via AwsIntegration/VTL mapping templates — no Lambda in the request path. This exercises the parts of ComposureCDK the request asked to highlight:

  • createTableV2Builder for the item store (a "gadgets" catalog — the business domain is arbitrary), keyed on id.
  • createServiceRoleBuilder("apigateway.amazonaws.com") for the role API Gateway assumes to call DynamoDB.
  • createRestApiBuilder wiring each HTTP verb (GET/POST on /gadgets, GET/PUT/DELETE on /gadgets/{id}) straight to a DynamoDB action (Scan, PutItem, GetItem, DeleteItem) — the resource tree is declared directly inside the compose() call, so every path/verb/action/VTL mapping is visible at its addMethod call site.

New declarative grant API in @composurecdk/dynamodb. The example's IAM wiring needed a table to grant access to a role built by a sibling component. Rather than reach for an imperative afterBuild hook, this PR adds grantReadData/grantWriteData/grantReadWriteData to createTableBuilder and createTableV2Builder, each accepting a Resolvable<IGrantable> — the same declarative pattern as the Neptune cluster builder's allowAccessFrom(ref(...)). The grant is queued at configuration time (table.grantReadWriteData(ref("apiRole", r => r.role))) and applied inside the table's own build() once the role resolves. Backed by a small shared TableGrants queue (packages/dynamodb/src/table-grants.ts) used by both builders, with unit tests covering concrete and Ref grantees plus .copy() preservation.

Also included, per the existing example conventions:

  • Registered in bin/app.ts and the packages/examples/README.md stack table.
  • A DynamoDB TableV2 removal-policy IPropertyInjector added to cleanDeskPolicy (this is the first example to use a DynamoDB table, and the doc comment there called out DynamoDB as a known gap) so the table can be torn down in CI.
  • A unit test (test/crud-api-app.test.ts) covering the resource tree, the AwsIntegration wiring, and the IAM grant.
  • A dedicated smoke test (test/smoke/crud-api.smoke.mjs) that exercises the full create → read → update → delete lifecycle against a live deployment, since this stack's runtime surface is the CRUD flow itself.

Checklist

  • Linked to an issue (or it's a small, obvious fix) — new example app + a small builder-API addition, no pattern change
  • npm run verify passes locally
  • Tests added/updated for the change

claude added 2 commits July 4, 2026 07:05
Adds ComposureCDK-CrudApiStack, demonstrating API Gateway wired straight
to DynamoDB via AwsIntegration/VTL mapping templates — no Lambda in the
request path. Grants the API's execution role least-privilege access to
the table via table.grantReadWriteData() in an afterBuild hook.

Also adds a DynamoDB TableV2 removal-policy injector to cleanDeskPolicy
so the new example's table can be torn down in CI, and a smoke test
that exercises the full create/read/update/delete lifecycle against a
live deployment.
Adds grantReadData/grantWriteData/grantReadWriteData to createTableBuilder
and createTableV2Builder, accepting a Resolvable<IGrantable> so a sibling
component's role can be granted access via ref() and applied during the
table's own build() — the same declarative pattern as the Neptune cluster
builder's allowAccessFrom(), instead of an imperative afterBuild hook.

Updates the crud-api-app example to use table.grantReadWriteData(ref(...))
and inlines its API resource tree directly into the compose() call, so the
HTTP verb -> DynamoDB action -> VTL mapping for each method is visible at
its addMethod call site rather than hidden behind a helper function.
tableAndRole: ["table", "apiRole"],
api: ["tableAndRole"],
},
).build(stack, "CrudApiApp");

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is terrible. We'll work on it some more

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants