Operation Types
This page documents the content operation interfaces and related types in the ReX content system.
Core Operation Interface
typescript
/**
* Core interface for content operations
*/
interface ContentOperations {
/**
* Read content from a URI
* @param uri The content URI
* @param options Read options
* @returns Promise resolving to the content
*/
read<T = string>(
uri: string,
options?: ContentReadOptions
): Promise<Content<T>>
/**
* Write content to a URI
* @param uri The content URI
* @param content The content to write
* @param options Write options
*/
write<T = string>(
uri: string,
content: Content<T>,
options?: ContentWriteOptions
): Promise<void>
/**
* Delete content at a URI
* @param uri The content URI
* @param options Delete options
*/
delete(uri: string, options?: ContentDeleteOptions): Promise<void>
/**
* List content matching a pattern
* @param pattern Optional glob pattern to match
* @param options List options
* @returns Promise resolving to an array of matching URIs
*/
list(pattern?: string, options?: ContentListOptions): Promise<string[]>
/**
* Check if content exists at a URI
* @param uri The content URI
* @param options Exists options
* @returns Promise resolving to true if content exists
*/
exists(uri: string, options?: ContentExistsOptions): Promise<boolean>
/**
* Register a change observer
* @param observer The change observer function
* @returns Unsubscribe function
*/
onChange(observer: ContentChangeObserver): () => void
/**
* Clean up resources
*/
dispose(): Promise<void>
}
The ContentOperations
interface defines the core operations available for content manipulation. It’s implemented by both the content store and storage adapters.
Operation Options
Each operation accepts optional parameters to customize its behavior:
Read Options
typescript
/**
* Options for content read operations
*/
interface ContentReadOptions {
/**
* Whether to throw an error if content doesn't exist (default: true)
*/
required?: boolean
/**
* Whether to include any referenced content
*/
includeReferences?: boolean
/**
* How to handle content transformations
*/
transform?: 'auto' | 'none' | 'manual'
/**
* Target content type for transformation
*/
targetContentType?: string
/**
* Custom headers for remote content (HTTP adapter)
*/
headers?: Record<string, string>
/**
* Operation timeout in milliseconds
*/
timeout?: number
/**
* Custom cache control
*/
cache?: 'default' | 'no-cache' | 'reload' | 'force-cache'
/**
* Extension point for adapter-specific options
*/
[key: string]: any
}
Write Options
typescript
/**
* Options for content write operations
*/
interface ContentWriteOptions {
/**
* Whether to create parent directories if they don't exist
*/
createDirectories?: boolean
/**
* Whether to overwrite existing content (default: true)
*/
overwrite?: boolean
/**
* Whether to write any referenced content
*/
includeReferences?: boolean
/**
* Custom headers for remote content (HTTP adapter)
*/
headers?: Record<string, string>
/**
* Operation timeout in milliseconds
*/
timeout?: number
/**
* Whether to validate content before writing
*/
validate?: boolean
/**
* Schema to validate against
*/
schema?: object | string
/**
* Extension point for adapter-specific options
*/
[key: string]: any
}
Delete Options
typescript
/**
* Options for content delete operations
*/
interface ContentDeleteOptions {
/**
* Whether to throw an error if content doesn't exist (default: true)
*/
required?: boolean
/**
* Whether to delete any referenced content
*/
deleteReferences?: boolean
/**
* Types of references to delete
*/
referenceTypes?: ContentReferenceType[]
/**
* Custom headers for remote content (HTTP adapter)
*/
headers?: Record<string, string>
/**
* Operation timeout in milliseconds
*/
timeout?: number
/**
* Extension point for adapter-specific options
*/
[key: string]: any
}
List Options
typescript
/**
* Options for content list operations
*/
interface ContentListOptions {
/**
* Whether to recursively list content in subdirectories
*/
recursive?: boolean
/**
* Maximum depth for recursive listing
*/
maxDepth?: number
/**
* Filter content by content type
*/
contentType?: string | string[]
/**
* Sort options
*/
sort?: {
/**
* Field to sort by
*/
by?: 'uri' | 'createdAt' | 'updatedAt' | 'title' | string
/**
* Sort direction
*/
direction?: 'asc' | 'desc'
}
/**
* Pagination options
*/
pagination?: {
/**
* Page number (1-based)
*/
page?: number
/**
* Items per page
*/
pageSize?: number
}
/**
* Operation timeout in milliseconds
*/
timeout?: number
/**
* Extension point for adapter-specific options
*/
[key: string]: any
}
Exists Options
typescript
/**
* Options for content exists operations
*/
interface ContentExistsOptions {
/**
* Custom headers for remote content (HTTP adapter)
*/
headers?: Record<string, string>
/**
* Operation timeout in milliseconds
*/
timeout?: number
/**
* Extension point for adapter-specific options
*/
[key: string]: any
}
Factory Types
The system includes factory functions for creating content stores and adapters:
typescript
/**
* Options for creating a content store
*/
interface ContentStoreOptions {
/**
* Adapter to use for storage
*/
adapter?: ContentAdapter
/**
* Factory function for creating an adapter
*/
adapterFactory?: ContentAdapterFactory
/**
* Root URI prefix
*/
root?: string
/**
* Whether to automatically create directories
*/
createDirectories?: boolean
/**
* Default read options
*/
defaultReadOptions?: ContentReadOptions
/**
* Default write options
*/
defaultWriteOptions?: ContentWriteOptions
/**
* Default list options
*/
defaultListOptions?: ContentListOptions
/**
* Initial content to populate the store with
*/
initialContent?: ContentCollection
}
/**
* Factory function for creating a content store
*/
type ContentStoreFactory = (options?: ContentStoreOptions) => ContentStore
/**
* Factory function for creating a content adapter
*/
type ContentAdapterFactory = (options?: ContentAdapterOptions) => ContentAdapter
Adapter Interface
Content adapters implement the same core operations interface:
typescript
/**
* Content adapter capabilities
*/
interface ContentAdapterCapabilities {
/**
* Whether the adapter supports reading content
*/
canRead: boolean
/**
* Whether the adapter supports writing content
*/
canWrite: boolean
/**
* Whether the adapter supports deleting content
*/
canDelete: boolean
/**
* Whether the adapter supports listing content
*/
canList: boolean
/**
* Whether the adapter supports watching for changes
*/
canWatch: boolean
/**
* Whether the adapter runs in a Node.js environment
*/
isNodeAdapter: boolean
/**
* Whether the adapter runs in a browser environment
*/
isBrowserAdapter: boolean
}
/**
* Interface for content storage adapters
*/
interface ContentAdapter extends ContentOperations {
/**
* Adapter name
*/
name: string
/**
* Adapter capabilities
*/
capabilities: ContentAdapterCapabilities
}
/**
* Options for creating a content adapter
*/
interface ContentAdapterOptions {
/**
* Adapter name
*/
name?: string
/**
* Root path or URI
*/
root?: string
/**
* Custom URI to path mapping function
*/
uriToPath?: (uri: string) => string
/**
* Custom path to URI mapping function
*/
pathToUri?: (path: string) => string
/**
* Extension point for adapter-specific options
*/
[key: string]: any
}
Registry Types
The content registry provides a way to manage multiple content stores:
typescript
/**
* Interface for a content registry
*/
interface ContentRegistry {
/**
* Get a content store by name
* @param name Store name
*/
getStore(name: string): ContentStore | undefined
/**
* Register a content store
* @param name Store name
* @param store Content store
*/
registerStore(name: string, store: ContentStore): void
/**
* Unregister a content store
* @param name Store name
*/
unregisterStore(name: string): void
/**
* Get all registered store names
*/
getStoreNames(): string[]
/**
* Check if a store exists
* @param name Store name
*/
hasStore(name: string): boolean
/**
* Get the default store
*/
getDefaultStore(): ContentStore
/**
* Set the default store
* @param name Store name
*/
setDefaultStore(name: string): void
/**
* Clean up resources
*/
dispose(): Promise<void>
}
Usage Examples
Basic Operations
typescript
import { createContentStore } from '@lib/content'
// Create a store
const store = createContentStore()
// Read content with options
async function readContent() {
const content = await store.read('posts/welcome.md', {
required: true,
includeReferences: true,
transform: 'auto',
targetContentType: 'text/html',
})
console.log(`Title: ${content.metadata.title}`)
console.log(`HTML: ${content.data}`)
}
// Write content with options
async function writeContent() {
await store.write(
'posts/new-post.md',
{
data: '# New Post\n\nThis is a new post.',
contentType: 'text/markdown',
metadata: {
title: 'New Post',
createdAt: new Date(),
},
},
{
createDirectories: true,
overwrite: true,
validate: true,
}
)
}
// List content with options
async function listContent() {
const uris = await store.list('posts/*.md', {
recursive: true,
contentType: 'text/markdown',
sort: {
by: 'updatedAt',
direction: 'desc',
},
pagination: {
page: 1,
pageSize: 10,
},
})
console.log(`Found ${uris.length} posts`)
}
Working with Adapters
typescript
import {
createAdapter,
createMemoryAdapter,
createFileSystemAdapter,
} from '@lib/content/adapters'
// Create an adapter with custom options
const httpAdapter = createAdapter({
name: 'http',
read: async (uri, options) => {
const response = await fetch(`https://api.example.com/${uri}`, {
headers: options?.headers,
})
if (!response.ok) {
throw new Error(`Failed to fetch ${uri}: ${response.statusText}`)
}
const data = await response.text()
const contentType = response.headers.get('content-type') || 'text/plain'
return {
data,
contentType,
metadata: {
title: uri.split('/').pop() || uri,
updatedAt: new Date(),
},
}
},
capabilities: {
canRead: true,
canWrite: false,
canDelete: false,
canList: false,
canWatch: false,
isNodeAdapter: false,
isBrowserAdapter: true,
},
})
// Create a content store with a specific adapter
const store = createContentStore({
adapter:
process.env.NODE_ENV === 'production'
? createFileSystemAdapter({ root: '/data' })
: createMemoryAdapter(),
})
Registry Usage
typescript
import { createContentRegistry, createContentStore } from '@lib/content'
// Create a registry
const registry = createContentRegistry()
// Register stores
registry.registerStore(
'main',
createContentStore({
adapterFactory: () => createFileSystemAdapter({ root: '/data/main' }),
})
)
registry.registerStore(
'temp',
createContentStore({
adapterFactory: () => createMemoryAdapter(),
})
)
// Set default store
registry.setDefaultStore('main')
// Get a store
const mainStore = registry.getStore('main')
const defaultStore = registry.getDefaultStore()
// Use a store
async function createPost(title: string, content: string) {
const store = registry.getStore('main')
if (!store) throw new Error('Main store not found')
const uri = `posts/${title.toLowerCase().replace(/\s+/g, '-')}.md`
await store.write(uri, {
data: `# ${title}\n\n${content}`,
contentType: 'text/markdown',
metadata: {
title,
createdAt: new Date(),
},
})
return uri
}