tevrocsdk
v0.1.38
Published
JavaScript SDK for the Tevroc API.
Maintainers
Readme
Tevroc SDK
Tevroc SDK helps you work with Tevroc apps and worker APIs from JavaScript or TypeScript projects. Use it for authentication, records, custom functions, AI integrations, payments, file handling, and more.
Install
npm / ESM
npm install tevrocsdkBrowser
<script src="https://unpkg.com/tevrocsdk@latest/tevroc-sdk.min.js"></script>
<script>
const tevroc = Tevroc.createClient({
baseUrl: "https://your-worker.example.workers.dev"
});
</script>Native / desktop integration (Capacitor and Tauri)
Tevroc SDK works in web apps, but it also fits naturally into mobile and desktop shells. When you need OAuth callbacks, native file access, or deep links, the host app usually provides the platform bridge and the SDK supplies the API client.
Capacitor (mobile)
- Declare the app identity and a custom URL scheme in your Capacitor config so the app can receive OAuth redirects.
- Add the Capacitor app and browser plugins so the SDK can use native file save, toast, and browser flows when available.
- Add an Android intent filter so the platform can route callback URLs back into your app.
- Listen for the platform event and forward the URL into your auth callback flow.
- For offline support, the SDK will keep using native storage when the Capacitor SQLite plugin is available and will safely fall back to localStorage in web or unsupported environments.
Typical file locations:
project-root/
├── capacitor.config.ts
├── android/
│ └── app/
│ └── src/
│ └── main/
│ └── AndroidManifest.xml
└── src/
└── app code that handles appUrlOpen eventsA typical setup looks like this:
File: capacitor.config.ts
import type { CapacitorConfig } from "@capacitor/cli";
const config: CapacitorConfig = {
appId: "com.example.app",
appName: "Example App",
webDir: "dist",
plugins: {
App: {
appUrlOpen: {
androidScheme: "myapp",
iosScheme: "myapp",
},
},
},
};
export default config;File: android/app/src/main/AndroidManifest.xml
<manifest>
<uses-permission android:name="android.permission.INTERNET" />
<application>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp" />
</intent-filter>
</application>
</manifest>File: src/main.ts or your app bootstrap file
import { App } from "@capacitor/app";
App.addListener("appUrlOpen", ({ url }) => {
handleAuthCallback(url);
});Tauri (desktop)
- Register a custom protocol in your Tauri config so the desktop app can receive deep links.
- Add the relevant Rust plugins for deep-link handling and single-instance behavior.
- Emit a frontend event from the Rust side and listen for it in your app.
Typical file locations:
project-root/
├── src-tauri/
│ ├── tauri.conf.json
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
└── src/
└── frontend code that listens for deep-link eventsA typical setup looks like this:
File: src-tauri/tauri.conf.json
{
"identifier": "com.example.desktop",
"plugins": {
"deep-link": {
"desktop": {
"schemes": ["myapp"]
}
}
}
}File: src-tauri/Cargo.toml
[dependencies]
tauri = { version = "2", features = [] }
tauri-plugin-deep-link = "2"
tauri-plugin-single-instance = "2"File: src-tauri/src/lib.rs
use tauri::{Manager, Emitter};
use tauri_plugin_deep_link::DeepLinkExt;
use serde_json::json;
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
let builder = tauri::Builder::default()
.plugin(tauri_plugin_single_instance::init(|app, argv, _cwd| {
if let Some(url) = argv.get(1) {
let _ = app.emit_to("main", "deep-link://open-url", json!(url));
}
}))
.plugin(tauri_plugin_deep_link::init())
.setup(|app| {
#[cfg(any(target_os = "linux", all(debug_assertions, windows)))]
app.deep_link().register_all()?;
Ok(())
});
builder.run(tauri::generate_context!()).expect("error while running app");
}File: src/main.ts or your app bootstrap file
import { listen } from "@tauri-apps/api/event";
listen("deep-link://open-url", (event) => {
handleAuthCallback(event.payload as string);
});Setup notes for local apps and desktop shells
If you are consuming the SDK from a monorepo or local workspace, point your app dependency at the local package folder and rebuild the SDK output before launching the app:
npm install ../tevrocsdk
cd ../tevrocsdk && npm run buildFor Tauri desktop apps, ensure the frontend can access the Tauri bridge and the Rust side exposes the PDF command. The recommended setup is:
- add the Tauri plugins for deep-link, dialog, fs, opener, and shell in your Rust app
- expose a command such as
open_pdf_filefrom client-flow/src-tauri/src/lib.rs - keep the base64 dependency in client-flow/src-tauri/Cargo.toml
For web and Capacitor apps, preview/print fall back to browser popup windows and native file save flows where available. In offline mode, the SDK keeps a local snapshot of entity data and retries sync when the network is available again.
Added services and capabilities
Recent SDK updates include:
- PDF helpers:
tevroc.pdf.downloadPdf,tevroc.pdf.previewPdf, andtevroc.pdf.printPdf - Desktop-friendly PDF handling for Tauri, where the SDK writes a temporary PDF and opens it with the host OS viewer
- Offline sync support with a safe fallback when Capacitor background-task support is unavailable
- Native store helpers for web/localStorage fallback and native persistence in Capacitor/Tauri contexts
- Auth, entity, integration, payments, and file helpers that work through the same unified client object
Create a client
Start by creating a client with your Tevroc worker URL and app details. This gives you a single object that you can use throughout your app for authentication, data access, integrations, and more.
import { createClient } from "tevrocsdk";
const tevroc = createClient({
baseUrl: "https://your-worker.example.workers.dev",
serviceUrl: "https://services.example.com",
appId: "tevroc-portal",
appName: "Tevroc Portal",
});You can also reuse an existing access token:
const tevroc = createClient({
baseUrl: "https://your-worker.example.workers.dev",
token: localStorage.getItem("tevroc_access_token"),
appId: "tevroc-portal",
appName: "Tevroc Portal",
});Authentication
Use the authentication helpers to sign users in, keep their session active, and fetch profile information. These methods are useful for login pages, protected screens, and account management flows.
Log in and fetch your profile
const { token, user } = await tevroc.auth.login({
email: "[email protected]",
password: "correct horse battery staple",
});
const me = await tevroc.auth.me();Register, log out, and reset password
await tevroc.auth.register({
email: "[email protected]",
password: "correct horse battery staple",
});
await tevroc.auth.logout();
await tevroc.auth.verifyOtp({ code: "123456" });
await tevroc.auth.changePassword({ oldPassword: "old", newPassword: "new" });
await tevroc.auth.resetPassword({ email: "[email protected]" });
await tevroc.auth.loginUrl("/dashboard");Google sign-in
await tevroc.auth.googleLogin({
appId: "tevroc-portal",
appName: "Tevroc Portal",
serviceUrl: "https://services.example.com",
});
tevroc.auth.onGoogleLogin((user, error) => {
if (error) {
console.error("Google login failed", error);
return;
}
console.log("Google user", user);
});
await tevroc.auth.loginWithGoogle({
accessToken: googleAccessToken,
});
await tevroc.auth.loginWithProvider("google", "/dashboard");Work with entities
Entities let you manage dynamic records in a simple, Base44-style way. They are ideal for CRUD screens such as projects, tasks, customers, or any custom business data.
const created = await tevroc.entities.Project.create({
name: "Launch site",
status: "active",
});
const projects = await tevroc.entities.Project.list({ limit: 20 });
const filtered = await tevroc.entities.Project.query({
filter: { status: "active" },
limit: 10,
});
await tevroc.entities.Project.update(created.data.id, { status: "done" });Common entity methods:
list({ limit, offset })get(id)create(record)update(id, patch)delete(id)query({ filter, limit })filter(filter, sortOrOptions, limit)bulkCreate(records)bulkUpdate(records)bulkDelete(ids)import(records)
Call custom functions
Use custom functions when you want to trigger server-side logic by name. This is useful for actions such as sending data to a worker route, running a calculation, or invoking a workflow.
await tevroc.functions.invoke("ping", { hello: "world" });
// Shorthand for common functions
await tevroc.functions.ping({ hello: "world" });Use core integrations
Core integrations give you quick access to common AI and content features such as LLM prompts, image generation, email delivery, file uploads, and signed URLs. These helpers make it easy to add backend-powered features without writing custom plumbing.
await tevroc.integrations.Core.InvokeLLM({
prompt: "Write a two-line launch checklist.",
});
await tevroc.integrations.Core.GenerateImage({
prompt: "A futuristic dashboard",
});
await tevroc.integrations.Core.SendEmail({
to: "[email protected]",
subject: "Hello",
text: "From Tevroc",
});
await tevroc.integrations.Core.UploadFile(file, {
filename: "report.pdf",
contentType: "application/pdf",
});
await tevroc.integrations.Core.UploadPrivateFile(file, {
filename: "report.pdf",
contentType: "application/pdf",
});
await tevroc.integrations.Core.CreateFileSignedUrl({
key: "report.pdf",
});
await tevroc.integrations.Core.ExtractDataFromUploadedFile({
fileId: "123",
});Accept payments
If your app needs a checkout or payment flow, the payments helpers can start a Yoco-based payment experience and let you react to the resulting status updates.
await tevroc.payments.create({
amountZAR: 50,
appId: "tevroc-portal",
mode: "web",
});
const unsubscribe = tevroc.payments.onstatus((status, error) => {
if (error) {
console.error("Payment listener error", error);
return;
}
console.log("Payment status:", status);
});Work with files and local app data
Use the file helpers to build links for uploaded assets and the native helpers to store lightweight app data locally across web, mobile, and desktop environments.
const fileUrl = tevroc.files.url("reports/summary.pdf");
const privateFileUrl = tevroc.files.privateUrl("reports/private.pdf");
await tevroc.files.get("reports/summary.pdf");
await tevroc.files.getPrivate("reports/private.pdf");Native store helpers
const store = tevroc.native.store;
const ref = store.ref("settings");
await store.set(ref, { theme: "dark" });
await store.update(ref, { lastOpened: Date.now() });
await store.get(ref);
await store.remove(ref);Google Drive and project helpers
await tevroc.native.files.saveJsonToDrive("project", { ok: true }, null, "user-1");
await tevroc.native.files.readJsonFromDrive("file_123", "user-1");
await tevroc.native.files.deleteFromDrive("file_123", "user-1");
await tevroc.native.projects.upsertUser({
uid: "u1",
email: "[email protected]",
displayName: "Ada",
photoURL: "",
});
await tevroc.native.projects.saveProjectMeta("u1", "p1", { title: "Launch" });Create agent conversations
Agents are useful when you want to create multi-turn conversations with a support or assistant experience. You can start a conversation, add user messages, and list the thread history from the SDK.
const conversation = await tevroc.agents.Support.createConversation({
title: "Onboarding",
});
## Offline & sync features
The SDK distribution includes built-in offline sync support when used in apps that integrate the native helpers (Capacitor/Tauri). Key features:
- Local storage of entities using platform-native SQLite when available (Capacitor/Tauri), with `localStorage` fallback.
- Queued operations: `create`, `update`, and `delete` are queued while offline and applied locally immediately so the UI remains responsive.
- Sync engine: periodic and event-driven flush of queued operations when the app regains connectivity or resumes; emits events and stores simple conflicts detected by timestamp comparison.
- Conflict APIs: `client.offline.listConflicts()` and `client.offline.resolveConflict(conflictId, resolution)` let apps inspect and resolve conflicts.
Example usage:
```js
const client = createClient({ baseUrl: 'https://api.example', appId: 'myapp' });
client.offline.startAutoSync();
client.offline.on('conflict', ({ conflictId }) => {
console.warn('Conflict detected:', conflictId);
});Notes:
- The SDK attempts to use
@capacitor/network,@capacitor/app, and@capacitor-community/background-taskwhen available. If plugins are missing it falls back to foreground sync on resume/focus. - For production mobile background sync, configure OS-level background permissions and install/verify background-task plugins.
await tevroc.agents.Support.addMessage(conversation.data.id, { role: "user", content: "Help me configure my workspace", });
const messages = await tevroc.agents.Support.listMessages(conversation.data.id);
## Connectors, logs, custom integrations, and SSO
These features help you connect external services, track app events, call custom integrations, and handle SSO flows. They are especially useful for admin dashboards, automation, and customer-facing experiences.
```js
await tevroc.connectors.list();
await tevroc.connectors.get("slack");
await tevroc.connectors.connect("slack", { config: { teamId: "T123" } });
await tevroc.connectors.disconnect("slack");
await tevroc.connectors.status("slack");
await tevroc.connectors.user.list();
await tevroc.connectors.user.refresh("abc123");
await tevroc.logs.list({ limit: 20 });
await tevroc.logs.create({
level: "info",
message: "User opened dashboard",
context: { source: "web" },
});
await tevroc.customIntegrations.example.echo({ ok: true });
await tevroc.sso.accessToken({ code: "provider-code" });
await tevroc.sso.callback({ code: "provider-code" });Make raw requests
Use request when you need to call a worker route that does not yet have a dedicated helper. This gives you a flexible fallback for custom endpoints while still using the same authenticated client.
const health = await tevroc.request("/health", { auth: false });Handle errors
Tevroc SDK throws structured errors that make it easier to respond to failed requests. You can inspect the status code and details to guide the user experience or retry logic.
import { TevrocError } from "tevrocsdk";
try {
await tevroc.auth.me();
} catch (error) {
if (error instanceof TevrocError && error.status === 401) {
// Ask the user to sign in again.
}
}