@ductape/client
v0.0.3
Published
Frontend client SDK for Ductape - real-time database, storage, and more
Maintainers
Readme
@ductape/client
Frontend SDK for Ductape. Access databases, storage, APIs, agents, brokers, and more directly from the browser.
Install
npm install @ductape/clientSetup
import { createClient } from '@ductape/client';
const ductape = createClient({
publishableKey: import.meta.env.VITE_PUBLISHABLE_KEY,
product: 'my-product',
env: 'prd',
});Every request through the publishable key is routed through the Ductape proxy and requires a session token. Your backend issues the session token after the user logs in — the frontend passes it in the session field of each request.
Real-time
Call connect() before using any subscription feature:
await ductape.connect();
ductape.onConnectionChange((event) => {
console.log(event.state); // 'connecting' | 'connected' | 'disconnected' | 'error'
});
ductape.disconnect();Services
Databases
const sessionToken = getSessionFromYourBackend();
const result = await ductape.databases.query({
database: 'orders-db',
table: 'orders',
where: { status: 'pending' },
limit: 20,
session: sessionToken,
});
await ductape.databases.insert({
database: 'orders-db',
table: 'orders',
data: { userId: '123', amount: 4900 },
session: sessionToken,
});
await ductape.databases.update({
database: 'orders-db',
table: 'orders',
where: { id: 'abc' },
data: { status: 'shipped' },
session: sessionToken,
});
await ductape.databases.delete({
database: 'orders-db',
table: 'orders',
where: { id: 'abc' },
session: sessionToken,
});
// Real-time row changes
const sub = ductape.databases.subscribe(
{ database: 'orders-db', table: 'orders', session: sessionToken },
(changes) => console.log(changes)
);
sub.unsubscribe();Third-party API actions
// Register OAuth credentials for automatic token refresh
await ductape.api.oauth({
product: 'my-product',
app: 'salesforce',
env: 'prd',
tokens: { accessToken: userAccessToken, refreshToken: userRefreshToken },
expiresIn: 3600,
credentials: (tokens) => ({
'headers:Authorization': `Bearer ${tokens.accessToken}`,
}),
onExpiry: async (currentTokens) => {
const res = await ductape.api.run({
app: 'salesforce',
action: 'refresh-token',
input: { 'body:refresh_token': currentTokens.refreshToken },
session: sessionToken,
});
return { tokens: { accessToken: res.data.access_token }, expiresIn: res.data.expires_in };
},
});
const result = await ductape.api.run({
app: 'salesforce',
action: 'get-contacts',
session: sessionToken,
});Storage
await ductape.storage.upload({
storage: 'receipts',
fileName: 'invoice-001.pdf',
data: fileBlob,
mimeType: 'application/pdf',
session: sessionToken,
});
const file = await ductape.storage.download({ storage: 'receipts', fileName: 'invoice-001.pdf', session: sessionToken });
const list = await ductape.storage.list({ storage: 'receipts', session: sessionToken });
const url = await ductape.storage.signedUrl({ storage: 'receipts', fileName: 'invoice-001.pdf', expiresIn: 3600, session: sessionToken });Cache
await ductape.cache.set({ cache: 'app-cache', key: 'config', value: { theme: 'dark' }, ttl: 3600, session: sessionToken });
const entry = await ductape.cache.get({ cache: 'app-cache', key: 'config', session: sessionToken });
await ductape.cache.del({ cache: 'app-cache', key: 'config', session: sessionToken });Agents
const result = await ductape.agents.run({
agent: 'support-bot',
input: 'How do I reset my password?',
session: sessionToken,
});
// Streaming
const stream = await ductape.agents.stream({ agent: 'support-bot', input: 'Summarise my account.', session: sessionToken });
for await (const event of stream) {
if (event.type === 'token') process.stdout.write(event.data);
}Features
const run = await ductape.features.execute({
feature: 'process-order',
input: { orderId: 'ord_123' },
session: sessionToken,
});
const status = await ductape.features.status({
feature: 'process-order',
executionId: run.executionId,
session: sessionToken,
});
const sub = ductape.features.subscribe(
{ feature: 'process-order', executionId: run.executionId, session: sessionToken },
(events) => console.log(events)
);
sub.unsubscribe();Brokers
await ductape.brokers.publish({
broker: 'kafka-cluster',
topic: 'order-events',
message: { orderId: 'ord_123', event: 'created' },
session: sessionToken,
});
const sub = ductape.brokers.subscribe(
{ broker: 'kafka-cluster', topic: 'order-events', session: sessionToken },
(messages) => console.log(messages)
);
sub.unsubscribe();Vectors
const results = await ductape.vectors.query({
vector: 'product-embeddings',
query: [0.1, 0.2, 0.85],
topK: 5,
session: sessionToken,
});Graphs
const node = await ductape.graphs.createNode({
graph: 'social-graph',
label: 'User',
properties: { name: 'Alice', age: 30 },
session: sessionToken,
});Warehouse
const result = await ductape.warehouse.query({
query: 'SELECT * FROM orders WHERE status = :status',
params: { status: 'pending' },
sources: [{ database: 'orders-db', tables: ['orders'] }],
session: sessionToken,
});Resilience
const quota = await ductape.resilience.quota.run({ tag: 'api-rate-limit', session: sessionToken });
const health = await ductape.resilience.health.status({ tag: 'payment-service', session: sessionToken });Notifications
await ductape.notifications.push.send({
notification: 'order-shipped',
input: { orderId: 'ord_123', userId: 'usr_456' },
session: sessionToken,
});Analytics
// Anonymous tracking — no session needed before login
await ductape.analytics.track({ event: 'page_view', properties: { page: '/home' } });
// Link to a session after login
ductape.analytics.identify(sessionToken);
await ductape.analytics.track({ event: 'purchase', properties: { amount: 4900 } });