Skip to main content

JavaScript SDK

The official JavaScript/TypeScript SDK for the OfSelf API.

Installation

npm install @ofself/sdk
# or
yarn add @ofself/sdk
# or
pnpm add @ofself/sdk

Requirements:

  • Node.js 16+ or modern browser

Quick Start

import { OfSelfClient } from '@ofself/sdk';

const client = new OfSelfClient({
apiKey: 'your-api-key'
});

// Create a node
const node = await client.nodes.create({
userId: 'user-123',
title: 'My First Note',
value: 'Hello, OfSelf!',
nodeType: 'note'
});

console.log(`Created: ${node.id}`);

Configuration

import { OfSelfClient } from '@ofself/sdk';

const client = new OfSelfClient({
apiKey: 'your-api-key',
baseUrl: 'https://api.ofself.ai/api/v1', // Default
timeout: 30000 // Request timeout in ms
});

Environment Variables

# .env
OFSELF_API_KEY=ofs_key_xxxxxxxxxxxxx
const client = new OfSelfClient({
apiKey: process.env.OFSELF_API_KEY!
});

Resources

Nodes

// Create
const node = await client.nodes.create({
userId: 'user-123',
title: 'Meeting Notes',
value: 'Content...',
nodeType: 'note',
tagIds: ['tag_work']
});

// List
const { items, total } = await client.nodes.list({
userId: 'user-123',
nodeType: 'note',
page: 1,
perPage: 20
});

// Get
const node = await client.nodes.get('user-123', 'node_abc');

// Update
const updated = await client.nodes.update({
userId: 'user-123',
nodeId: 'node_abc',
title: 'Updated Title'
});

// Delete
await client.nodes.delete('user-123', 'node_abc');

// Vector search
const results = await client.nodes.vectorSearch('user-123', 'project deadlines', {
limit: 10
});

Tags

// Create
const tag = await client.tags.create({
userId: 'user-123',
name: 'Work',
color: '#3B82F6'
});

// List
const { items } = await client.tags.list('user-123');

// Get nodes with tag
const nodes = await client.tags.getNodes('user-123', 'tag_work');

// Add tag to node
await client.nodes.addTag('user-123', 'node_abc', 'tag_work');

Files

// Upload (browser)
const fileInput = document.querySelector('input[type="file"]');
const file = await client.files.upload({
userId: 'user-123',
file: fileInput.files[0],
tagIds: ['tag_documents']
});

// Upload (Node.js)
import { readFileSync } from 'fs';
const buffer = readFileSync('document.pdf');
const file = await client.files.upload({
userId: 'user-123',
file: new Blob([buffer]),
filename: 'document.pdf'
});

// List
const { items } = await client.files.list({ userId: 'user-123' });

// Download
const blob = await client.files.download('user-123', 'file_abc');

Proposals

// Create proposal
const proposal = await client.proposals.create({
userId: 'user-123',
proposalType: 'create_node',
canonicalData: {
entities: [{
title: 'Imported Note',
value: 'Content',
nodeType: 'note'
}]
}
});

// List pending
const { items } = await client.proposals.list('user-123', {
status: 'pending'
});

// Approve (as user)
await client.proposals.approve('user-123', 'prop_abc');

Graph

// Get snapshot for visualization
const graph = await client.graph.snapshot('user-123');

console.log(`Nodes: ${graph.nodes.length}`);
console.log(`Edges: ${graph.edges.length}`);

Error Handling

import {
OfSelfClient,
OfSelfError,
AuthenticationError,
PermissionDeniedError,
NotFoundError,
ValidationError,
RateLimitError,
} from '@ofself/sdk';

const client = new OfSelfClient({ apiKey: 'your-key' });

try {
const node = await client.nodes.get('user-123', 'invalid');
} catch (error) {
if (error instanceof AuthenticationError) {
console.log('Invalid API key');
} else if (error instanceof PermissionDeniedError) {
console.log("User hasn't authorized your app");
} else if (error instanceof NotFoundError) {
console.log('Node not found');
} else if (error instanceof ValidationError) {
console.log('Validation failed:', error.errors);
} else if (error instanceof RateLimitError) {
console.log(`Rate limited. Retry after ${error.retryAfter}s`);
} else if (error instanceof OfSelfError) {
console.log(`API error: ${error.message}`);
}
}

TypeScript Support

Full TypeScript support with type definitions:

import { OfSelfClient, Node, Tag, Proposal } from '@ofself/sdk';

const client = new OfSelfClient({ apiKey: 'key' });

// Types are inferred
const node = await client.nodes.create({
userId: 'user-123',
title: 'Note'
});

node.id // string
node.title // string
node.nodeType // string

React Example

import { useState, useEffect } from 'react';
import { OfSelfClient, Node } from '@ofself/sdk';

const client = new OfSelfClient({
apiKey: process.env.REACT_APP_OFSELF_KEY!
});

function NodeList({ userId }: { userId: string }) {
const [nodes, setNodes] = useState<Node[]>([]);
const [loading, setLoading] = useState(true);

useEffect(() => {
client.nodes.list({ userId })
.then(res => setNodes(res.items))
.finally(() => setLoading(false));
}, [userId]);

if (loading) return <div>Loading...</div>;

return (
<ul>
{nodes.map(node => (
<li key={node.id}>{node.title}</li>
))}
</ul>
);
}

Next.js Example

// pages/api/nodes.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { OfSelfClient } from '@ofself/sdk';

const client = new OfSelfClient({
apiKey: process.env.OFSELF_API_KEY!
});

export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { userId } = req.query;

try {
const { items } = await client.nodes.list({
userId: userId as string
});
res.status(200).json(items);
} catch (error) {
res.status(500).json({ error: 'Failed to fetch nodes' });
}
}

Browser Usage

Works in modern browsers with native fetch:

<script type="module">
import { OfSelfClient } from 'https://unpkg.com/@ofself/sdk';

const client = new OfSelfClient({ apiKey: 'your-key' });
const { items } = await client.nodes.list({ userId: 'user-123' });
console.log(items);
</script>

Pagination

// Iterate through all pages
async function getAllNodes(userId: string) {
const allNodes = [];
let page = 1;

while (true) {
const result = await client.nodes.list({
userId,
page,
perPage: 100
});

allNodes.push(...result.items);

if (!result.hasNext) break;
page++;
}

return allNodes;
}