npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@arcaelas/dynamite

v1.0.29

Published

<p align="center"> <img src="docs/assets/cover.png" alt="Dynamite ORM - Arcaelas Insiders for DynamoDB" width="100%"> </p>

Readme

@arcaelas/dynamite

A modern, decorator-first ORM for DynamoDB with TypeScript support Full-featured | Type-safe | Relationships | Auto table creation | Transactions


Quick Start

import { Dynamite, Table, PrimaryKey, Default, CreatedAt, UpdatedAt, CreationOptional } from "@arcaelas/dynamite";

// Define your model
class User extends Table<User> {
  @PrimaryKey()
  @Default(() => crypto.randomUUID())
  declare id: CreationOptional<string>;

  declare name: string;
  declare email: string;

  @Default(() => "customer")
  declare role: CreationOptional<string>;

  @CreatedAt()
  declare created_at: CreationOptional<string>;

  @UpdatedAt()
  declare updated_at: CreationOptional<string>;
}

// Connect to DynamoDB
const dynamite = new Dynamite({
  region: "us-east-1",
  endpoint: "http://localhost:8000", // DynamoDB Local
  credentials: { accessKeyId: "test", secretAccessKey: "test" },
  tables: [User]
});

await dynamite.connect();

// Use it!
const user = await User.create({ name: "John Doe", email: "[email protected]" });
console.log(user.id);         // "a1b2c3d4-..."
console.log(user.role);       // "customer"
console.log(user.created_at); // "2025-01-15T10:30:00.000Z"

Installation

npm install @arcaelas/dynamite

Decorators

Index Decorators

| Decorator | Description | |-----------|-------------| | @PrimaryKey() | Primary key (partition key) | | @Index() | Partition key for GSI | | @IndexSort() | Sort key |

Data Decorators

| Decorator | Description | |-----------|-------------| | @Default(value \| fn) | Default value (static or dynamic) | | @Mutate(fn) | Transform value before save | | @Validate(fn) | Validate value before save | | @Serialize(fromDB, toDB) | Bidirectional transformation | | @NotNull() | Required field validation | | @Name("custom") | Custom column/table name | | @Column() | Column configuration |

Timestamp Decorators

| Decorator | Description | |-----------|-------------| | @CreatedAt() | Auto-set on creation | | @UpdatedAt() | Auto-set on every update | | @DeleteAt() | Soft delete timestamp |

Relationship Decorators

| Decorator | Description | |-----------|-------------| | @HasMany(() => Model, "foreign_key") | One-to-many | | @HasOne(() => Model, "foreign_key") | One-to-one | | @BelongsTo(() => Model, "local_key") | Many-to-one | | @ManyToMany(() => Model, config) | Many-to-many with pivot table |


TypeScript Types

import {
  CreationOptional,  // Optional during create(), required after
  NonAttribute,      // Excluded from database (computed/relations)
  InferAttributes,   // Extract DB attributes from model
  InferRelations,    // Extract relations from model
  CreateInput,       // Input type for create()
  UpdateInput,       // Input type for update()
  WhereOptions,      // Query options type
  QueryOperator      // Available operators
} from "@arcaelas/dynamite";

CreationOptional

Use for fields that are optional during creation but exist after:

class User extends Table<User> {
  @PrimaryKey()
  @Default(() => crypto.randomUUID())
  declare id: CreationOptional<string>;  // Optional in create()

  declare name: string;  // Required in create()

  @CreatedAt()
  declare created_at: CreationOptional<string>;  // Auto-generated
}

NonAttribute

Use for computed properties and relations (not stored in DB):

class User extends Table<User> {
  declare first_name: string;
  declare last_name: string;

  // Computed property - not stored
  declare full_name: NonAttribute<string>;

  // Relations - loaded via include
  @HasMany(() => Order, "user_id")
  declare orders: NonAttribute<Order[]>;
}

Query Operations

Basic Queries

// Get all
const users = await User.where({});

// Filter by field
const admins = await User.where({ role: "admin" });
const user = await User.where("email", "[email protected]");

// First/Last
const first = await User.first({ active: true });
const last = await User.last({});

Query Operators

// Comparison
await User.where("age", ">=", 18);
await User.where("age", "<", 65);
await User.where("status", "!=", "banned");

// Array membership
await User.where("role", "in", ["admin", "moderator"]);

// String contains
await User.where("email", "$include", "gmail");

