$ (ctx)
Build semantic triple patterns with $.Subject.predicate.Object
The $ is a JavaScript Proxy that enables building semantic triple patterns following the $.Subject.predicate.Object convention. It's the foundation of SDK.do's semantic architecture.
Overview
The $ proxy allows you to construct semantic paths through simple property access:
import { $ } from 'sdk.do'
$.Person.worksFor.Organization
$.Order.contains.Product
$.User.created.Account
$.Business.owns.BrandHow It Works
The $ is implemented as a JavaScript Proxy that:
- Intercepts property access
- Builds a semantic path string
- Converts to string when needed
- Provides type hints through TypeScript
const path = $.Business.owns.Brand
console.log(String(path)) // "$.Business.owns.Brand"
console.log(path.path) // "$.Business.owns.Brand"Semantic Triple Pattern
Semantic triples follow the Subject-Predicate-Object pattern from RDF:
- Subject: The entity (e.g.,
Person,Business,Order) - Predicate: The relationship or property (e.g.,
worksFor,owns,contains) - Object: The target entity or value (e.g.,
Organization,Brand,Product)
Examples
// Relationships
$.Person.worksFor.Organization
$.Employee.reportsTo.Manager
$.Product.manufacturedBy.Company
// Properties
$.User.hasEmail.EmailAddress
$.Order.hasStatus.OrderStatus
$.Document.createdBy.User
// Events
$.Order.created.Event
$.User.updated.Event
$.Payment.processed.Event
// Specific entities
$.John.worksFor.Acme
$.Order123.contains.Product456
$.Alice.manages.TeamUsage in SDK Functions
With Events
Use $ to define semantic event paths:
import { $, on, send } from 'sdk.do'
// Subscribe to events
on.Order.created(async (order) => {
console.log('Order created:', order.id)
})
// Send events
send.User.updated({
userId: 'user-123',
changes: { name: 'Alice' },
})With Database Relationships
Query relationships using semantic paths:
import { $, db } from 'sdk.do'
// Query related entities
const brands = await db.related({ collection: 'businesses', id: 'acme-inc' }, $.owns, 'brands')
const employees = await db.related({ collection: 'companies', id: 'company-123' }, $.employs, 'users')Pattern Matching
Use wildcards for pattern matching in events:
// Match any Order event
on($.Order['*'], async (data) => {
// Matches $.Order.created, $.Order.updated, $.Order.deleted
console.log('Any order event:', data)
})
// Match specific patterns
on($.User['*'].completed, async (data) => {
// Matches $.User.registration.completed, $.User.purchase.completed, etc.
})String Conversion
The $ proxy automatically converts to string:
const path = $.Business.owns.Brand
// Explicit conversion
String(path) // "$.Business.owns.Brand"
path.toString() // "$.Business.owns.Brand"
path.valueOf() // "$.Business.owns.Brand"
// Direct property access
path.path // "$.Business.owns.Brand"
// Implicit conversion in template literals
console.log(`Path: ${path}`) // "Path: $.Business.owns.Brand"TypeScript Support
Basic Usage
import { $ } from 'sdk.do'
import type { PathProxy } from 'sdk.do'
const path: PathProxy = $.Person.worksFor.OrganizationTyped Path Proxy
For full autocomplete support:
import { $ } from 'sdk.do'
import type { TypedPathProxy } from 'graphdl'
// Cast for autocomplete
const typed = $ as unknown as TypedPathProxy
// Now get autocomplete for Schema.org entities
typed.Person. // Autocomplete shows: worksFor, knows, owns, etc.
typed.Organization. // Autocomplete shows: employs, produces, etc.Type Safety in Functions
import { $, on } from 'sdk.do'
import type { PathProxy } from 'sdk.do'
function subscribeToEvent(event: PathProxy, handler: (data: any) => void) {
return on(event, handler)
}
// Type-safe usage
subscribeToEvent($.Order.created, (order) => {
console.log(order.id)
})Best Practices
Use Semantic Names
Choose descriptive, semantic predicates:
// Good - semantic and clear
$.Person.worksFor.Organization
$.Order.contains.Product
$.User.hasRole.Admin
// Avoid - not semantic
$.Person.has.Organization
$.Order.related.Product
$.User.is.AdminFollow Schema.org Conventions
Use established Schema.org predicates when possible:
// Schema.org predicates
$.Person.worksFor.Organization // from Schema.org
$.Product.manufacturer.Organization
$.Event.location.Place
$.Book.author.PersonKeep Paths Readable
Make paths human-readable:
// Good - readable
$.Employee.reportsTo.Manager
$.Customer.placedOrder.Order
$.Article.writtenBy.Author
// Avoid - not readable
$.Emp.rpts.Mgr
$.Cust.ord.Ord
$.Art.auth.AuthUse Consistent Casing
Follow PascalCase for entities, camelCase for predicates:
// Correct casing
$.Person.worksFor.Organization
$.Product.hasCategory.Category
$.Order.createdBy.User
// Inconsistent (avoid)
$.person.WorksFor.organization
$.PRODUCT.hasCategory.CATEGORYCommon Patterns
Entity Relationships
// Ownership
$.Business.owns.Brand
$.Company.owns.Subsidiary
$.Person.owns.Asset
// Employment
$.Person.worksFor.Organization
$.Employee.reportsTo.Manager
$.Contractor.providesServicesTo.Client
// Hierarchy
$.Child.childOf.Parent
$.Department.partOf.Organization
$.Component.assembledIn.ProductEvents
// CRUD events
$.User.created
$.Order.updated
$.Product.deleted
// State transitions
$.Order.shipped
$.Payment.processed
$.Task.completed
// Notifications
$.Email.sent
$.SMS.delivered
$.Notification.readProperties
// Identity
$.Person.hasEmail.EmailAddress
$.User.hasUsername.String
$.Entity.hasId.Identifier
// Status
$.Order.hasStatus.OrderStatus
$.User.hasRole.Role
$.Task.hasPriority.Priority
// Temporal
$.Event.startTime.DateTime
$.Subscription.expiresAt.DateTime
$.Document.modifiedAt.DateTimeImplementation Details
The $ proxy is implemented in the graphdl package:
// Simplified implementation
const handler: ProxyHandler<{ path: string }> = {
get(target, prop) {
if (prop === 'toString' || prop === 'valueOf') {
return () => target.path
}
if (prop === 'path') {
return target.path
}
const newPath = target.path ? `${target.path}.${String(prop)}` : String(prop)
return new Proxy({ path: newPath }, handler)
},
}
export const $ = new Proxy({ path: '$' }, handler)Related Documentation
- SDK.do Overview - Main SDK documentation
- Event Functions - Using
$with events - Database Functions - Using
$with relationships