@arke-institute/sdk
v3.6.16
Published
TypeScript SDK for the Arke API - auto-generated from OpenAPI spec
Downloads
350
Maintainers
Readme
@arke-institute/sdk
TypeScript SDK for the Arke API - auto-generated from OpenAPI spec.
Installation
npm install @arke-institute/sdkQuick Start
import { ArkeClient } from '@arke-institute/sdk';
const arke = new ArkeClient({
authToken: 'your-jwt-token',
});
// Create an entity
const { data, error } = await arke.api.POST('/entities', {
body: {
collection_id: '01ABC...',
type: 'document',
properties: { title: 'My Document' },
},
});
if (error) {
console.error('Failed:', error);
} else {
console.log('Created:', data.id);
}Configuration
const arke = new ArkeClient({
// Base URL (default: 'https://api.arke.institute')
baseUrl: 'https://api.arke.institute',
// JWT or API key
authToken: 'your-token',
// Network: 'main' or 'test' (default: 'main')
network: 'test',
// Custom headers
headers: {
'X-Custom-Header': 'value',
},
});API Access
All API calls are made through the arke.api property, which provides full type safety:
// GET request
const { data } = await arke.api.GET('/entities/{id}', {
params: { path: { id: '01XYZ...' } },
});
// POST request
const { data } = await arke.api.POST('/entities', {
body: { collection_id: '...', type: 'document', properties: {} },
});
// PUT request (update)
const { data } = await arke.api.PUT('/entities/{id}', {
params: { path: { id: '01XYZ...' } },
body: { expect_tip: 'bafyrei...', properties_merge: { status: 'active' } },
});
// DELETE request
await arke.api.DELETE('/relationships', {
body: { source_id: '...', target_id: '...', predicate: 'contains' },
});Available Endpoints
The SDK provides typed access to all Arke API endpoints:
| Endpoint Group | Description |
|----------------|-------------|
| /auth/* | Authentication and registration |
| /users/* | User profile and API keys |
| /collections/* | Collection CRUD, roles, members |
| /entities/* | Entity CRUD |
| /relationships | Relationship management |
| /files/* | File storage and downloads |
| /folders/* | Folder hierarchy |
| /versions/* | Version history |
| /agents/* | Agent management |
| /permissions/* | Permission introspection |
Error Handling
import {
ArkeError,
CASConflictError,
NotFoundError,
parseApiError
} from '@arke-institute/sdk';
const { data, error, response } = await arke.api.GET('/entities/{id}', {
params: { path: { id: 'invalid-id' } },
});
if (error) {
// Parse into typed error
const arkeError = parseApiError(response.status, error);
if (arkeError instanceof CASConflictError) {
console.log('Concurrent modification - expected:', arkeError.expectedTip);
} else if (arkeError instanceof NotFoundError) {
console.log('Entity not found');
}
}CAS Retry for Concurrent Updates
When multiple clients update the same entity simultaneously, use withCasRetry for automatic retry with backoff:
import { ArkeClient, withCasRetry } from '@arke-institute/sdk';
const client = new ArkeClient({ authToken: 'xxx' });
const { data, attempts } = await withCasRetry({
getTip: async () => {
// Lightweight endpoint - single DO lookup, no manifest fetch
const { data } = await client.api.GET('/entities/{id}/tip', {
params: { path: { id: entityId } }
});
return data!.cid;
},
update: async (tip) => {
return client.api.PUT('/entities/{id}', {
params: { path: { id: entityId } },
body: {
expect_tip: tip,
relationships_add: [{ predicate: 'contains', peer: childId }]
}
});
}
}, { concurrency: 100 }); // Expected number of concurrent writers
console.log(`Updated in ${attempts} attempt(s)`);Set concurrency based on expected parallel updates. The utility automatically:
- Staggers initial requests to reduce collisions
- Applies exponential backoff with jitter on conflicts
- Scales retry attempts based on concurrency level
See docs/cas-retry.md for best practices.
Authentication Management
const arke = new ArkeClient();
// Set token after login
arke.setAuthToken('new-token');
// Check auth status
if (arke.isAuthenticated) {
// Make authenticated requests
}
// Clear token on logout
arke.clearAuthToken();Test Network
Use the test network for development (uses 'II' prefixed IDs):
const arke = new ArkeClient({
authToken: 'your-token',
network: 'test',
});Folder Upload
Upload entire folder structures with automatic CID computation and relationship linking:
Node.js
import { ArkeClient } from '@arke-institute/sdk';
import { uploadTree, scanDirectory } from '@arke-institute/sdk/operations';
const arke = new ArkeClient({ authToken: 'your-token' });
// Scan a local directory
const tree = await scanDirectory('/path/to/my-folder');
// Upload to a new collection
const result = await uploadTree(arke, tree, {
target: {
createCollection: {
label: 'My Upload',
description: 'Uploaded folder contents',
},
},
onProgress: (p) => {
console.log(`${p.phase}: ${p.completedFiles}/${p.totalFiles} files`);
},
});
console.log('Collection:', result.collection.id);
console.log('Files:', result.files.length);
console.log('Folders:', result.folders.length);Browser (Drag & Drop)
import { uploadTree, scanFileSystemEntries } from '@arke-institute/sdk/operations';
dropzone.ondrop = async (e) => {
e.preventDefault();
const entries = Array.from(e.dataTransfer.items)
.map(item => item.webkitGetAsEntry())
.filter(Boolean);
const tree = await scanFileSystemEntries(entries);
const result = await uploadTree(client, tree, {
target: { collectionId: 'existing-collection-id' },
});
};Browser (File Input)
import { uploadTree, scanFileList } from '@arke-institute/sdk/operations';
// <input type="file" webkitdirectory multiple />
input.onchange = async (e) => {
const tree = await scanFileList(e.target.files);
const result = await uploadTree(client, tree, {
target: { parentId: 'existing-folder-id', collectionId: 'collection-id' },
});
};Upload Options
const result = await uploadTree(client, tree, {
target: {
// Option 1: Create new collection
createCollection: { label: 'New Collection' },
// Option 2: Upload to existing collection root
collectionId: '01ABC...',
// Option 3: Upload to existing folder
collectionId: '01ABC...',
parentId: '01XYZ...',
},
// Progress tracking
onProgress: (p) => console.log(p.phase, p.completedFiles),
// Parallel uploads (default: 5)
concurrency: 10,
// Continue if some files fail
continueOnError: true,
});CID Utilities
import { computeCid, verifyCid } from '@arke-institute/sdk/operations';
// Compute CIDv1 for any content
const cid = await computeCid(new TextEncoder().encode('hello'));
// => "bafkreifzjut3te2nhyekklss27nh3k72ysco7y32koao5eei66wof36n5e"
// Verify content matches CID
const isValid = await verifyCid(content, expectedCid);Development
Regenerate Types
When the API changes, regenerate the types:
# From production API
npm run generate
# From local dev server
npm run generate:localBuild
npm run buildTest
npm testPublish
# Dry run
npm run publish-all:dry
# Actual publish
npm run publish-allHigh-Level Operations
The SDK includes modules for common workflows:
- CAS Retry: Concurrent update handling with automatic retry (docs)
- Folder Upload: Upload entire directory structures with CID computation
- BatchOperations: Bulk entity/relationship creation (planned)
- CryptoOperations: Ed25519 key generation (planned)
License
MIT
