Understanding the $ SDK
Complete guide to the $ SDK and semantic Business-as-Code patterns
The $ SDK is the foundation of Business-as-Code on the .do platform. It provides a semantic interface for defining, deploying, and operating businesses programmatically.
Philosophy
The $ SDK is built on three core principles:
- Semantic Intent - Express what you want, not how to do it
- Composability - Combine simple functions into complex business logic
- AI-Native - Build systems that AI agents can understand and execute
Installation
pnpm install sdk.doimport $, { ai, api, db, on, send, every, user } from 'sdk.do'The $ Semantic Proxy
The $ object is a JavaScript Proxy that creates semantic paths using the $.Subject.predicate.Object pattern.
Basic Usage
import $ from 'sdk.do'
// Entity types
$.Person
$.Organization
$.Product
$.Order
// Relationships
$.Person.worksFor.Organization
$.Business.owns.Brand
$.Product.manufacturer.Organization
// Events
$.Order.created
$.Invoice.paid
$.Customer.registered
// Operations
$.Report.generate
$.Email.send
$.Inventory.syncHow It Works
The $ proxy intercepts property access to build semantic paths:
// Each property access extends the path
const path = $.Person.worksFor.Organization
// Convert to string to see the full path
console.log(String(path)) // "$.Person.worksFor.Organization"
// Use in semantic operations
on($.Order.created, handler)
await send($.Invoice.generate, data)
const businesses = await db.list($.Business)Dynamic Access
Use bracket notation for dynamic property access:
// Static access
$.Person.john.worksFor.Organization.acme
// Dynamic access
const personId = 'john'
const orgId = 'acme'
$.Person[personId].worksFor.Organization[orgId]Core Primitives
db - Database Operations
Manage business data with semantic types:
import { db } from 'sdk.do'
// List entities by semantic type
const businesses = await db.list($.Business, {
where: { status: 'active' },
limit: 100,
})
// Get entity by type and ID
const business = await db.get($.Business, 'acme-corp')
// Create with semantic type
await db.create($.Business, {
$id: 'acme-corp',
$type: $.Business,
name: 'Acme Corp',
status: 'active',
})
// Update entity
await db.update($.Business, 'acme-corp', {
status: 'verified',
})
// Delete entity
await db.delete($.Business, 'acme-corp')
// Query relationships
const brands = await db.related(business, $.owns, $.Brand)
const employees = await db.related(business, $.employs, $.Person)
// Create relationships
await db.relate(business, $.owns, brand)
await db.relate(person, $.worksFor, organization)ai - AI Services
Integrate AI into your business operations:
import { ai } from 'sdk.do'
// Generate text with semantic context
const content = await ai.generate({
prompt: 'Write a blog post about Business-as-Code',
schema: $.BlogPosting,
model: 'claude-sonnet-4.5',
})
// Generate structured data
const product = await ai.generate({
prompt: 'Create a product description for a laptop',
schema: $.Product,
model: 'gpt-5',
})
// Create embeddings for semantic search
const embeddings = await ai.embed('Business-as-Code enables autonomous operations')
// Batch processing for efficiency
const results = await ai.batch([
{ prompt: 'Summarize Q1 results', schema: $.Report },
{ prompt: 'Generate social posts', schema: $.SocialMediaPosting },
{ prompt: 'Create email campaign', schema: $.EmailMessage },
])on - Event Listeners
React to business events with semantic patterns:
import { on } from 'sdk.do'
// Listen for specific events
on($.Order.created, async (order) => {
console.log('New order:', order.id)
await processOrder(order)
})
on($.Invoice.paid, async (invoice) => {
console.log('Payment received:', invoice.amount)
await fulfillOrder(invoice.orderId)
})
// Pattern matching with wildcards
on($.*.created, async (entity) => {
console.log('Entity created:', entity.$type, entity.$id)
await logEvent('entity_created', entity)
})
// Multiple event types
on([$.Order.created, $.Order.updated], async (order) => {
await updateInventory(order)
await notifyWarehouse(order)
})
// Scoped event listeners
on($.Customer.*.*, async (event) => {
// Matches all customer events
// $.Customer.registered, $.Customer.updated, etc.
await trackCustomerActivity(event)
})send - Event Publishing
Trigger business operations by sending semantic events:
import { send } from 'sdk.do'
// Send business events
await send($.Order.created, {
$type: $.Order,
$id: 'order-123',
customer: 'customer-456',
items: [...],
total: 99.99
})
await send($.Invoice.paid, {
$type: $.Invoice,
$id: 'invoice-789',
orderId: 'order-123',
amount: 99.99
})
// Trigger operations
await send($.Report.generate, {
type: 'monthly',
month: '2025-10'
})
// Send to external services
await send($.Email.send, {
to: '[email protected]',
subject: 'Order Confirmation',
template: 'order-confirmation',
data: { order }
})every - Scheduled Tasks
Run business operations on a schedule:
import { every } from 'sdk.do'
// Named schedules
every($.Daily, async () => {
await send($.Report.generate, { type: 'daily' })
await send($.Backup.create, { type: 'incremental' })
})
every($.Hourly, async () => {
await send($.Metrics.collect, { interval: 'hourly' })
})
every($.Weekly, async () => {
await send($.Newsletter.send, { day: 'monday' })
})
every($.Monthly, async () => {
await send($.Invoice.generate, { type: 'subscription' })
})
// Cron expressions for precise scheduling
every('0 0 * * *', async () => {
// Every day at midnight
await send($.Backup.create, { type: 'full' })
})
every('0 */4 * * *', async () => {
// Every 4 hours
await send($.Inventory.sync, { source: 'warehouse' })
})
every('0 9 * * 1', async () => {
// Every Monday at 9am
await send($.Report.weekly, { recipients: ['[email protected]'] })
})api - External Integrations
Connect to external services with semantic context:
import { api } from 'sdk.do'
// Stripe integration
const customer = await api.stripe.customers.create({
email: '[email protected]',
metadata: {
$type: $.Person,
$id: 'customer-123',
},
})
// Generic HTTP requests
const response = await api.fetch('https://api.example.com/data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: 'value' }),
})
// OAuth integration
const token = await api.oauth.authorize({
provider: 'github',
scope: ['user', 'repo'],
})user - User Context
Access current user information and permissions:
import { user } from 'sdk.do'
// Get current user
const currentUser = await user.current()
console.log(currentUser.id, currentUser.email)
// Check permissions
const canEdit = await user.can('edit', $.Blog)
const canDelete = await user.can('delete', $.Blog, 'blog-123')
// Get user session
const session = await user.session()
// Access user properties
const userId = user.id
const userEmail = user.email
const userRoles = user.rolesSemantic Pattern Reference
Subject.predicate.Object
The fundamental pattern for expressing relationships:
// Entity relationships
$.Person.worksFor.Organization
$.Organization.owns.Brand
$.Product.manufacturer.Organization
$.Person.knows.Person
// Event paths
$.Order.created.by.Customer
$.Invoice.paid.via.Stripe
$.Email.sent.to.Customer
// Operation chains
$.Order.fulfillment.requires.Inventory
$.Report.generation.uses.AnalyticsCommon Patterns
Lifecycle Events:
$.Entity.created
$.Entity.updated
$.Entity.deleted
$.Entity.archivedBusiness Events:
$.Order.placed
$.Order.confirmed
$.Order.shipped
$.Order.delivered
$.Order.cancelledWorkflow Operations:
$.Invoice.generate
$.Email.send
$.Report.create
$.Backup.start
$.Inventory.syncBest Practices
1. Use Semantic Types
Always specify semantic types for entities:
// Good
await db.create($.Business, {
$type: $.Business,
$id: 'acme-corp',
name: 'Acme Corp',
})
// Avoid
await db.Businesses.create({
id: 'acme-corp',
name: 'Acme Corp',
})2. Compose Event Chains
Build complex workflows from simple event chains:
// Order fulfillment workflow
on($.Order.created, async (order) => {
await send($.Order.validate, order)
})
on($.Order.validated, async (order) => {
await send($.Payment.process, order)
})
on($.Payment.completed, async (payment) => {
await send($.Inventory.reserve, payment.order)
})
on($.Inventory.reserved, async (reservation) => {
await send($.Shipment.create, reservation)
})3. Use Semantic Queries
Query by semantic type and relationships:
// Get all businesses
const businesses = await db.list($.Business)
// Get brands owned by business
const brands = await db.related(business, $.owns, $.Brand)
// Get employees of organization
const employees = await db.related(org, $.employs, $.Person)4. Error Handling
Handle errors gracefully in event handlers:
on($.Order.created, async (order) => {
try {
await send($.Payment.process, order)
} catch (error) {
await send($.Order.failed, { order, error: error.message })
await send($.Alert.send, {
severity: 'error',
message: `Order ${order.id} failed: ${error.message}`,
})
}
})5. Type Safety
Use TypeScript types from schema.org.ai:
import type { Organization, Person, Product } from 'schema.org.ai'
const business: Organization = {
$type: 'Organization',
$id: 'acme-corp',
name: 'Acme Corp',
employee: [...]
}Advanced Usage
Custom Semantic Paths
Define custom business-specific paths:
// Define domain-specific paths
const CustomerLifecycle = {
registered: $.Customer.registered,
verified: $.Customer.verified,
subscribed: $.Customer.subscribed,
churned: $.Customer.churned,
}
// Use in event handlers
on(CustomerLifecycle.registered, async (customer) => {
await send(CustomerLifecycle.verified, customer)
})Workflow Orchestration
Build complex multi-step workflows:
// Define workflow stages
const OrderWorkflow = {
stages: [$.Order.created, $.Order.validated, $.Payment.processed, $.Inventory.reserved, $.Shipment.created, $.Order.delivered],
}
// Implement workflow
OrderWorkflow.stages.forEach((stage, index) => {
if (index < OrderWorkflow.stages.length - 1) {
const nextStage = OrderWorkflow.stages[index + 1]
on(stage, async (data) => {
await send(nextStage, data)
})
}
})Batch Operations
Efficiently process multiple operations:
// Batch database operations
const results = await Promise.all([db.create($.Business, business1), db.create($.Business, business2), db.create($.Business, business3)])
// Batch AI generation
const content = await ai.batch([
{ prompt: 'Generate post 1', schema: $.BlogPosting },
{ prompt: 'Generate post 2', schema: $.BlogPosting },
{ prompt: 'Generate post 3', schema: $.BlogPosting },
])Advanced Patterns
Event Sourcing
Maintain complete event history for audit and replay:
import { $, db, on, send } from 'sdk.do'
const EventSourcing = {
// Append-only event store
append: async (streamId, event) => {
const eventRecord = await db.create($.Event, {
$type: $.Event,
stream: streamId,
eventType: event.$type,
data: event,
timestamp: new Date(),
version: await getNextVersion(streamId),
})
// Publish event
await send(event.$type, event)
return eventRecord
},
// Rebuild entity from events
rehydrate: async (streamId) => {
const events = await db.list($.Event, {
where: { stream: streamId },
sort: 'version',
})
// Replay all events
let state = {}
for (const event of events) {
state = await applyEvent(state, event)
}
return state
},
// Snapshot for performance
snapshot: async (streamId, state) => {
await db.create($.Snapshot, {
stream: streamId,
state,
version: await getCurrentVersion(streamId),
timestamp: new Date(),
})
},
// Rebuild with snapshots
rehydrateWithSnapshot: async (streamId) => {
// Get latest snapshot
const snapshot = await db.get($.Snapshot, {
where: { stream: streamId },
sort: '-version',
limit: 1,
})
// Get events since snapshot
const events = await db.list($.Event, {
where: {
stream: streamId,
version: { $gt: snapshot?.version || 0 },
},
sort: 'version',
})
// Replay from snapshot
let state = snapshot?.state || {}
for (const event of events) {
state = await applyEvent(state, event)
}
return state
},
}
// Example: Order event sourcing
on($.Order.created, async (order) => {
await EventSourcing.append(`order-${order.id}`, {
$type: $.Order.created,
...order,
})
})
on($.Order.paid, async (payment) => {
await EventSourcing.append(`order-${payment.orderId}`, {
$type: $.Order.paid,
...payment,
})
})
// Rebuild order state
const orderState = await EventSourcing.rehydrate('order-123')CQRS (Command Query Responsibility Segregation)
Separate read and write models:
const CQRS = {
// Command side (write)
commands: {
createOrder: async (command) => {
// Validate command
const validation = await validate(command)
if (!validation.valid) {
throw new Error(validation.error)
}
// Execute command
const order = await db.create($.Order, {
...command,
status: 'pending',
})
// Emit events
await send($.Order.created, order)
return order.id
},
updateOrder: async (command) => {
const order = await db.get($.Order, command.orderId)
await db.update($.Order, command.orderId, {
...command.updates,
})
await send($.Order.updated, {
orderId: command.orderId,
changes: command.updates,
})
},
},
// Query side (read)
queries: {
// Denormalized read models
orderSummary: async (orderId) => {
return await db.get($.OrderSummary, orderId)
},
customerOrders: async (customerId) => {
return await db.list($.OrderSummary, {
where: { customerId },
sort: '-createdAt',
})
},
ordersByStatus: async (status) => {
return await db.list($.OrderSummary, {
where: { status },
})
},
},
// Projections (update read models from events)
projections: {
orderSummary: on($.Order.created, async (order) => {
await db.create($.OrderSummary, {
id: order.id,
customerId: order.customer,
customerName: order.customer.name,
total: order.total,
status: order.status,
itemCount: order.items.length,
createdAt: order.createdAt,
})
}),
updateOnPayment: on($.Order.paid, async (payment) => {
await db.update($.OrderSummary, payment.orderId, {
status: 'paid',
paidAt: payment.paidAt,
})
}),
},
}Reactive Programming
Build reactive data flows:
import { $, db, on, send } from 'sdk.do'
// Observable streams
const Observable = {
// Create observable from database query
fromQuery: (type, query) => {
const subscribers = []
// Initial data
db.list(type, query).then((results) => {
subscribers.forEach((fn) => fn(results))
})
// Watch for changes
on($[type].*, async (event) => {
const results = await db.list(type, query)
subscribers.forEach((fn) => fn(results))
})
return {
subscribe: (fn) => {
subscribers.push(fn)
return () => {
const index = subscribers.indexOf(fn)
if (index > -1) subscribers.splice(index, 1)
}
},
}
},
// Map operator
map: (observable, transform) => {
return {
subscribe: (fn) => {
return observable.subscribe((value) => fn(transform(value)))
},
}
},
// Filter operator
filter: (observable, predicate) => {
return {
subscribe: (fn) => {
return observable.subscribe((value) => {
if (predicate(value)) fn(value)
})
},
}
},
// Merge operator
merge: (...observables) => {
return {
subscribe: (fn) => {
const unsubscribers = observables.map((obs) => obs.subscribe(fn))
return () => unsubscribers.forEach((unsub) => unsub())
},
}
},
}
// Example: Reactive dashboard
const activeOrders$ = Observable.fromQuery($.Order, {
where: { status: 'active' },
})
const paidOrders$ = Observable.fromQuery($.Order, {
where: { status: 'paid' },
})
const orderCount$ = Observable.map(activeOrders$, (orders) => orders.length)
const totalRevenue$ = Observable.map(paidOrders$, (orders) =>
orders.reduce((sum, order) => sum + order.total, 0)
)
// Subscribe to updates
orderCount$.subscribe((count) => {
console.log(`Active orders: ${count}`)
updateDashboard({ activeOrders: count })
})
totalRevenue$.subscribe((revenue) => {
console.log(`Total revenue: $${revenue}`)
updateDashboard({ revenue })
})Domain-Driven Design
Implement DDD patterns with semantic types:
// Aggregates
const OrderAggregate = {
// Root entity
create: async (data) => {
const order = await db.create($.Order, {
$type: $.Order,
...data,
status: 'draft',
items: [],
})
return {
id: order.id,
addItem: async (item) => {
await db.update($.Order, order.id, {
items: [...order.items, item],
total: order.total + item.price * item.quantity,
})
await send($.Order.itemAdded, { orderId: order.id, item })
},
removeItem: async (itemId) => {
const item = order.items.find((i) => i.id === itemId)
await db.update($.Order, order.id, {
items: order.items.filter((i) => i.id !== itemId),
total: order.total - item.price * item.quantity,
})
await send($.Order.itemRemoved, { orderId: order.id, itemId })
},
submit: async () => {
if (order.items.length === 0) {
throw new Error('Cannot submit empty order')
}
await db.update($.Order, order.id, {
status: 'pending',
submittedAt: new Date(),
})
await send($.Order.submitted, order)
},
}
},
}
// Value Objects
const Money = {
create: (amount, currency = 'USD') => ({
amount,
currency,
add: (other) => {
if (currency !== other.currency) {
throw new Error('Currency mismatch')
}
return Money.create(amount + other.amount, currency)
},
multiply: (factor) => Money.create(amount * factor, currency),
equals: (other) => amount === other.amount && currency === other.currency,
}),
}
// Domain Services
const PricingService = {
calculateOrderTotal: async (order) => {
let total = Money.create(0)
for (const item of order.items) {
const price = await PricingService.getPrice(item.product, order.customer)
total = total.add(price.multiply(item.quantity))
}
// Apply discounts
const discounts = await PricingService.getDiscounts(order.customer)
for (const discount of discounts) {
total = total.add(total.multiply(-discount.rate))
}
return total
},
getPrice: async (product, customer) => {
const basePrice = Money.create(product.basePrice)
// Customer-specific pricing
if (customer.segment === 'enterprise') {
return basePrice.multiply(0.9) // 10% discount
}
return basePrice
},
}
// Repositories
const OrderRepository = {
findById: async (id) => {
const order = await db.get($.Order, id)
return OrderAggregate.create(order)
},
findByCustomer: async (customerId) => {
return await db.list($.Order, {
where: { customer: customerId },
})
},
save: async (order) => {
await db.update($.Order, order.id, order)
await send($.Order.updated, order)
},
}Microservices Communication
Coordinate between services using semantic events:
const ServiceMesh = {
// Service registry
services: {
orders: {
endpoint: 'https://orders.example.com',
events: [$.Order.created, $.Order.updated, $.Order.cancelled],
},
inventory: {
endpoint: 'https://inventory.example.com',
events: [$.Inventory.reserved, $.Inventory.released],
},
payments: {
endpoint: 'https://payments.example.com',
events: [$.Payment.processed, $.Payment.failed],
},
fulfillment: {
endpoint: 'https://fulfillment.example.com',
events: [$.Shipment.created, $.Shipment.shipped],
},
},
// RPC call to service
call: async (service, method, params) => {
const endpoint = ServiceMesh.services[service].endpoint
return await api.fetch(`${endpoint}/rpc/${method}`, {
method: 'POST',
body: JSON.stringify(params),
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${await getServiceToken(service)}`,
},
})
},
// Publish event to service
publish: async (event) => {
// Find services interested in this event
const interestedServices = Object.entries(ServiceMesh.services).filter(([, config]) =>
config.events.includes(event.$type)
)
// Publish to each service
await Promise.all(
interestedServices.map(async ([service, config]) => {
await api.fetch(`${config.endpoint}/events`, {
method: 'POST',
body: JSON.stringify(event),
headers: {
'Content-Type': 'application/json',
'X-Event-Type': event.$type,
},
})
})
)
},
// Circuit breaker pattern
withCircuitBreaker: (service, method) => {
let failures = 0
let lastFailure = null
const threshold = 5
const timeout = 60000 // 1 minute
return async (params) => {
// Check if circuit is open
if (failures >= threshold) {
const timeSinceLastFailure = Date.now() - lastFailure
if (timeSinceLastFailure < timeout) {
throw new Error(`Circuit breaker open for ${service}.${method}`)
} else {
// Reset circuit
failures = 0
}
}
try {
const result = await ServiceMesh.call(service, method, params)
failures = 0
return result
} catch (error) {
failures++
lastFailure = Date.now()
throw error
}
}
},
}
// Example: Order processing across services
on($.Order.created, async (order) => {
// Reserve inventory
const reservation = await ServiceMesh.call('inventory', 'reserve', {
items: order.items,
orderId: order.id,
})
// Process payment
const payment = await ServiceMesh.call('payments', 'charge', {
orderId: order.id,
amount: order.total,
customer: order.customer,
})
// Create shipment
if (payment.status === 'succeeded') {
await ServiceMesh.call('fulfillment', 'createShipment', {
orderId: order.id,
items: order.items,
address: order.shippingAddress,
})
}
})Testing Patterns
Comprehensive testing approaches:
import { $, db, on, send, test } from 'sdk.do'
// Unit tests
test('Order total calculation', async () => {
const order = {
items: [
{ product: 'item1', quantity: 2, price: 10 },
{ product: 'item2', quantity: 1, price: 25 },
],
}
const total = calculateOrderTotal(order)
expect(total).toBe(45) // 2*10 + 1*25
})
// Integration tests
test('Order workflow', async () => {
// Create test order
const order = await db.create($.Order, {
customer: 'test-customer',
items: [{ product: 'test-product', quantity: 1, price: 100 }],
})
// Trigger order processing
await send($.Order.created, order)
// Wait for async processing
await waitFor(async () => {
const updated = await db.get($.Order, order.id)
return updated.status === 'paid'
})
// Verify final state
const final = await db.get($.Order, order.id)
expect(final.status).toBe('paid')
expect(final.total).toBe(100)
})
// Event-driven tests
test('Order events', async () => {
const events = []
// Listen for events
const unsubscribe = on($.Order.*, (event) => {
events.push(event)
})
// Trigger workflow
const order = await db.create($.Order, { customer: 'test' })
await send($.Order.created, order)
await send($.Order.paid, order)
// Verify events
expect(events).toHaveLength(2)
expect(events[0].$type).toBe($.Order.created)
expect(events[1].$type).toBe($.Order.paid)
unsubscribe()
})
// Mocking external services
test('Payment processing', async () => {
// Mock Stripe
api.stripe = {
charges: {
create: async (params) => ({
id: 'ch_test_123',
status: 'succeeded',
amount: params.amount,
}),
},
}
const payment = await processPayment({
amount: 1000,
customer: 'cus_test',
})
expect(payment.status).toBe('succeeded')
})Performance Optimization
Caching Strategies
const Cache = {
// In-memory cache
memory: new Map(),
// Get with cache
get: async (key, fetcher, ttl = 3600) => {
// Check cache
const cached = Cache.memory.get(key)
if (cached && Date.now() - cached.timestamp < ttl * 1000) {
return cached.value
}
// Fetch and cache
const value = await fetcher()
Cache.memory.set(key, {
value,
timestamp: Date.now(),
})
return value
},
// Cache invalidation
invalidate: (pattern) => {
for (const key of Cache.memory.keys()) {
if (key.match(pattern)) {
Cache.memory.delete(key)
}
}
},
}
// Example: Cache expensive queries
const getPopularProducts = async () => {
return await Cache.get(
'popular-products',
async () => {
return await db.list($.Product, {
sort: '-views',
limit: 10,
})
},
300 // 5 minutes
)
}
// Invalidate on product update
on($.Product.updated, async (product) => {
Cache.invalidate(/^popular-products/)
})Batch Processing
const Batch = {
// Batch database operations
operations: [],
add: (operation) => {
Batch.operations.push(operation)
// Auto-flush when batch is full
if (Batch.operations.length >= 100) {
Batch.flush()
}
},
flush: async () => {
const ops = [...Batch.operations]
Batch.operations = []
// Execute in parallel
await Promise.all(ops.map((op) => op()))
},
}
// Example: Batch inserts
for (const item of items) {
Batch.add(async () => {
await db.create($.Product, item)
})
}
await Batch.flush()
// Periodic flushing
every('*/5 * * * *', async () => {
// Every 5 minutes
await Batch.flush()
})Next Steps
- Business Modeling - Learn to model your business
- Examples - See real-world implementations
- Monetization - Add revenue streams
- Integration - Connect external services
Documentation Status: This documentation describes the planned API design for the .do platform. Code examples represent the intended interface and may not reflect the current implementation state.