kaiwen-sdk
v1.0.1
Published
[](https://www.npmjs.com/package/kaiwen-sdk) [](#) [](https://www.typesc
Readme
Kaiwen SDK
A modular, platform-independent, and fully-typed TypeScript SDK for modern JavaScript applications (Browser, Node.js, React Native/Expo).
Features
- Platform-Agnostic Core: Works in any JavaScript runtime.
- CommonJS Build: Out-of-the-box support for React Native Metro Bundler and Node.js without transpile configurations.
- Modular Initialization: Toggle modules (auth, db, jobs, notifications) on or off to minimize runtime overhead.
- Type-Safe Schemas: Define custom types for Storage, Application State, Events, and Database collections.
- Auth Management: Easy register, login, session persistence, and automatic session restoration.
- Storage and Database: Built-in Memory, LocalStorage, and AsyncStorage adapters with a query-matching database.
- Background Jobs: Cancellable, pauseable, and resumeable task runner with progress tracking and pause checks.
- Pluggable Notifications: Console, Expo, and React Native push providers, supporting immediate or scheduled delivery with explicit triggers.
- Centralized Observability: Global logger manager collecting errors and runtime logs across all active modules.
Installation
npm install kaiwen-sdkQuick Start
Client SDK Example
Initialize the client SDK with all modules enabled (default):
import { createApp } from 'kaiwen-sdk';
// Initialize the app
const app = createApp();
await app.initialize();To disable specific modules or pass custom providers:
const app = createApp({
auth: true, // Enable local auth provider
db: false, // Disable database module
jobs: true, // Enable background jobs
notifications: false, // Disable notifications
logger: true, // Enable default console logging
});Server SDK Example
For server-side applications, use createServerApp which inherits from the core app structure but exposes backend-friendly aliases (like server.notifications):
import { createServerApp } from 'kaiwen-sdk';
const server = createServerApp();
await server.initialize();Authentication (Register and Login)
Kaiwen SDK makes user authentication extremely easy. By default, it uses LocalAuthProvider backed by the configuration's storage.
1. Register a New User
Registration automatically logs the user in and caches their session in storage.
try {
const user = await app.auth.register({
username: 'kaiwen',
password: 'secure_password_123',
email: '[email protected]' // Custom properties are supported!
});
console.log('Registered successfully! User ID:', user.id);
console.log('Current User logged in:', app.auth.user);
} catch (error) {
console.error('Registration failed:', error.message);
}2. Login
try {
const user = await app.auth.login({
username: 'kaiwen',
password: 'secure_password_123'
});
console.log('Logged in successfully! Username:', user.username);
} catch (error) {
console.error('Login failed:', error.message);
}3. Check and Restore Session on Startup
Session persistence is handled automatically. When you call app.initialize(), the SDK restores the cached user session.
// On app startup
await app.initialize();
if (app.auth.user) {
console.log('Session restored! Welcome back,', app.auth.user.username);
} else {
console.log('No active session.');
}4. Logout
await app.auth.logout();
console.log('Logged out. Current user is now:', app.auth.user); // nullNotifications and Expo Integration
The Notification Manager handles push notifications via custom providers.
Console Notification Provider (Default)
Useful for testing in terminal or non-mobile environments:
import { ConsoleNotificationProvider } from 'kaiwen-sdk';
const app = createApp({
notifications: new ConsoleNotificationProvider()
});Expo Notification Provider (React Native and Expo)
Pass the native Expo notification module during initialization:
import * as Notifications from 'expo-notifications';
import { createApp, ExpoNotificationProvider } from 'kaiwen-sdk';
const app = createApp({
notifications: new ExpoNotificationProvider(Notifications)
});
await app.initialize(); // Automatically requests permissionsSending a Notification Directly
await app.notification.send(
'Welcome!',
'This is a local push notification.',
{ clickAction: 'open_profile' }
);Scheduling a Notification (Expo, React Native, Console)
Schedule notifications by passing a delay (in seconds) or a specific target Date object. Explicit trigger properties conform to Expo SDK requirements.
// Schedule a notification to fire in 10 seconds
await app.notification.schedule(
'Scheduled Alert',
'This is triggered after 10 seconds.',
10,
{ sound: 'default' }
);
// Schedule a notification for a specific Date
const targetTime = new Date('2026-06-05T10:00:00');
await app.notification.schedule(
'Meeting Reminder',
'Your daily sync starts now.',
targetTime
);Centralized Logger and Observability
The Logger module automatically collects error reports and warnings from other components (such as failed background jobs, authentication errors, and database transaction failures).
Default Console Logger
By default, the console logger is active. You can customize the logger using AppOptions.
const app = createApp({
logger: true // Resolves to ConsoleLoggerProvider
});Custom Observability Provider (e.g., Sentry, Custom API)
To send errors and info logs to services like Sentry, LogRocket, or your backend log collection endpoint, implement the ILoggerProvider interface.
import { createApp, ILoggerProvider, LogMetadata } from 'kaiwen-sdk';
// Custom logger provider implementation
class MySentryLoggerProvider implements ILoggerProvider {
log(level: 'info' | 'warn' | 'error', message: string, error?: Error, metadata?: LogMetadata): void {
if (level === 'error') {
// Forward to Sentry
// Sentry.captureException(error || new Error(message), { extra: metadata });
console.log(`[Sentry Alert] Sent error: ${message}`);
} else {
// Forward info/warnings as breadcrumbs
// Sentry.addBreadcrumb({ message, level, data: metadata });
console.log(`[Sentry Breadcrumb] Level: ${level} | Message: ${message}`);
}
}
}
// Pass custom provider to app configuration
const app = createApp({
logger: new MySentryLoggerProvider()
});Logging Manually
You can log custom events directly from the app instance:
app.logger.info('User opened Settings screen', { userId: 'usr_123' });
app.logger.error('Failed to parse API payload', new Error('JSON parsing issue'));Combined Usage Scenarios
Kaiwen SDK modules are designed to integrate seamlessly through the shared EventBus and APIs.
Scenario 1: Automatic Job-Completion Push Notifications (Built-in)
By default, the Notification Manager listens for the job:completed event on the EventBus. When any job completes successfully, a push notification is automatically generated and sent to the active notification provider.
// Just run the job. When it finishes, a push notification will automatically trigger.
await app.jobs.start('image-optimization', async () => {
// Perform optimization tasks
return { optimizedCount: 42 };
});
// The user automatically receives a push notification:
// Title: Job Completed
// Body: Job "image-optimization" completed successfully.Scenario 2: Manual Notification / Alerting on Job Milestones or Failures
You can manually trigger push notifications or schedule reminders from within a job's execution context.
await app.jobs.start('video-upload', async (context) => {
try {
// Stage 1: Upload started
await app.notification.send('Upload Started', 'Your video is being uploaded.');
for (let i = 10; i <= 100; i += 30) {
context.updateProgress(i);
await context.checkPause();
if (context.isCancelled()) return { cancelled: true };
await new Promise((resolve) => setTimeout(resolve, 500));
}
} catch (error) {
// Notify on failure
await app.notification.send('Upload Failed', `Error: ${error.message}`);
throw error;
}
});Scenario 3: Event-Driven Scheduled Reminders (Auth + Notifications)
Using the EventBus, you can listen for application events and schedule future notifications dynamically. For example, when a user registers, schedule a welcome notification to fire after a delay.
// Subscribe to user registration event via EventBus
app.events.on('user:registered', async (user) => {
console.log(`Scheduling onboarding notification for ${user.username}`);
// Schedule a notification to trigger 30 minutes (1800 seconds) after registration
await app.notification.schedule(
'Getting Started',
`Hey ${user.username}! Need help setting up your profile?`,
1800,
{ screen: 'ProfileSetup' }
);
});
// Trigger registration
await app.auth.register({
username: 'kaiwen',
password: 'secure_password_123'
});Storage Manager
Type-safe, schema-enforced key-value storage.
interface MyStorageSchema {
theme: 'light' | 'dark';
token: string | null;
settings: {
notificationsEnabled: boolean;
};
}
// Pass schema to createApp
const app = createApp<{}, MyStorageSchema>();
// All operations are now strongly typed and asynchronous!
await app.storage.set('theme', 'dark');
const theme = await app.storage.get('theme'); // typed as 'light' | 'dark'Available adapters:
MemoryStorageAdapter(In-memory, default fallback)LocalStorageAdapter(Browserwindow.localStorage)AsyncStorageAdapter(React Native@react-native-async-storage/async-storage)
Background Jobs
Run, monitor, pause, resume, and cancel asynchronous work easily using the unified JobManager.
// Start a job with an executor
const jobInfo = await app.jobs.start('video-upload', async (context) => {
for (let i = 0; i <= 100; i += 10) {
// Check if job was requested to pause
await context.checkPause();
// Check if job was cancelled
if (context.isCancelled()) {
console.log('Upload cancelled');
return { cancelled: true };
}
// Update progress
context.updateProgress(i);
await new Promise((r) => setTimeout(r, 100)); // Simulate work
}
return { fileUrl: 'https://example.com/video.mp4' };
});
// Control job execution via the JobManager
await app.jobs.pause('video-upload');
await app.jobs.resume('video-upload');
await app.jobs.cancel('video-upload');
// Access job metrics
const job = app.jobs.get('video-upload');
if (job) {
console.log('Status:', job.status); // 'running', 'paused', 'completed', 'cancelled', 'failed'
console.log('Progress:', job.progress); // 0-100
}Database Manager
A client-side or server-side document database manager with schema-enforcing capabilities and querying.
interface UserProfile {
name: string;
age: number;
}
interface MyDbSchema {
users: UserProfile;
}
const app = createApp<{}, {}, {}, any, MyDbSchema>();
// Insert document into 'users' collection
const user = await app.db.insert('users', { name: 'Kaiwen', age: 25 });
console.log('New User ID:', user.id); // Automatically assigned
// Find documents with simple query-matching logic
const youngUsers = await app.db.find('users', { name: 'Kaiwen' });State Manager
Asynchronous application state manager with reactive callbacks.
interface MyStateSchema {
counter: number;
theme: 'light' | 'dark';
}
const app = createApp<{}, {}, MyStateSchema>();
// Subscribe to state change events
const unsubscribe = app.state.subscribe('counter', (newValue, oldValue) => {
console.log(`Counter changed from ${oldValue} to ${newValue}`);
});
// Set state asynchronously
await app.state.set('counter', 0);
// Get state asynchronously
const currentCounter = await app.state.get('counter');
// Unsubscribe when done
unsubscribe();EventBus
Communication hub for modules to talk to each other without tight coupling.
// Listen to a custom event
app.events.on('user:registered', (user) => {
console.log('Event bus received user signup:', user.username);
});
// Emit an event
app.events.on('user:registered', { username: 'kaiwen' });Running Tests
Verify the SDK inside the project workspace:
npm run testBuild the distribution bundles:
npm run build