Available operators: =, !=, <>, <, <=, >, >=, in, $include

Query Options

const users = await User.where({}, {
  limit: 10,
  skip: 20,
  order: "DESC",
  attributes: ["id", "name", "email"],
  include: {
    orders: {
      where: { status: "completed" },
      limit: 5
    }
  }
});

Relationships

Defining Relations

class User extends Table<User> {
  @PrimaryKey()
  declare id: string;

  @HasMany(() => Order, "user_id")
  declare orders: NonAttribute<Order[]>;

  @HasOne(() => Profile, "user_id")
  declare profile: NonAttribute<Profile | null>;

  @ManyToMany(() => Role, {
    pivotTable: "user_roles",
    foreignKey: "user_id",
    relatedKey: "role_id"
  })
  declare roles: NonAttribute<Role[]>;
}

class Order extends Table<Order> {
  @PrimaryKey()
  declare id: string;

  declare user_id: string;

  @BelongsTo(() => User, "user_id")
  declare user: NonAttribute<User | null>;
}

Loading Relations

const users = await User.where({}, {
  include: {
    orders: { where: { status: "completed" } },
    profile: {},
    roles: {}
  }
});

ManyToMany Operations

const user = await User.first({ id: "user-1" });

// Attach relation
await user.attach(Role, "role-123");

// Detach relation
await user.detach(Role, "role-123");

// Sync relations (replace all)
await user.sync(Role, ["role-1", "role-2", "role-3"]);

CRUD Operations

Create

const user = await User.create({
  name: "John Doe",
  email: "[email protected]"
});

Read

const users = await User.where({ active: true });
const user = await User.first({ id: "user-123" });

Update

// Static update (bulk)
await User.update({ role: "premium" }, { id: "user-123" });

// Instance update
user.name = "Jane Doe";
await user.save();

// Or
await user.update({ name: "Jane Doe" });

Delete

// Static delete (bulk)
await User.delete({ status: "inactive" });

// Instance delete (soft delete if @DeleteAt present)
await user.destroy();

// Force hard delete
await user.forceDestroy();

Soft Deletes

class Post extends Table<Post> {
  @PrimaryKey()
  declare id: string;

  declare title: string;

  @DeleteAt()
  declare deleted_at: CreationOptional<string | null>;
}

// Soft delete
await post.destroy(); // Sets deleted_at timestamp

// Query including soft-deleted
const all = await Post.withTrashed({});

// Query only soft-deleted
const trashed = await Post.onlyTrashed({});

// Force hard delete
await post.forceDestroy();

Transactions

await dynamite.tx(async (tx) => {
  const user = await User.create({ name: "John" }, tx);
  await Order.create({ user_id: user.id, total: 100 }, tx);
  // If any operation fails, all are rolled back
});

Configuration

DynamoDB Local

const dynamite = new Dynamite({
  region: "us-east-1",
  endpoint: "http://localhost:8000",
  credentials: { accessKeyId: "test", secretAccessKey: "test" },
  tables: [User, Order, Product]
});

await dynamite.connect();

AWS DynamoDB

const dynamite = new Dynamite({
  region: "us-east-1",
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!
  },
  tables: [User, Order, Product]
});

await dynamite.connect();

Docker Setup

docker run -d -p 8000:8000 amazon/dynamodb-local

API Reference

Static Methods

// CRUD
static create(data, tx?): Promise<T>
static update(data, filters, tx?): Promise<number>
static delete(filters, tx?): Promise<number>

// Query
static where(filters, options?): Promise<T[]>
static where(field, value): Promise<T[]>
static where(field, operator, value): Promise<T[]>
static first(filters?, options?): Promise<T | undefined>
static last(filters?, options?): Promise<T | undefined>

// Soft deletes
static withTrashed(filters?, options?): Promise<T[]>
static onlyTrashed(filters?, options?): Promise<T[]>

Instance Methods

// CRUD
save(): Promise<boolean>
update(data): Promise<boolean>
destroy(): Promise<null>
forceDestroy(): Promise<null>

// ManyToMany
attach(Model, id, pivotData?): Promise<void>
detach(Model, id): Promise<void>
sync(Model, ids): Promise<void>

// Serialization
toJSON(): Record<string, unknown>

Documentation

For complete documentation, examples, and guides:

arcaelas.github.io/dynamite


License

MIT License - see LICENSE file for details.


Made with care by Miguel Alejandro - Arcaelas Insiders