Primitives.org.ai

Digital Objects

Unified storage primitive for AI primitives

Digital Objects provides a unified nouns/verbs/things/actions model that forms the foundation for AI-native applications. It combines entity storage, event sourcing, and graph relationships into a single coherent abstraction.

Why Digital Objects?

Traditional databases separate schemas from data, events from relationships, and audit trails from business logic. Digital Objects unifies these concepts:

ConceptTraditionalDigital Objects
SchemaSeparate DDLNouns with linguistic forms
DataRaw recordsThings with metadata
EventsEvent tablesActions are events
RelationshipsJoin tablesActions are graph edges
AuditSeparate logsActions include audit trail

Core Concepts

Nouns     ──define──>  Things
  │                      │
  │                      │
Verbs     ──define──>  Actions ──────> Graph Edges
                         │              Event Log
                         └─────────────> Audit Trail

Nouns

Entity type definitions with linguistic consistency:

import { MemoryProvider } from 'digital-objects'

const provider = new MemoryProvider()

// Define a noun with auto-derived forms
await provider.defineNoun({ name: 'BlogPost' })
// Creates: singular='blog post', plural='blog posts', slug='blog-post'

Verbs

Action definitions with full conjugation support:

await provider.defineVerb({ name: 'publish' })
// Creates: action='publish', act='publishes', activity='publishing',
//          event='published', reverseBy='publishedBy', reverseAt='publishedAt'

Things

Entity instances that implement nouns:

const post = await provider.create('BlogPost', {
  title: 'Getting Started',
  content: 'Welcome to Digital Objects...',
})
// { id: 'abc123', noun: 'BlogPost', data: {...}, createdAt, updatedAt }

Actions

Events + relationships + audit trail unified:

const action = await provider.perform('publish', authorId, postId, {
  visibility: 'public',
})
// Creates a graph edge: author --publish--> post
// Also serves as an event record and audit entry

Quick Start

Installation

npm install digital-objects

Basic Usage

import { MemoryProvider } from 'digital-objects'

// Create a provider
const provider = new MemoryProvider()

// Define your domain
await provider.defineNoun({ name: 'User' })
await provider.defineNoun({ name: 'Post' })
await provider.defineVerb({ name: 'create' })
await provider.defineVerb({ name: 'follow' })

// Create entities
const alice = await provider.create('User', { name: 'Alice' })
const bob = await provider.create('User', { name: 'Bob' })
const post = await provider.create('Post', {
  title: 'Hello World',
  author: alice.id,
})

// Create relationships via actions
await provider.perform('create', alice.id, post.id)
await provider.perform('follow', bob.id, alice.id)

// Query the graph
const followers = await provider.related(alice.id, 'follow', 'in')
// [{ id: bob.id, noun: 'User', data: { name: 'Bob' }, ... }]

With Cloudflare Workers

import { NS } from 'digital-objects/ns'

export default {
  async fetch(request: Request, env: Env) {
    const ns = env.NS.get(env.NS.idFromName('my-namespace'))
    return ns.fetch(request)
  }
}

// wrangler.toml
// [[durable_objects.bindings]]
// name = "NS"
// class_name = "NS"

Architecture

Digital Objects supports multiple storage backends:

ProviderUse CaseStorage
MemoryProviderTesting, developmentIn-memory Maps
NSProduction on WorkersSQLite in Durable Objects
NSClientExternal accessHTTP to NS

All providers implement the same DigitalObjectsProvider interface, making it easy to switch between them.

Key Features

Linguistic Consistency

Nouns and verbs automatically derive all grammatical forms:

import { deriveNoun, deriveVerb } from 'digital-objects'

deriveNoun('BlogPost')
// { singular: 'blog post', plural: 'blog posts', slug: 'blog-post' }

deriveVerb('publish')
// { action: 'publish', act: 'publishes', activity: 'publishing',
//   event: 'published', reverseBy: 'publishedBy', reverseAt: 'publishedAt' }

Unified Graph Model

Actions serve triple duty as events, relationships, and audit records:

// This single action:
await provider.perform('assign', managerId, taskId, { priority: 'high' })

// Creates:
// 1. A graph edge: manager --assign--> task
// 2. An event record: "assign happened at {time}"
// 3. An audit entry: "who did what to whom"

R2 Persistence

Backup and restore with Cloudflare R2:

import { createSnapshot, restoreSnapshot } from 'digital-objects'

// Backup
await createSnapshot(provider, r2, 'my-namespace')

// Restore
await restoreSnapshot(provider, r2, 'my-namespace')

Type Safety

Full TypeScript support with generics:

interface User {
  name: string
  email: string
}

interface Post {
  title: string
  content: string
}

const user = await provider.create<User>('User', {
  name: 'Alice',
  email: 'alice@example.com',
})
// user.data is typed as User

const posts = await provider.list<Post>('Post')
// posts is Thing<Post>[]

When to Use Digital Objects

Use digital-objects when you need:

  • A unified model for entities, relationships, and events
  • Linguistic consistency (auto-pluralization, verb conjugation)
  • Cloudflare Durable Objects as your backend
  • Graph traversal capabilities
  • Built-in audit trail

Consider alternatives when you need:

  • Complex SQL joins (use a traditional ORM)
  • Real-time subscriptions (add Durable Objects WebSockets)
  • Full-text search with ranking (add a search engine)

Next Steps

  • Nouns - Learn about entity type definitions
  • Verbs - Understand action conjugations
  • Things - CRUD operations for entities
  • Actions - Events, edges, and audit trails
  • Graph - Traverse relationships
  • Providers - Choose your storage backend
  • R2 Persistence - Backup and restore
  • Database - The ai-database package for SQL-like operations with promise pipelining
Was this page helpful?

On this page