Back to list
martinffx

dynamodb-toolbox

by martinffx

My Spec-Driven workflow for Claude Code

0🍴 0📅 Jan 11, 2026

SKILL.md


name: dynamodb-toolbox description: DynamoDB single-table design using dynamodb-toolbox v2. Use when creating entities, defining key patterns, designing GSIs, writing queries, implementing pagination, or working with any DynamoDB data layer in TypeScript projects.

DynamoDB with dynamodb-toolbox v2

Type-safe DynamoDB interactions with Entity and Table abstractions.

Table Configuration

import { Table } from 'dynamodb-toolbox/table'

const AppTable = new Table({
  name: process.env.TABLE_NAME || "AppTable",
  partitionKey: { name: "PK", type: "string" },
  sortKey: { name: "SK", type: "string" },
  indexes: {
    GSI1: {
      type: "global",
      partitionKey: { name: "GSI1PK", type: "string" },
      sortKey: { name: "GSI1SK", type: "string" },
    },
    GSI2: {
      type: "global",
      partitionKey: { name: "GSI2PK", type: "string" },
      sortKey: { name: "GSI2SK", type: "string" },
    },
    GSI3: {
      type: "global",
      partitionKey: { name: "GSI3PK", type: "string" },
      sortKey: { name: "GSI3SK", type: "string" },
    },
  },
  entityAttributeSavedAs: "_et", // default, customize if needed
});

Index Purpose

IndexPurpose
Main Table (PK/SK)Primary entity access
GSI1General secondary access patterns
GSI2Entity-specific queries and relationships
GSI3Hierarchical queries with temporal sorting

Key Patterns

Entity:      ENTITY#{id}
Hierarchy:   PARENT#{parent_id}#CHILD#{child_id}
Prefix:      TYPE#{category}#{identifier}
Temporal:    ENTITY#{id}#{timestamp}

Entity Definition (v2 syntax)

import { Entity } from 'dynamodb-toolbox/entity'
import { item } from 'dynamodb-toolbox/schema/item'
import { string } from 'dynamodb-toolbox/schema/string'
import { number } from 'dynamodb-toolbox/schema/number'
import { prefix } from 'dynamodb-toolbox/transformers/prefix'

const UserEntity = new Entity({
  name: "USER",
  table: AppTable,
  schema: item({
    // Key attributes - use .key() and .savedAs() for mapping
    username: string().key().savedAs("PK").transform(prefix("ACCOUNT#")),
    sk: string().key().savedAs("SK").default(() => "PROFILE"),
    
    // GSI keys
    gsi1pk: string().savedAs("GSI1PK").optional(),
    gsi1sk: string().savedAs("GSI1SK").optional(),
    
    // Regular attributes
    email: string(),
    bio: string().optional(),
    createdAt: string().default(() => new Date().toISOString()),
  }),
});

Alternative: Using computeKey

const UserEntity = new Entity({
  name: "USER",
  table: AppTable,
  schema: item({
    username: string().key(),
    email: string(),
  }),
  computeKey: ({ username }) => ({
    PK: `ACCOUNT#${username}`,
    SK: "PROFILE",
  }),
});
const RepoEntity = new Entity({
  name: "REPO",
  table: AppTable,
  schema: item({
    owner: string().key(),
    repoName: string().key(),
  }).and(prev => ({
    PK: string().key().link<typeof prev>(
      ({ owner, repoName }) => `REPO#${owner}#${repoName}`
    ),
    SK: string().key().link<typeof prev>(
      ({ owner, repoName }) => `REPO#${owner}#${repoName}`
    ),
  })),
});

Type Safety (v2)

import { type InputItem, type DecodedItem } from 'dynamodb-toolbox/entity'

// Input types for creating/updating
type UserInput = InputItem<typeof UserEntity>

// Output types for reading
type User = DecodedItem<typeof UserEntity>

Repository Pattern (v2)

import { EntityRepository } from 'dynamodb-toolbox/entity/actions/repository'

const userRepo = UserEntity.build(EntityRepository)

// Put
await userRepo.put({ username: "alice", email: "alice@example.com" })

// Get
const { Item } = await userRepo.get({ username: "alice" })

// Delete
await userRepo.delete({ username: "alice" })

Query Commands

import { QueryCommand } from 'dynamodb-toolbox/table/actions/query'

const { Items } = await AppTable.build(QueryCommand)
  .entities(UserEntity)
  .query({ partition: "ACCOUNT#alice" })
  .send()

Pagination

function encodePageToken(lastEvaluated?: Record<string, any>): string | undefined {
  if (!lastEvaluated) return undefined;
  return Buffer.from(JSON.stringify(lastEvaluated)).toString("base64");
}

function decodePageToken(token?: string): Record<string, any> | undefined {
  if (!token) return undefined;
  return JSON.parse(Buffer.from(token, "base64").toString());
}

Guidelines

  1. Use item({}) or map({}) for schema definition (not schema())
  2. Mark key attributes with .key()
  3. Use .savedAs() to map to table attribute names
  4. Use .transform(prefix(...)) for key prefixes
  5. Use DecodedItem for read types, InputItem for write types
  6. Prefer EntityRepository for simple CRUD operations
  7. Use computeKey or .link() for complex key derivation

Score

Total Score

55/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

0/5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon