@dismissible/nestjs-dynamodb-storage
v3.0.0
Published
DynamoDB storage adapter for Dismissible using AWS SDK v3
Maintainers
Readme
Dismissible manages the state of your UI elements across sessions, so your users see what matters, once! No more onboarding messages reappearing on every tab, no more notifications haunting users across devices. Dismissible syncs dismissal state everywhere, so every message is intentional, never repetitive.
@dismissible/nestjs-dynamodb-storage
DynamoDB storage adapter for the Dismissible system using AWS SDK v3.
Part of the Dismissible API - This library is part of the Dismissible API ecosystem. Visit dismissible.io for more information and documentation.
Overview
This library provides a production-ready DynamoDB storage adapter for the Dismissible system. It uses AWS SDK v3 for DynamoDB access and includes:
- Persistent storage of dismissible items using DynamoDB
- Support for LocalStack/DynamoDB Local for local development
- Automatic document serialization/deserialization
- Full TypeScript support
Installation
npm install @dismissible/nestjs-dynamodb-storagePrerequisites
- AWS account with DynamoDB access (or LocalStack for local development)
- Node.js 24 or higher
- AWS SDK for JavaScript v3 compatible environment
Getting Started
1. Create DynamoDB Table
Before using the storage module, you must create the DynamoDB table.
Option A: Using the CLI Tool (Recommended)
The package includes a CLI helper for table creation:
# For local development with LocalStack
DISMISSIBLE_STORAGE_DYNAMODB_ENDPOINT=http://localhost:4566 npx dismissible-dynamodb-setup
# For production (uses default AWS credentials)
DISMISSIBLE_STORAGE_DYNAMODB_AWS_REGION=us-east-1 npx dismissible-dynamodb-setupOption B: Using AWS Console or CLI
Create the table manually using AWS Console or AWS CLI:
aws dynamodb create-table \
--table-name items \
--attribute-definitions \
AttributeName=userId,AttributeType=S \
AttributeName=id,AttributeType=S \
--key-schema \
AttributeName=userId,KeyType=HASH \
AttributeName=id,KeyType=RANGE \
--billing-mode PAY_PER_REQUEST \
--region us-east-1Example item stored in the table:
{
"userId": "user-123",
"id": "welcome-banner-v2",
"createdAt": "2024-01-15T10:30:00.000Z",
"dismissedAt": "2024-01-15T12:00:00.000Z"
}Option C: Using CloudFormation/SAM
Resources:
DismissibleTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: dismissible-items
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: userId
AttributeType: S
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: userId
KeyType: HASH
- AttributeName: id
KeyType: RANGE2. Module Configuration
Import and configure the module in your NestJS application:
import { Module } from '@nestjs/common';
import { DismissibleModule } from '@dismissible/nestjs-core';
import { DynamoDBStorageModule } from '@dismissible/nestjs-dynamodb-storage';
import { LoggerModule } from '@dismissible/nestjs-logger';
@Module({
imports: [
LoggerModule.forRoot({}),
DynamoDBStorageModule.forRoot({
tableName: 'items',
region: 'us-east-1',
// Optional: endpoint for LocalStack
endpoint: process.env.DISMISSIBLE_STORAGE_DYNAMODB_ENDPOINT,
}),
DismissibleModule.forRoot({
storage: DynamoDBStorageModule,
}),
],
})
export class AppModule {}3. Async Configuration
You can also configure the module asynchronously:
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { DynamoDBStorageModule } from '@dismissible/nestjs-dynamodb-storage';
@Module({
imports: [
ConfigModule.forRoot(),
DynamoDBStorageModule.forRootAsync({
imports: [ConfigModule],
useFactory: (config: ConfigService) => ({
tableName: config.get<string>('DISMISSIBLE_STORAGE_DYNAMODB_TABLE_NAME')!,
region: config.get<string>('DISMISSIBLE_STORAGE_DYNAMODB_AWS_REGION'),
endpoint: config.get<string>('DISMISSIBLE_STORAGE_DYNAMODB_ENDPOINT'),
accessKeyId: config.get<string>('DISMISSIBLE_STORAGE_DYNAMODB_AWS_ACCESS_KEY_ID'),
secretAccessKey: config.get<string>('DISMISSIBLE_STORAGE_DYNAMODB_AWS_SECRET_ACCESS_KEY'),
sessionToken: config.get<string>('DISMISSIBLE_STORAGE_DYNAMODB_AWS_SESSION_TOKEN'),
}),
inject: [ConfigService],
}),
],
})
export class AppModule {}DynamoDB Table Schema
The library expects a DynamoDB table with the following schema:
| Attribute | Type | Key Type | Description | | ----------- | ------ | ------------- | ----------------------------- | | userId | String | Partition Key | User identifier | | id | String | Sort Key | Item identifier | | createdAt | String | - | ISO 8601 timestamp | | dismissedAt | String | - | ISO 8601 timestamp (nullable) |
Billing Mode: PAY_PER_REQUEST (on-demand capacity)
API Reference
DynamoDBStorageModule
DynamoDBStorageModule.forRoot(options)
Configures the DynamoDB storage module synchronously.
Options:
tableName: string- DynamoDB table name (required)region?: string- AWS region (default: us-east-1)endpoint?: string- DynamoDB endpoint URL (for LocalStack/DynamoDB Local)accessKeyId?: string- AWS access key IDsecretAccessKey?: string- AWS secret access keysessionToken?: string- AWS session token (optional)
Returns: DynamicModule
DynamoDBStorageModule.forRootAsync(options)
Configures the DynamoDB storage module asynchronously.
Options:
imports?: any[]- Modules to importuseFactory: (deps) => DynamoDBStorageModuleOptions- Factory functioninject?: any[]- Dependencies to inject into the factory
Returns: DynamicModule
DynamoDBStorageAdapter
The adapter implements IDismissibleStorage and provides:
get(userId, itemId)- Retrieve an itemcreate(item)- Create a new itemupdate(item)- Update an existing item
DynamoDBClientService
The service manages the DynamoDB client lifecycle:
- Initializes DynamoDBClient with configured credentials
- Creates DynamoDBDocumentClient for automatic serialization
- Handles connection lifecycle (no explicit cleanup required)
CLI Tool
The package includes a CLI tool for DynamoDB table setup:
# Create table with default settings
npx dismissible-dynamodb-setup
# With custom table name
DISMISSIBLE_STORAGE_DYNAMODB_TABLE_NAME=my-table npx dismissible-dynamodb-setup
# For LocalStack
DISMISSIBLE_STORAGE_DYNAMODB_ENDPOINT=http://localhost:4566 DISMISSIBLE_STORAGE_DYNAMODB_AWS_REGION=us-east-1 npx dismissible-dynamodb-setup
# For AWS
DISMISSIBLE_STORAGE_DYNAMODB_AWS_REGION=us-west-2 DISMISSIBLE_STORAGE_DYNAMODB_AWS_ACCESS_KEY_ID=xxx DISMISSIBLE_STORAGE_DYNAMODB_AWS_SECRET_ACCESS_KEY=yyy npx dismissible-dynamodb-setupEnvironment Variables
When using this package as part of the @dismissible/nestjs-api, the following environment variables will be available:
| Variable | Description | Default |
| ---------------------------------------------------- | ----------------------- | ----------------- |
| DISMISSIBLE_STORAGE_DYNAMODB_TABLE_NAME | DynamoDB table name | dismissible-items |
| DISMISSIBLE_STORAGE_DYNAMODB_AWS_REGION | AWS region | us-east-1 |
| DISMISSIBLE_STORAGE_DYNAMODB_AWS_ACCESS_KEY_ID | AWS access key ID | - |
| DISMISSIBLE_STORAGE_DYNAMODB_AWS_SECRET_ACCESS_KEY | AWS secret access key | - |
| DISMISSIBLE_STORAGE_DYNAMODB_AWS_SESSION_TOKEN | AWS session token | - |
| DISMISSIBLE_STORAGE_DYNAMODB_ENDPOINT | LocalStack endpoint URL | - |
For more information, see all configuration.
Local Development with LocalStack
LocalStack provides a local AWS cloud stack for development. To use it with this library:
- Start LocalStack:
docker run -d --name localstack -p 4566:4566 localstack/localstack- Create the table:
DISMISSIBLE_STORAGE_DYNAMODB_ENDPOINT=http://localhost:4566 DISMISSIBLE_STORAGE_DYNAMODB_AWS_REGION=us-east-1 npx dismissible-dynamodb-setup- Configure your application:
DynamoDBStorageModule.forRoot({
tableName: 'items',
region: 'us-east-1',
endpoint: 'http://localhost:4566',
accessKeyId: 'test',
secretAccessKey: 'test',
}),Production Considerations
- IAM Permissions: Ensure your application has the following permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"dynamodb:DeleteItem",
"dynamodb:Scan",
"dynamodb:BatchWriteItem",
"dynamodb:CreateTable",
"dynamodb:DescribeTable"
],
"Resource": "arn:aws:dynamodb:*:*:table/dismissible-items"
}
]
}[!IMPORTANT] Note: If you change the
DISMISSIBLE_STORAGE_DYNAMODB_TABLE_NAMEenvironment variable, you must update theResourceARN in the IAM policy to match your table name. The Resource ARN is restricted to the specific table name (dismissible-itemsby default) to prevent access to other tables.
[!CAUTION] Best Practice: While
dynamodb:CreateTableis included in the permissions above, it's recommended to create the table before deploying your application and avoid runningDISMISSIBLE_STORAGE_RUN_SETUP=trueduring production deployments. This reduces the risk of accidental table creation and follows the principle of least privilege.
Table Creation: Create the table before deploying your application. Use the CLI tool or CloudFormation/Terraform.
Monitoring: Enable CloudWatch metrics for DynamoDB to monitor throughput and latency.
Backups: Consider enabling point-in-time recovery for disaster recovery.
Related Packages
@dismissible/nestjs-core- Main dismissible service@dismissible/nestjs-storage- Storage interface@dismissible/nestjs-item- Data models@dismissible/nestjs-logger- Logging
License
MIT
