### Starting Development Server with Deno Task
Source: https://github.com/goatplatform/goatdb/blob/main/docs/tutorial.md
This command initiates the development server for the application using Deno tasks. It starts an interactive server at `http://localhost:8080` that provides automatic rebuilding and reloading on code changes, supporting `beforeBuild` and `afterBuild` hooks for external build steps.
```bash
deno task debug
```
--------------------------------
### Initializing React Scaffold for Deno SPA with GoatDB
Source: https://github.com/goatplatform/goatdb/blob/main/docs/installation.md
This optional command initializes a React project scaffold for Single Page Applications (SPAs) using GoatDB. It installs React dependencies and sets up client-side and server-side code structures, streamlining SPA development with GoatDB.
```bash
deno run -A jsr:@goatdb/goatdb/init
```
--------------------------------
### Installing GoatDB in Node.js using pnpm
Source: https://github.com/goatplatform/goatdb/blob/main/docs/installation.md
This command installs the GoatDB package in a Node.js environment using pnpm. Node.js support for GoatDB is experimental and not yet production-ready.
```bash
pnpm dlx jsr add @goatdb/goatdb
```
--------------------------------
### Example Test File Structure with Assertions (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/tests/README.md
This TypeScript example demonstrates a complete test file structure, showing how to import `TEST` and `assertEquals`. It defines a simple test within 'ExampleSuite' that asserts the basic arithmetic operation `1 + 1` equals `2`, showcasing integration of assertion utilities.
```ts
import { TEST } from './mod.ts';
import { assertEquals } from './asserts.ts';
export default function setup() {
TEST('ExampleSuite', 'example test', () => {
assertEquals(1 + 1, 2);
});
}
```
--------------------------------
### Installing GoatDB in Node.js using Yarn
Source: https://github.com/goatplatform/goatdb/blob/main/docs/installation.md
This command installs the GoatDB package in a Node.js environment using Yarn. Node.js support for GoatDB is experimental and should not be used in production.
```bash
yarn dlx jsr add @goatdb/goatdb
```
--------------------------------
### Installing GoatDB in Node.js using npm
Source: https://github.com/goatplatform/goatdb/blob/main/docs/installation.md
This command installs the GoatDB package in a Node.js environment using npm. Note that Node.js support for GoatDB is currently experimental and not recommended for production use.
```bash
npx jsr add @goatdb/goatdb
```
--------------------------------
### Adding GoatDB to Deno Project
Source: https://github.com/goatplatform/goatdb/blob/main/docs/installation.md
This command adds the GoatDB package from jsr.io to your Deno project, making it available for use. It's the primary step for integrating GoatDB into a Deno application.
```bash
deno add jsr:@goatdb/goatdb
```
--------------------------------
### Installing GoatDB in Deno
Source: https://github.com/goatplatform/goatdb/blob/main/README.md
This command installs the GoatDB library into a Deno project using the `deno add` command, fetching it from the JSR registry. It's the recommended way to add GoatDB as a dependency for Deno applications, simplifying package management.
```bash
deno add jsr:@goatdb/goatdb
```
--------------------------------
### Initializing GoatDB Instance with useDB() Hook (JavaScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/react.md
This snippet demonstrates how to use the `useDB()` hook to initialize and retrieve the default GoatDB instance. This hook automatically handles storage (using OPFS in browsers) and background server synchronization, ensuring the application is ready to interact with the database without additional setup. It also triggers re-renders on user changes.
```JavaScript
const db = useDB();
```
--------------------------------
### Querying Ordered Items in GoatDB
Source: https://github.com/goatplatform/goatdb/blob/main/docs/order-stamps.md
This example illustrates how to retrieve items from GoatDB in their defined order. By specifying `sortBy: 'orderStamp'` in the query, items are returned lexicographically based on their order stamp. It also shows how to get live results and listen for automatic updates to the query results.
```TypeScript
// Get all items in order
const query = db.query({
source: '/todos',
schema: todoSchema,
sortBy: 'orderStamp',
});
// Get live results that update automatically
const todos = query.results();
// Listen for changes
query.onResultsChanged(() => {
console.log('Todos updated:', query.results());
});
```
--------------------------------
### Using useQuery() for Task List Filtering in JavaScript
Source: https://github.com/goatplatform/goatdb/blob/main/docs/react.md
This example demonstrates how to use the `useQuery` hook to fetch and display a list of tasks. It configures the query with a schema, source path, a sort descriptor to order tasks by text, and a predicate to filter out completed tasks. It also enables `showIntermittentResults` for UI updates during the initial scan.
```javascript
function TaskList() {
const tasksQuery = useQuery({
schema: taskSchema,
source: '/data/tasks',
sortDescriptor: (a, b) => a.get('text').localeCompare(b.get('text')),
predicate: (item) => !item.get('done'),
showIntermittentResults: true,
});
return (
{tasksQuery.results().map((task) => (
{task.get('text')}
))}
);
}
```
--------------------------------
### Accessing Low-Level GoatDB Repository APIs (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/repositories.md
This snippet demonstrates how to access and utilize the low-level repository APIs in GoatDB. It covers methods for getting a repository instance, retrieving values and commits, setting new values, listing keys and paths, and inspecting the commit graph and network for debugging and advanced use cases.
```typescript
// Get a repository instance directly
const repo = db.repository('/users/john');
// Low-level repository methods
// Get the current value and commit for a specific key
// Returns [value, commit] tuple or undefined if key doesn't exist
const [value, commit] = repo.valueForKey('/users/john');
// Set a new value for a key with an optional parent commit
// Returns a Promise that resolves to the new commit or undefined if no change
await repo.setValueForKey('/users/john', newItem, parentCommit);
// Get all keys in the repository
// Returns an iterable of all keys
const keys = repo.keys();
// Get all full paths in the repository
// Returns an iterable of paths (repository path + key)
const paths = repo.paths();
// Get the commit graph for a specific key
// Returns an array of CommitGraph objects showing the commit history
const graph = repo.graphForKey('/users/john/foo');
// Get a Cytoscape-compatible JSON representation of the commit network for a key
// This can be used to visualize the commit history in Cytoscape (https://cytoscape.org/)
const network = repo.debugNetworkForKey('/users/john/foo');
```
--------------------------------
### Reading Data from ManagedItem in GoatDB (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/reading-and-writing-data.md
This example illustrates various methods for reading data from a ManagedItem. It covers retrieving specific field values using `get()`, checking for field existence with `has()`, accessing all available fields via `keys`, and safely reading nested data.
```typescript
// Get a specific item
const userSettings = db.item('/users/john/settings');
// Get a field value
const theme = userSettings.get('theme');
// Check if a field exists
if (userSettings.has('notifications')) {
const notifications = userSettings.get('notifications');
}
// Get all available fields
const allSettings = userSettings.keys;
// Example: Reading nested data
const preferences = userSettings.get('preferences');
const language = preferences?.language;
```
--------------------------------
### Demonstrating Query Instance Reuse in GoatDB (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/query.md
This example highlights GoatDB's query instance reuse mechanism. When two queries are created with identical configurations (source, schema, predicate), GoatDB returns the same underlying query instance. This optimization prevents redundant work, ensures data consistency across consumers, and maintains a single source of truth for the query's state.
```typescript
// First query
const query1 = db.query({
source: '/sys/users',
schema: kSchemaUser,
predicate: ({ item }) => item.get('role') === 'admin',
});
// Second query with same config - returns same instance
const query2 = db.query({
source: '/sys/users',
schema: kSchemaUser,
predicate: ({ item }) => item.get('role') === 'admin',
});
console.log(query1 === query2); // true
```
--------------------------------
### Managing Tasks with useQuery and useItem Hooks in React
Source: https://github.com/goatplatform/goatdb/blob/main/README.md
This React example demonstrates how to use GoatDB's `useQuery` and `useItem` hooks for real-time data management. `TaskList` uses `useQuery` to fetch and display a live list of incomplete tasks, while `TaskEditor` uses `useItem` to manage and update individual task properties, providing automatic synchronization and reactivity.
```jsx
function TaskList() {
const tasks = useQuery({
schema: taskSchema, // see https://goatdb.dev/schema/
source: '/tasks',
predicate: (item) => !item.get('done'), // see https://goatdb.dev/query/
});
return (
{tasks.results().map((task) => (
))}
);
}
function TaskEditor({ path }) {
const task = useItem(path, { keys: ['text', 'done'] }); // see https://goatdb.dev/read-write-data/
if (!task) return Loading...;
return (
task.set('text', e.target.value)}
/>
);
}
```
--------------------------------
### Safe Repeated Use of Orderstamp.end() and Orderstamp.start() in GoatDB (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/order-stamps.md
This example shows that repeatedly calling `Orderstamp.end()` or `Orderstamp.start()` to append or prepend items is always safe and does not lead to stamp growth or collisions. It demonstrates adding items to the end and beginning of a list respectively.
```typescript
// Example: Repeatedly calling end() or start() is always safe
// (no risk of stamp growth or collision)
for (const title of ['A', 'B', 'C']) {
db.create('/todos', todoSchema, {
orderStamp: Orderstamp.end(), // Always safe to call repeatedly
title,
});
}
```
```typescript
for (const title of ['X', 'Y', 'Z']) {
db.create('/todos', todoSchema, {
orderStamp: Orderstamp.start(), // Always safe to call repeatedly
title,
});
}
```
--------------------------------
### Complex Chained Queries for User Activity in GoatDB (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/query.md
This example illustrates a more complex chained query sequence to optimize data processing. It first filters for active users, then finds their recent activities, and finally sorts these activities by recency, demonstrating how each step processes a smaller, more relevant subset of data for efficiency.
```typescript
// First, get all active users (small subset of total users)
const activeUsers = db.query({
source: '/sys/users',
predicate: ({ item }) => item.get('active'),
});
// Then, get their recent activities (only for active users)
const recentActivities = db.query({
source: activeUsers,
predicate: ({ item }) => {
const activities = item.get('activities');
return activities.some((activity) => isRecent(activity.date));
},
});
// Finally, sort by most recent activity
const sortedActivities = db.query({
source: recentActivities,
sortBy: ({ left, right }) => {
const leftRecent = getMostRecentActivity(left);
const rightRecent = getMostRecentActivity(right);
return rightRecent.date - leftRecent.date;
},
});
```
--------------------------------
### Using useItem() for Task Editing in JavaScript
Source: https://github.com/goatplatform/goatdb/blob/main/docs/react.md
This example demonstrates the `useItem` hook to monitor and edit a specific task item. It tracks only the 'text' field for optimized re-renders and provides an input field to modify the task's text, with changes automatically synchronized by GoatDB.
```javascript
function TaskEditor({ path }) {
const task = useItem(path, { keys: ['text'] });
if (!task) {
return
Loading task...
;
}
return (
task.set('text', e.target.value)}
/>
);
}
```
--------------------------------
### Inserting Ordered Items in GoatDB
Source: https://github.com/goatplatform/goatdb/blob/main/docs/order-stamps.md
This snippet demonstrates how to insert new items into a GoatDB collection while maintaining a specific order using order stamps. It shows examples of inserting an item at the beginning, at the end, and between two existing items by generating the appropriate `orderStamp` value using `Orderstamp.start()`, `Orderstamp.end()`, and `Orderstamp.between()` respectively.
```TypeScript
// Insert at the beginning
db.create('/todos', todoSchema, {
orderStamp: Orderstamp.start(),
title: 'First item',
});
// Insert at the end
db.create('/todos', todoSchema, {
orderStamp: Orderstamp.end(),
title: 'Last item',
});
// Insert between two items
const firstItem = db.item('/todos/item1');
const lastItem = db.item('/todos/item2');
db.create('/todos', todoSchema, {
orderStamp: Orderstamp.between(
firstItem.get('orderStamp'),
lastItem.get('orderStamp'),
),
title: 'Middle item',
});
```
--------------------------------
### Peer P1 Changes with Continuous Identifiers (Logoot Principle)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/conflict-resolution.md
This example shows Peer P1's change from 'ABC' to 'BCY' using the continuous identifier approach. Deletions and insertions are applied to specific, stable indexes, demonstrating how Logoot resolves the shifting index problem and enables robust concurrent editing without requiring centralized synchronization.
```Text
Value: B C Y
- - - - - - -
Index: 0 1 2 3 4 5 6
Changes: [-A, 1], [+Y, 6]
```
--------------------------------
### Protecting Specific API Path (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/authorization-rules.md
This example demonstrates how to protect a specific, sensitive API endpoint. By registering an authorization rule for the exact path /api/private and returning false, it explicitly denies all access to this endpoint. This allows for fine-grained control over critical parts of the application, ensuring they remain inaccessible unless explicitly allowed by other rules.
```TypeScript
// Specific path protection example
// This rule protects a specific private API endpoint
DataRegistry.default.registerAuthRule(
'/api/private',
() => false,
);
```
--------------------------------
### Defining a Schema with Orderstamp Field in GoatDB
Source: https://github.com/goatplatform/goatdb/blob/main/docs/order-stamps.md
This example illustrates how to define a schema in GoatDB that includes an `orderStamp` field. The `orderStamp` field is of type `string` and is crucial for maintaining the order of items. It defaults to `Orderstamp.end()`, ensuring new items are appended to the list by default.
```TypeScript
import { DataRegistry } from '@goatdb/goatdb';
const todoSchema = {
ns: 'todo',
version: 1,
fields: {
// This field stores an order stamp as a string
orderStamp: {
type: 'string',
default: () => Orderstamp.end(),
},
title: {
type: 'string',
required: true,
},
completed: {
type: 'boolean',
default: () => false,
},
},
} as const;
```
--------------------------------
### Peer P1 Changes with Fixed Indexes (Traditional)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/conflict-resolution.md
This example shows how Peer P1's change from 'ABC' to 'BCY' is represented using traditional fixed indexes. It highlights how removing 'A' at index 0 shifts subsequent characters, affecting how subsequent changes are interpreted and potentially leading to conflicts in concurrent editing scenarios.
```Text
Value: B C Y
- - -
Index: 0 1 2
Changes: [-A, 0], [+Y, 2]
```
--------------------------------
### Filtering Data with Predicate and Context in GoatDB (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/query.md
This example illustrates how to filter data using a predicate function while passing external, dynamic values via the `ctx` parameter. This ensures the predicate remains a pure function, avoiding side effects or dependencies on mutable external state. Here, the current date (`now`) is passed in context to find overdue tasks.
```typescript
// Find overdue tasks using the current date from context
const overdueTasks = db.query({
source: '/data/tasks',
schema: kSchemaTask,
ctx: { now: new Date() }, // Pass current date in context
predicate: ({ item, ctx }) => {
const dueDate = item.get('dueDate');
return dueDate < ctx.now && !item.get('completed');
},
});
```
--------------------------------
### Sorting Query Results with Custom Function in GoatDB (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/query.md
This example illustrates using a custom sort function with the `sortBy` option for more complex sorting logic. The function receives `left` and `right` items and returns a comparison result. This allows for multi-field sorting, such as sorting by last name then first name, while adhering to the pure function requirement.
```typescript
// Custom sort function
const usersByLastFirst = db.query({
source: '/sys/users',
schema: kSchemaUser,
sortBy: ({ left, right }) => {
const lastNameCompare = left.get('lastName').localeCompare(
right.get('lastName'),
);
if (lastNameCompare !== 0) return lastNameCompare;
return left.get('firstName').localeCompare(right.get('firstName'));
},
});
```
--------------------------------
### Building Production Executable with Deno Task
Source: https://github.com/goatplatform/goatdb/blob/main/docs/tutorial.md
This command triggers the build process to create a self-contained executable for production deployment. It compiles the application into a single binary, ready for distribution.
```bash
deno task build
```
--------------------------------
### Configuring Deno Build Target OS and Architecture
Source: https://github.com/goatplatform/goatdb/blob/main/docs/tutorial.md
This TypeScript snippet demonstrates how to configure the target operating system and architecture for the production build process. It uses the `compile` function to specify `os` (e.g., 'linux', 'mac', 'windows') and `arch` (e.g., 'x64', 'arm64'), enabling cross-compilation for different environments.
```typescript
await compile({
// ... other options ...
os: 'linux', // Target OS: 'mac', 'linux', or 'windows'
arch: 'x64' // Target architecture: 'x64' or 'arm64'
});
```
--------------------------------
### Running Tests with Deno Task
Source: https://github.com/goatplatform/goatdb/blob/main/tests/README.md
This snippet provides the command to execute the GoatDB test suite using Deno's task runner. It is the standard method for initiating tests within the project, ensuring all configured tests are run.
```bash
deno task test
```
--------------------------------
### Running GoatDB Benchmarks (Bash)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/benchmarks.md
This command executes the performance benchmarks for GoatDB. Users must first clone the GoatDB repository to their local machine before running this Deno task. The benchmarks provide insights into GoatDB's performance across different modes compared to SQLite.
```bash
deno task bench
```
--------------------------------
### Opening a Repository in GoatDB (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/repositories.md
This snippet demonstrates how to explicitly open a GoatDB repository using the `db.open()` method. Preloading repositories in advance can improve performance by avoiding delays during initial data access, especially in interactive applications. The method returns a Promise that resolves to the Repository instance.
```typescript
// Explicitly open a repository (returns a Promise that resolves to the Repository instance)
const repo = await db.open('/users/john');
```
--------------------------------
### Linking GoatDB for Local Development in Bash
Source: https://github.com/goatplatform/goatdb/blob/main/README.md
This command links a local clone of the GoatDB repository into your current project. It uses Deno to execute the `@goatdb/goatdb/link` utility, allowing you to develop against a local version of the library rather than a published package. Replace `./path/to/goatdb` with the actual path to your local GoatDB repository.
```bash
deno run -A jsr:@goatdb/goatdb/link link ./path/to/goatdb
```
--------------------------------
### Monitoring GoatDB Loading State with useDBReady() Hook (JavaScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/react.md
This snippet illustrates how to use the `useDBReady()` hook to monitor the database's loading state. It returns "loading" during initialization, "ready" when fully loaded and synchronized, or "error" if an issue occurs. This hook is crucial for managing initial loading screens and handling database readiness in a React application.
```JavaScript
function App() {
const dbStatus = useDBReady();
if (dbStatus === 'loading') {
return ;
} else if (dbStatus === 'error') {
return ;
}
return ;
}
```
--------------------------------
### Implementing Deny-All Authorization Rule (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/authorization-rules.md
This snippet illustrates a fundamental security best practice: a 'deny-all' rule. By registering a rule that matches all paths (/.*/) and always returns false, it ensures that no operations are permitted by default. This approach requires explicit 'allow' rules to be registered later, creating a secure-by-default authorization system.
```TypeScript
// Deny-All rule - a security best practice
DataRegistry.default.registerAuthRule(
/.*/,
() => false,
);
```
--------------------------------
### Creating a Basic Query in GoatDB (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/query.md
This snippet demonstrates how to create a basic query in GoatDB using the `db.query()` method. It shows how to specify a data source, schema, and a predicate function to filter items. After defining the query, it illustrates waiting for the initial results to load using `loadingFinished()` and then retrieving the results with `results()`.
```typescript
// Find all users with admin role
const adminUsers = db.query({
source: '/sys/users',
schema: kSchemaUser,
predicate: ({ item }) => item.get('role') === 'admin',
});
// Wait for initial results
await adminUsers.loadingFinished();
// Get the results
const results = adminUsers.results();
```
--------------------------------
### Basic Usage of GoatDB in TypeScript
Source: https://github.com/goatplatform/goatdb/blob/main/README.md
This snippet demonstrates the fundamental steps to initialize GoatDB, create a new document, and update its properties. It imports the `GoatDB` class, instantiates a database connection with a local path and a peer, then creates a document under the `/todos` path and updates its 'done' field. This illustrates the basic API for data manipulation.
```typescript
import { GoatDB } from '@goatdb/goatdb';
const db = new GoatDB({ path: './data', peers: ['http://10.0.0.1'] });
const item = db.create('/todos', { text: 'Hello, GoatDB!', done: false });
item.set('done', true);
```
--------------------------------
### Creating New Tasks with React Header Component (TSX)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/tutorial.md
The `Header` component provides an input field and a button to add new tasks. It uses the `useDB` hook from `@goatdb/goatdb/react` to access the database instance and calls `db.create` to persist new task items in the current user's repository based on the defined `kSchemaTask`.
```tsx
// client/Header.tsx
import React, { useRef } from 'react';
import { useDB } from '@goatdb/goatdb/react';
import { kSchemaTask } from '../common/registry.ts';
export function Header() {
const db = useDB();
const ref = useRef(null);
return (
);
}
```
--------------------------------
### Root Application Component for GoatDB React App
Source: https://github.com/goatplatform/goatdb/blob/main/docs/tutorial.md
This is the main React component that orchestrates the application's state based on the database readiness and user login status. It utilizes `useDB` and `useDBReady` hooks from `@goatdb/goatdb/react` to conditionally render a loading state, an error state, the main `Contents` component if logged in, or the `Login` component if not authenticated.
```tsx
// client/App.tsx
import React from 'react';
import { useDB, useDBReady } from '@goatdb/goatdb/react';
import { Contents } from './Contents.tsx';
import { Login } from './Login.tsx';
export function App() {
const db = useDB();
const ready = useDBReady();
if (ready === 'loading') return
Loading...
;
if (ready === 'error') return
Error loading database
;
return db.loggedIn ? : ;
}
```
--------------------------------
### Understanding and Listening to GoatDB Item Mutations (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/reading-and-writing-data.md
This snippet illustrates how GoatDB's internal mutation system tracks changes. It shows how a `set()` operation generates a mutation and how applications can listen to these mutations via the `on('change')` event to understand which fields were modified and their old values.
```typescript
const todoItem = db.item('/todos/work/1');
// When you make a change
todoItem.set('title', 'New Task');
// Behind the scenes, a mutation is created:
const mutation = ['title', true, 'Old Task'];
// You can listen to these changes
todoItem.on('change', (mutations) => {
mutations.forEach(([field, isLocal, oldValue]) => {
console.log(`${field} changed from ${oldValue}`);
});
});
```
--------------------------------
### Creating Items with GoatDB API (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/reading-and-writing-data.md
This snippet demonstrates how to create new items in GoatDB using the `db.create()` method. It shows creating an item with initial data and creating an empty item, both identified by a unique path.
```typescript
// Create with initial data
const newTodo = db.create('/todos/work', {
title: 'Finish documentation',
completed: false,
dueDate: '2024-03-15',
});
// Create empty item
const emptyTodo = db.create('/todos/personal');
```
--------------------------------
### Enabling Trusted Mode for GoatDB Instance (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/sessions.md
This snippet demonstrates how to initialize a GoatDB database instance in 'trusted mode'. By setting the `trusted` flag to `true` in the configuration object, cryptographic signing and authorization checks are bypassed, which can significantly improve performance in controlled or secure environments where security is handled externally. This mode should be used with caution due to disabled security features.
```TypeScript
const db = new GoatDB({
path: '/path/to/db',
trusted: true,
});
```
--------------------------------
### Using Temporary Directories in Tests (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/tests/README.md
This TypeScript snippet demonstrates how to utilize `ctx.tempDir()` to create and interact with a temporary file unique to a test suite. It shows writing content to a file within the temporary directory and then asserting its existence, with the assurance that the directory will be automatically cleaned up after the suite completes.
```ts
import { TEST } from './mod.ts';
import { assertTrue } from './asserts.ts';
import { exists, writeTextFile } from 'jsr:@std/fs';
export default function setup() {
TEST('TempDirSuite', 'can write to temp dir', async (ctx) => {
const tempPath = await ctx.tempDir('myfile.txt');
await writeTextFile(tempPath, 'hello!');
assertTrue(await exists(tempPath));
});
}
```
--------------------------------
### Implementing User Login with Magic Link Email in React
Source: https://github.com/goatplatform/goatdb/blob/main/docs/tutorial.md
This React component provides a user interface for logging in via a magic link sent to their email. It uses the `useDB` hook from `@goatdb/goatdb/react` to interact with the database, handling email input, sending the magic link, and displaying success or error messages. The `loginWithMagicLinkEmail` method is central to the authentication flow.
```tsx
// client/Login.tsx
import React, { useRef, useState } from 'react';
import { useDB } from '@goatdb/goatdb/react';
export function Login() {
const db = useDB();
const ref = useRef(null);
const [emailSent, setEmailSent] = useState(false);
const [error, setError] = useState(false);
return (
{emailSent &&
Check your email for the login link
}
{error &&
Error sending login email. Please try again.
}
);
}
```
--------------------------------
### Defining a Basic Test in TypeScript
Source: https://github.com/goatplatform/goatdb/blob/main/tests/README.md
This TypeScript snippet illustrates how to define a test using the `TEST` function. It imports `TEST` from the local module and registers an asynchronous test named 'should do something' within the 'MyFeature' suite, passing a context object `ctx` to the test function.
```ts
import { TEST } from './mod.ts';
export default function setupMyFeatureTests() {
TEST('MyFeature', 'should do something', async (ctx) => {
// Test implementation
});
}
```
--------------------------------
### Reading Data from GoatDB Repositories (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/repositories.md
This snippet demonstrates various methods for reading data from GoatDB repositories. It shows how to retrieve a single item by its full path, query multiple items using a schema filter within a specified repository path, and list all keys present in a given repository. These operations are essential for accessing and navigating data stored in GoatDB.
```TypeScript
// Get a specific item by its full path
// Returns the current value of the item or undefined if it doesn't exist
const user = db.item('/users/john/foo');
// Query items using a schema filter
// This example gets all notes in john's repository that match the note schema
const allNotes = db.query({
source: '/users/john', // Repository path to search in
schema: kSchemaNote // Schema to filter by
});
// Get all keys in a repository
// This is useful for listing all items or checking what exists
const allKeys = db.keys('/users/john');
```
--------------------------------
### Bulk Creating Todos with Efficient Order Stamps in GoatDB (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/order-stamps.md
This function demonstrates how to efficiently add multiple todo items to GoatDB using `Orderstamp.between()` for bulk allocation. It takes an array of titles, a `prev` stamp, and a `next` stamp, ensuring that new items are inserted between `prev` and `next` without causing stamp growth.
```typescript
// Example: Bulk create todos with efficient order stamps (only needed for between())
function addMultipleTodos(titles: string[], prev: string, next: string) {
for (let i = 0; i < titles.length; i++) {
db.create('/todos', todoSchema, {
orderStamp: Orderstamp.between(prev, next, titles.length, i),
title: titles[i],
});
}
}
```
--------------------------------
### Managing Task List and Filtering with React Contents Component (TSX)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/tutorial.md
The `Contents` component orchestrates the display of the task list, including the `Header` for adding tasks and `TaskItem` components for individual tasks. It uses the `useQuery` hook to fetch tasks from the user's repository, supporting sorting by `dateCreated` and dynamic filtering based on a 'show completed tasks' checkbox, demonstrating real-time query capabilities.
```tsx
// client/Contents.tsx
import React, { useState } from 'react';
import { useDB, useQuery } from '@goatdb/goatdb/react';
import { kSchemaTask } from '../common/registry.ts';
import { Header } from './Header.tsx';
import { TaskItem } from './TaskItem.tsx';
export function Contents() {
const db = useDB();
const [showChecked, setShowChecked] = useState(true);
// Query tasks from the user's repository
const query = useQuery({
schema: kSchemaTask,
source: `/data/${db.currentUser!.key}`,
sortBy: 'dateCreated',
sortDescending: true,
predicate: ({ item, ctx }) => !item.get('done') || ctx.showChecked,
showIntermittentResults: true,
ctx: { showChecked },
});
return (
{query.results().map(({ path }) => )}
);
}
```
--------------------------------
### Defining Task Schema and Authorization Rules with GoatDB (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/tutorial.md
This snippet defines the `kSchemaTask` for a todo item, specifying fields like `text`, `done`, and `dateCreated` with their types and default values. It also registers this schema and an authorization rule that restricts users to accessing only their own data repositories, ensuring data isolation and security.
```typescript
import { DataRegistry, itemPathGetPart } from '@goatdb/goatdb';
// Define the task schema
export const kSchemaTask = {
ns: 'task',
version: 1,
fields: {
text: {
type: 'string',
required: true,
},
done: {
type: 'boolean',
default: () => false,
},
dateCreated: {
type: 'date',
default: () => new Date(),
},
},
} as const;
export type SchemaTypeTask = typeof kSchemaTask;
// Register schemas and authorization rules
export function registerSchemas(
registry: DataRegistry = DataRegistry.default,
): void {
// Register the task schema
registry.registerSchema(kSchemaTask);
// Allow each user to access only their own repository
registry.registerAuthRule(
/\/data\/\w+/,
({ repoPath, session }) =>
itemPathGetPart(repoPath, 'repo') === session.owner,
);
}
```
--------------------------------
### Displaying and Managing Individual Tasks with React TaskItem Component (TSX)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/tutorial.md
The `TaskItem` component renders a single task, allowing users to mark it as done, edit its text, or delete it. It leverages the `useItem` hook to subscribe to real-time changes for a specific task path, ensuring the UI reflects the latest state and enabling direct updates to the task's properties.
```tsx
// client/TaskItem.tsx
import React from 'react';
import { useItem } from '@goatdb/goatdb/react';
import { SchemaTypeTask } from '../common/registry.ts';
export type TaskItemProps = {
path: string;
};
export function TaskItem({ path }: TaskItemProps) {
// Subscribe to changes for this specific task
const task = useItem(path)!;
return (
);
}
```
--------------------------------
### Initializing and Updating ManagedItem in GoatDB (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/reading-and-writing-data.md
This snippet demonstrates how to obtain a ManagedItem instance, which creates one if it doesn't already exist. It shows how to update a single field using `set()`, with changes immediately reflected in memory and automatically synchronized with other parts of the application and remote peers.
```typescript
// Get a managed item (creates one if it doesn't exist)
const userProfile = db.item('/users/john/profile');
// Changes are immediately reflected in memory
userProfile.set('name', 'John Smith');
// The changes will be automatically synchronized
// with other parts of your application
```
--------------------------------
### Styling the Page Container (CSS)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/404.html
This CSS rule defines the styling for the main container of the 404 page. It centers the content horizontally, sets a maximum width to prevent overly wide layouts, and adds top/bottom margins for spacing.
```CSS
.container {
margin: 10px auto;
max-width: 600px;
text-align: center;
}
```
--------------------------------
### Enabling Trusted Mode in GoatDB Initialization
Source: https://github.com/goatplatform/goatdb/blob/main/docs/authorization-rules.md
This snippet demonstrates how to enable 'trusted mode' when initializing a GoatDB instance. When enabled, all registered authorization rules are ignored, granting full access to all repositories and items, and effectively disabling GoatDB's built-in security model.
```typescript
const db = new GoatDB({
path: '/path/to/db',
trusted: true,
});
```
--------------------------------
### Representing Initial Value with Fixed Indexes
Source: https://github.com/goatplatform/goatdb/blob/main/docs/conflict-resolution.md
This snippet illustrates the initial state of a string 'ABC' and its corresponding fixed indexes, demonstrating a traditional approach to character indexing before applying changes. This method can lead to issues when characters are removed or inserted, as subsequent indexes shift.
```Text
Value: A B C
- - -
Index: 0 1 2
```
--------------------------------
### Basic Orderstamp API Usage in GoatDB
Source: https://github.com/goatplatform/goatdb/blob/main/docs/order-stamps.md
This snippet demonstrates the fundamental API calls for generating order stamps using the `@goatdb/goatdb` library. It shows how to create stamps for the beginning and end of a list, generate a stamp between two existing stamps, and convert a numeric value into an order stamp. These stamps are string values used for lexicographical ordering.
```TypeScript
import { Orderstamp } from '@goatdb/goatdb';
// Create a stamp at the start of the list
const firstStamp = Orderstamp.start();
// Create a stamp at the end of the list
const lastStamp = Orderstamp.end();
// Create a stamp between two existing stamps
const middleStamp = Orderstamp.between(prevStamp, nextStamp);
// Create a stamp from a numeric value (optional)
const numericStamp = Orderstamp.from(42);
```
--------------------------------
### Styling the Main Heading (CSS)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/404.html
This CSS rule styles the primary heading (h1) on the 404 page. It sets specific margins, a large font size, a compact line height, and negative letter spacing to create a prominent and visually distinct error message.
```CSS
h1 {
margin: 30px 0;
font-size: 4em;
line-height: 1;
letter-spacing: -1px;
}
```
--------------------------------
### Using GoatDB Queries as Efficient Indexes (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/query.md
This snippet demonstrates how a sorted GoatDB query can function as an efficient ad-hoc index. By sorting a query by a specific field (e.g., 'email'), subsequent lookups using the `find()` method become highly optimized (O(log n) complexity) after the initial loading is complete, enabling fast data retrieval.
```typescript
// Create an index over user emails
const usersByEmail = db.query({
source: '/sys/users',
schema: kSchemaUser,
sortBy: 'email',
});
// O(log n) lookup by email after index is built
await usersByEmail.loadingFinished();
const user = usersByEmail.find('email', 'user@example.com');
```
--------------------------------
### Chaining Queries for Filtering Data in GoatDB (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/query.md
This snippet demonstrates basic query chaining in GoatDB. It first queries for all "important" todos and then uses the results of that query as the source for a second query to find "recent" todos among the important ones, showcasing data composition.
```typescript
// Find important todos
const importantTodos = db.query({
source: '/data/todos',
predicate: ({ item }) => item.get('important'),
});
// Then find recent important todos
const recentImportant = db.query({
source: importantTodos,
predicate: ({ item }) => isRecent(item.get('date')),
});
```
--------------------------------
### Subscribing to Real-Time Query Updates in GoatDB (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/query.md
This snippet demonstrates how GoatDB queries automatically update their results in real-time. It shows how to create a query for active users and then attach an onResultsChanged event listener to log changes, making it suitable for building reactive UIs or backend services.
```typescript
// Create a query
const activeUsers = db.query({
source: '/sys/users',
predicate: ({ item }) => item.get('active'),
});
// Listen for changes
activeUsers.onResultsChanged(() => {
console.log('Active users changed:', activeUsers.results());
});
```
--------------------------------
### Upgrading a Schema with Data Transformation in JavaScript
Source: https://github.com/goatplatform/goatdb/blob/main/docs/schema.md
This snippet demonstrates how to upgrade an existing schema to version 2, adding a 'timestamp' field and renaming 'value' to 'contents'. It includes an 'upgrade' function to transform data from the previous schema version, ensuring backward compatibility. The 'registerSchemas' function registers this new schema version with the provided or default DataRegistry.
```javascript
export const kSchemeMessageV2 = {
ns: 'message',
version: 2,
fields: {
sender: {
type: 'string',
required: true,
},
contents: {
type: 'string',
required: true,
},
timestamp: {
type: 'date',
default: () => new Date(),
},
upgrade: (data) => {
data.set('contents', data.get('value'));
return data;
},
},
} as const;
export function registerSchemas(
registry: DataRegistry = DataRegistry.default,
): void {
// Previous schema versions go in here
registry.default.register(kSchemeMessageV2);
}
```
--------------------------------
### Peer P2 Changes with Fixed Indexes (Traditional)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/conflict-resolution.md
This snippet demonstrates Peer P2's change from 'ABC' to 'ABX' using traditional fixed indexes. It shows how removing 'C' and inserting 'X' at index 2 is represented, further illustrating the challenges of fixed indexing when multiple peers make concurrent modifications.
```Text
Value: A B X
- - -
Index: 0 1 2
Changes: [-C, 2], [+X, 2]
```
--------------------------------
### Defining and Registering a New Schema in JavaScript
Source: https://github.com/goatplatform/goatdb/blob/main/docs/schema.md
This code defines a new schema named kSchemeMessage for 'message' items with version 1, specifying 'sender' and 'value' as required string fields. It then registers this schema with the default DataRegistry to make it available for use in GoatDB, and defines a TypeScript type for convenience.
```javascript
export const kSchemeMessage = {
ns: 'message',
version: 1,
fields: {
sender: {
type: 'string',
required: true,
},
value: {
type: 'string',
required: true,
},
},
} as const;
DataRegistry.default.register(kSchemeMessage);
type SchemeMessageType = typeof kSchemeMessage;
```
--------------------------------
### Implementing Owner-Only Access with GoatDB
Source: https://github.com/goatplatform/goatdb/blob/main/docs/authorization-rules.md
This pattern ensures that sessions can only access data that they own. It achieves this by comparing the session's owner ID with the repository ID derived from the `repoPath`, granting access only if they match.
```typescript
// Owner-only access pattern
// This ensures sessions can only access their own data
DataRegistry.default.registerAuthRule(
'/user/*',
({ session, repoPath }) => {
// Only the session owner can access
const repoId = itemPathGetPart(repoPath, 'repo');
return session.owner === repoId;
},
);
```
--------------------------------
### Implementing Public Read, Private Write with GoatDB
Source: https://github.com/goatplatform/goatdb/blob/main/docs/authorization-rules.md
This pattern allows public content to be read by anyone but restricts modification to only authenticated sessions. It's commonly used for collaborative applications where content is publicly visible but privately editable.
```typescript
// Public read, private write pattern
// This is a common pattern for public content that only authenticated sessions can modify
DataRegistry.default.registerAuthRule(
'/public/*',
({ session, op }) => {
// Allow anyone to read
if (op === 'read') {
return true;
}
// Only authenticated sessions can write
return session.owner !== undefined;
},
);
```
--------------------------------
### Accessing the Default DataRegistry in JavaScript
Source: https://github.com/goatplatform/goatdb/blob/main/docs/schema.md
This snippet demonstrates how to access the default instance of the DataRegistry in GoatDB. The DataRegistry is essential for registering and managing schemas, allowing them to be used for creating and manipulating items within the database. This default instance is sufficient for most applications.
```javascript
const manager = DataRegistry.default;
```
--------------------------------
### Comparing Inefficient and Efficient Bulk Insertions with Orderstamp.between() in TypeScript
Source: https://github.com/goatplatform/goatdb/blob/main/docs/order-stamps.md
This snippet illustrates the difference between inefficient sequential `Orderstamp.between()` calls, which can cause stamp growth, and efficient bulk allocation using the `N` and `i` parameters. The efficient method prevents unnecessary stamp length increases when inserting multiple items between the same two points.
```typescript
// Inefficient (causes stamp growth):
let s = prev;
for (let i = 0; i < N; i++) {
s = Orderstamp.between(s, next);
}
```
```typescript
// Efficient
for (let i = 0; i < N; i++) {
const stamp = Orderstamp.between(prev, next, N, i);
}
```
--------------------------------
### Implementing Role-Based Access Control with GoatDB
Source: https://github.com/goatplatform/goatdb/blob/main/docs/authorization-rules.md
This pattern restricts write access to sessions possessing specific roles, such as 'editor'. It allows anyone to read but denies anonymous writes and requires the session owner to have the designated role for write operations.
```typescript
// Role-based access control
// This pattern restricts write access to sessions with specific roles
DataRegistry.default.registerAuthRule(
'/editor/*',
({ db, session, op }) => {
// Allow anyone to read
if (op === 'read') {
return true;
}
// Deny anonymous writes
if (!session.owner) {
return false;
}
// Only editor sessions can write
const userItem = db.item('/sys/users', session.owner);
return userItem.get('roles').includes('editor');
},
);
```
--------------------------------
### Forcing Data Persistence with GoatDB Flush Operations (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/reading-and-writing-data.md
This snippet shows how to explicitly force data persistence in GoatDB using `db.flush()` for a specific repository or `db.flushAll()` for all repositories. This operation ensures that pending writes are completed, though it should be used sparingly due to potential performance impacts.
```typescript
// Wait for writes to complete for a specific repository
await db.flush('/todos/personal');
// Or flush all repositories
await db.flushAll();
```
--------------------------------
### Writing and Updating Data in ManagedItem in GoatDB (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/reading-and-writing-data.md
This snippet demonstrates how to write and update data using a ManagedItem. It shows how to update a single field, update multiple fields simultaneously with `setMulti()`, delete a specific field using `delete()`, and update nested data structures. All write operations are processed asynchronously for performance.
```typescript
const userProfile = db.item('/users/john/profile');
// Single field update
userProfile.set('name', 'John Smith');
// Multiple fields at once
userProfile.setMulti({
name: 'John Smith',
age: 31,
email: 'john.smith@example.com'
});
// Delete a field
userProfile.delete('email');
// Example: Updating nested data
userProfile.set('theme', 'dark');
```
--------------------------------
### Allowing Public Read, Denying Write Access (TypeScript)
Source: https://github.com/goatplatform/goatdb/blob/main/docs/authorization-rules.md
This rule illustrates how to combine access types for a broad set of repositories. It allows read operations (op === 'read') for any path under /public/* while implicitly denying write operations. This is useful for creating publicly viewable data that can only be modified by specific, more privileged rules.
```TypeScript
// Public read access with write restrictions
DataRegistry.default.registerAuthRule(
'/public/*',
({ op }) => op === 'read',
);
```