Interact with Desktop App via API
Eidos provides a powerful RPC-based API through its desktop application. By using @eidos.space/client with Bun, you can quickly automate data ingestion with built-in TypeScript support and superior performance.
This guide demonstrates how to fetch the top stories from Hacker News and ingest them into an Eidos table using Bun. The example includes story content for semantic search capabilities.
Prerequisites
Section titled “Prerequisites”- Eidos Desktop: Ensure the Eidos desktop application is running.
- Bun: Ensure you have Bun installed on your machine.
Initialize a new project and install the Eidos RPC client:
# Initialize a new Bun projectmkdir hn-ingestor && cd hn-ingestorbun init -y
# Install the Eidos RPC clientbun add @eidos.space/clientExample: Hacker News Ingestor
Section titled “Example: Hacker News Ingestor”Create a file named index.ts and add the following code. This script will:
- Connect to your Eidos desktop instance using
createEidosClient. - Check if a table named “Hacker News” exists, and create it if it doesn’t.
- Fetch the top 10 stories from Hacker News, including their content.
- Upsert the data: If a story (indexed by its HN ID) already exists, update its score; otherwise, create a new record.
import { createEidosClient } from '@eidos.space/client';
// Your Space ID can be found in the Eidos Desktop app (dashboard or URL)const SPACE_ID = 'your_space_id';const EIDOS_PORT = 13127; // Default Eidos Desktop RPC port
// 1. Initialize the Eidos Clientconst client = createEidosClient({ endpoint: `http://${SPACE_ID}.eidos.localhost:${EIDOS_PORT}/rpc`,});
const space = client.space;const TABLE_NAME = 'Hacker News';
// 2. Check and Create Tableconst tables = await space.schema.listTables();let table = tables.find(t => t.name === TABLE_NAME);
if (!table) { console.log(`Creating table "${TABLE_NAME}"...`); table = await space.schema.createTable({ name: TABLE_NAME, fields: [ { name: 'Content', columnName: 'content', type: 'text' }, { name: 'HN ID', columnName: 'hn_id', type: 'number' }, { name: 'URL', columnName: 'url', type: 'url' }, { name: 'HN Link', columnName: 'hn_link', type: 'url' }, { name: 'Author', columnName: 'author', type: 'text' }, { name: 'Score', columnName: 'score', type: 'number' }, { name: 'Type', columnName: 'type', type: 'select', property: { options: [ { id: 'self', name: 'self', color: 'blue' }, { id: 'link', name: 'link', color: 'green' }, ], }, }, ], });}
const hnTable = space.table(table.id);
// 3. Fetch Hacker News Top Storiesconsole.log('Fetching top stories...');const topIds = (await fetch('https://hacker-news.firebaseio.com/v0/topstories.json') .then(res => res.json())) as string[];
// Process top 10for (const id of topIds.slice(0, 10)) { const item = (await fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json`) .then(res => res.json())) as { type: string; title: string; url: string; text?: string; by: string; score: number; };
if (item?.type === 'story') { // Extract content: 'text' exists for self-posts (Ask HN, Show HN) // For external links, content will be empty const content = item.text ? item.text.replace(/<[^>]+>/g, '') : ''; const postType = item.text ? 'self' : 'link';
const data = { content: content, url: item.url, hn_link: `https://news.ycombinator.com/item?id=${id}`, author: item.by, score: item.score, type: postType, };
// 4. Ingest/Update into Eidos // Check if record already exists using the custom hn_id field const existing = await hnTable.findFirst({ where: { hn_id: id } });
if (existing) { console.log(`Updating: ${item.title}`); await hnTable.update({ where: { _id: existing._id }, data }); } else { console.log(`Creating: ${item.title}`); await hnTable.create({ data: { hn_id: id, ...data }, }); } }}
console.log('Done!');Run the Script
Section titled “Run the Script”Execute the script directly using Bun:
bun index.tsNext Steps
Section titled “Next Steps”- Learn how to use semantic search on your ingested data
- Explore the Table API reference for more operations
- Build custom Script Extensions for automated workflows