@umituz/web-cloudflare
v1.7.8
Published
Comprehensive Cloudflare Workers & Pages integration with config-based patterns, middleware, router, workflows, AI (with audio/music generation, TTS, ASR), React hooks, and multi-tenant support
Maintainers
Keywords
Readme
@umituz/web-cloudflare
Comprehensive Cloudflare Workers & Pages integration with config-based patterns, middleware, router, workflows, and AI building blocks.
🚀 Features
- ✅ Config-Based Patterns - Pre-built configurations for different app types
- ✅ Domain-Driven Design - DDD architecture for better modularity
- ✅ Wrangler CLI Integration - TypeScript wrapper for Wrangler CLI commands
- ✅ Workers Service - HTTP handler with routing and middleware
- ✅ AI Building Blocks ⭐ NEW - Generic LLM, embeddings, vector search, streaming
- ✅ AI Gateway - Multi-provider AI routing with caching, fallback, cost tracking
- ✅ Workers AI Integration - Direct Cloudflare Workers AI with neuron tracking
- ✅ Express-like Router - Simple, intuitive routing with middleware support
- ✅ Enhanced Middleware - CORS, caching, rate limiting, AI quota, session management
- ✅ Workflows - Idempotent, retryable long-running operations with AI pipelines
- ✅ Utility Functions - 100+ helper functions for common tasks
- ✅ Type-Safe - Full TypeScript support with JSDoc
- ✅ Tree-Shakeable - Subpath exports for optimal bundle size
- ✅ Performance Optimized - Memory leak prevention, intelligent caching, automatic cleanup
📦 Installation
npm install @umituz/web-cloudflare🎯 Quick Start
AI-Ready Worker (Recommended for AI Applications)
import { aiReadyConfig, WorkerService } from '@umituz/web-cloudflare/config';
import { createRouter } from '@umituz/web-cloudflare/router';
import { requireAIQuota, cors } from '@umituz/web-cloudflare/middleware';
import { WorkersAIService, EmbeddingService, VectorizeService } from '@umituz/web-cloudflare/ai';
// Initialize AI services
const ai = new WorkersAIService({ bindings: { AI: env.AI } });
const embeddings = new EmbeddingService({ bindings: { AI: env.AI } });
const vectorize = new VectorizeService();
vectorize.bindIndex('documents', env.VECTORIZE);
// Create worker with AI-ready config
const worker = new WorkerService({
...aiReadyConfig,
env: {
KV: env.KV,
R2: env.R2,
D1: env.D1,
AI: env.AI,
VECTORIZE: env.VECTORIZE,
},
});
// Setup router with AI quota middleware
const router = createRouter()
.use(cors)
.use((req) => requireAIQuota(req, {
enabled: true,
quota: 10000000, // 10M neurons per day
period: 86400,
kv: env.KV,
}))
.post('/api/ai/generate', async (req) => {
const { prompt, model } = await req.json();
const response = await ai.callLLM(model || '@cf/meta/llama-3.1-8b-instruct', {
prompt,
});
return json(response);
})
.post('/api/embeddings', async (req) => {
const { text } = await req.json();
const embedding = await embeddings.generateTextEmbedding(text);
return json({ embedding, dimensions: embedding.length });
})
.post('/api/search', async (req) => {
const { query } = await req.json();
const queryEmbedding = await embeddings.generateTextEmbedding(query);
const results = await vectorize.query(queryEmbedding, { topK: 10 });
return json({ results });
});
export default {
fetch: (req, env, ctx) => router.handle(req, env, ctx),
};Using Pre-built Configs
import { socialMediaConfig, ConfigBuilder, WorkerService } from '@umituz/web-cloudflare/config';
const worker = new WorkerService({
...socialMediaConfig,
env: {
KV: env.KV,
R2: env.R2,
D1: env.D1,
AI: env.AI,
},
});
// Or build your own with AI support
const customConfig = ConfigBuilder
.create()
.withCache({ enabled: true, defaultTTL: 300 })
.withRateLimit({ enabled: true, maxRequests: 100, window: 60 })
.withAIGateway({
providers: [
{
id: 'workers-ai',
name: 'Workers AI',
type: 'workers-ai',
baseURL: '',
apiKey: '',
models: ['@cf/meta/llama-3.1-8b-instruct'],
weight: 3,
},
{
id: 'openai-fallback',
name: 'OpenAI',
type: 'openai',
baseURL: 'https://api.openai.com/v1',
apiKey: '',
models: ['gpt-4'],
fallbackProvider: 'workers-ai',
weight: 1,
},
],
cacheEnabled: true,
cacheTTL: 7200,
})
.withAIModels(['@cf/meta/llama-3.1-8b-instruct', '@cf/meta/llama-3.3-70b-instruct'])
.withAICaching(true, 7200)
.withAIQuota(10000000, 86400) // 10M neurons per day
.withVectorize(true, ['documents', 'embeddings'])
.build();Using Router
import { createRouter, json, success, fail } from '@umituz/web-cloudflare/router';
import { cors } from '@umituz/web-cloudflare/middleware';
const router = createRouter()
.use(cors)
.get('/api/health', () => json({ status: 'healthy' }))
.get('/api/users', async () => {
const users = await fetchUsers();
return success(users);
})
.post('/api/users', async (request) => {
const body = await request.json();
const user = await createUser(body);
return success(user, 'User created');
})
.get('/api/users/:id', async (request, params) => {
const user = await getUser(params.id);
if (!user) {
return fail('User not found', 404);
}
return success(user);
});
export default {
fetch: (req, env, ctx) => router.handle(req, env, ctx),
};RAG Implementation (Retrieval-Augmented Generation)
import { WorkersAIService, EmbeddingService, VectorizeService } from '@umituz/web-cloudflare/ai';
const ai = new WorkersAIService({ bindings: { AI: env.AI } });
const embeddings = new EmbeddingService({ bindings: { AI: env.AI } });
const vectorize = new VectorizeService();
vectorize.bindIndex('documents', env.VECTORIZE);
// 1. Index documents
const docs = [
{ id: 'doc1', text: 'Cloudflare Workers is fast', source: 'docs' },
{ id: 'doc2', text: 'Edge computing is the future', source: 'blog' },
];
for (const doc of docs) {
const embedding = await embeddings.generateTextEmbedding(doc.text);
await vectorize.upsert([{
id: doc.id,
values: embedding,
metadata: { text: doc.text, source: doc.source },
}]);
}
// 2. RAG query
router.post('/api/rag', async (req) => {
const { query } = await req.json();
// Generate query embedding
const queryEmbedding = await embeddings.generateTextEmbedding(query);
// Search vector index
const ragResult = await vectorize.ragQuery(
queryEmbedding,
docs.map(d => ({ id: d.id, text: d.text, metadata: { source: d.source } })),
{ topK: 3 }
);
// Generate response with context
const response = await ai.callLLM('@cf/meta/llama-3.1-8b-instruct', {
prompt: `Context: ${ragResult.context}\n\nQuestion: ${query}\n\nAnswer:`,
});
return json({
answer: response.content,
sources: ragResult.matches,
});
});AI Content Generation Pipeline
import { WorkflowService, WORKFLOW_TEMPLATES } from '@umituz/web-cloudflare/workflows';
const workflows = new WorkflowService({
KV: env.KV,
D1: env.D1,
maxExecutionTime: 600,
});
// Create workflow
await workflows.createWorkflow({
id: 'blog-post-generator',
name: 'Blog Post Generator with Quality Control',
steps: [
{ id: 'generate', handler: 'ai-generate-draft', timeout: 60 },
{ id: 'validate', handler: 'content-validate', dependencies: ['generate'] },
{ id: 'seo-optimize', handler: 'ai-optimize-seo', dependencies: ['validate'] },
{ id: 'save', handler: 'd1-insert', dependencies: ['seo-optimize'] },
],
});
// Execute workflow
const execution = await workflows.startExecution('blog-post-generator', {
topic: 'Cloudflare Workers AI',
tone: 'professional',
});
// Check status
const status = await workflows.getExecution(execution.id);
console.log('Status:', status.status);
console.log('Completed steps:', status.completedSteps);Enhanced D1 Service with Migrations & Transactions
import { D1Service, D1QueryBuilder } from '@umituz/web-cloudflare/d1';
const d1 = new D1Service();
d1.bindDatabase('main', env.DB);
// Create migrations table
await d1.createTable('_migrations', {
id: 'TEXT PRIMARY KEY',
name: 'TEXT NOT NULL',
sql: 'TEXT NOT NULL',
applied_at: 'INTEGER',
rolled_back_at: 'INTEGER',
}, 'main');
// Run migration
await d1.runMigration(`
CREATE TABLE users (
id TEXT PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
created_at INTEGER
)
`, 'main');
// Query builder
const builder = d1.queryBuilder('users');
const result = await builder
.select(['id', 'email'])
.where('email LIKE ?', ['%@example.com'])
.orderBy('created_at', 'DESC')
.limit(10)
.execute('main');
// Transaction
await d1.runInTransaction(async (txn) => {
await txn.query(`INSERT INTO users (id, email) VALUES (?, ?)`, ['user1', '[email protected]']);
await txn.query(`INSERT INTO profiles (user_id, bio) VALUES (?, ?)`, ['user1', 'Bio']);
await txn.commit();
}, 'main');
// Schema validation
const validation = await d1.validateSchema('users', {
id: 'TEXT',
email: 'TEXT',
created_at: 'INTEGER',
}, 'main');
console.log('Schema valid:', validation.valid);Enhanced R2 Service with Metadata & Multipart Upload
import { R2Service } from '@umituz/web-cloudflare/r2';
import { D1Service } from '@umituz/web-cloudflare/d1';
const r2 = new R2Service();
const d1 = new D1Service();
r2.bindBucket('assets', env.BUCKET);
r2.bindD1Service(d1);
// Upload with automatic D1 metadata save
await r2.putWithMetadata('files/document.pdf', fileData, {
customMetadata: {
contentType: 'application/pdf',
uploadedBy: 'user123',
},
saveToD1: {
table: 'files',
foreignKey: 'r2_key',
additionalData: {
filename: 'document.pdf',
size: fileData.size,
},
},
}, { binding: 'assets' });
// Multipart upload for large files
const uploadId = await r2.createMultipartUpload('large-video.mp4');
await r2.uploadPart(uploadId, 1, part1Data);
await r2.uploadPart(uploadId, 2, part2Data);
await r2.uploadPart(uploadId, 3, part3Data);
await r2.completeMultipartUpload(uploadId, [
{ partNumber: 1, etag: 'etag1' },
{ partNumber: 2, etag: 'etag2' },
{ partNumber: 3, etag: 'etag3' },
]);
// Get public/signed URLs
const publicURL = r2.getPublicURL('files/document.pdf', { binding: 'assets' });
const signedURL = await r2.getSignedURL('private/file.pdf', 3600, 'assets');Enhanced KV Service with AI Caching
import { KVService } from '@umituz/web-cloudflare/kv';
const kv = new KVService();
kv.initialize({
namespace: 'cache',
defaultTTL: 3600,
l1CacheSize: 1000,
enableL1Cache: true,
});
kv.bindNamespace('main', env.CACHE);
// AI response caching
await kv.cacheAIResponse('ai:prompt:hello', {
id: 'resp-1',
content: 'Hello!',
provider: 'workers-ai',
model: '@cf/meta/llama-3.1-8b-instruct',
usage: { promptTokens: 10, completionTokens: 20, totalTokens: 30, neurons: 5, cost: 0.0001 },
cached: false,
timestamp: Date.now(),
}, { ttl: 7200, tags: ['greeting', 'hello'] });
// Get cached AI response
const cached = await kv.getCachedAIResponse('ai:prompt:hello');
// Invalidate by tag
await kv.invalidateTagged('greeting');
// Hierarchical caching (L1 memory + L2 KV)
const data = await kv.getWithCache<DataType>('key', { ttl: 3600 });
// Cache warming
await kv.warmCache([
{ key: 'popular:1', value: data1, ttl: 3600 },
{ key: 'popular:2', value: data2, ttl: 3600 },
]);
// Cache statistics
const stats = await kv.getCacheStats();
console.log('L1 cache size:', stats.l1Size);Session Management
import { SessionManager } from '@umituz/web-cloudflare/middleware';
import { KVService } from '@umituz/web-cloudflare/kv';
import { D1Service } from '@umituz/web-cloudflare/d1';
const kv = new KVService();
const d1 = new D1Service();
const sessions = new SessionManager(kv, d1);
// Create session
const sessionId = await sessions.createSession('user123', {
ttl: 86400, // 24 hours
data: { role: 'admin', permissions: ['read', 'write'] },
});
// Validate session
const sessionData = await sessions.validateSession(sessionId);
if (sessionData) {
console.log('User:', sessionData.userId);
}
// Refresh session
await sessions.refreshSession(sessionId, 86400);
// Destroy session
await sessions.destroySession(sessionId);
// Destroy all user sessions
await sessions.destroyUserSessions('user123');Device-Based Authentication ⭐ NEW
Package: @umituz/web-cloudflare/auth
Firebase-style anonymous user authentication with device ID support and account upgrade functionality. Perfect for mobile apps where users can start using the app immediately and create an account later.
Features
- ✅ Anonymous Users - Auto-create users from device ID
- ✅ Account Upgrade - Convert anonymous users to real accounts
- ✅ Credit System - Built-in credit/quota management
- ✅ Session Management - KV + D1 hybrid session storage
- ✅ iOS/Android Ready - React Native examples included
Quick Start
import { DeviceAuthService } from '@umituz/web-cloudflare/auth';
import { createRouter, success } from '@umituz/web-cloudflare/router';
const authService = new DeviceAuthService(env.DB, env.CACHE, {
initialCredits: 10, // 10 free credits for new users
sessionTTL: 86400, // 24 hour sessions
tokenSecret: 'your-secret-key',
});
const router = createRouter()
// Register device (anonymous auth)
.post('/api/auth/register-device', async (req) => {
const { device_id } = await req.json();
const result = await authService.registerDevice({
deviceId: device_id,
deviceInfo: { model: 'iPhone', os: 'iOS' },
});
return success(result, 'Device registered');
})
// Upgrade to real account
.post('/api/auth/upgrade-account', async (req) => {
const authHeader = req.headers.get('Authorization');
const token = authHeader?.replace('Bearer ', '');
const session = await authService.validateSession(token!);
const { email, password, display_name } = await req.json();
const result = await authService.upgradeAccount(session!.user.id, {
email,
password,
displayName: display_name,
});
return success(result, 'Account upgraded');
})
// Consume credits
.post('/api/generate', async (req) => {
const authHeader = req.headers.get('Authorization');
const token = authHeader?.replace('Bearer ', '');
const session = await authService.validateSession(token!);
// Check credits
if (session!.user.creditsRemaining < 1) {
return new Response('Insufficient credits', { status: 402 });
}
// Consume credit
await authService.consumeCredits(session!.user.id, 1, 'AI generation');
// Do the work...
return success({ generated: '...' });
});iOS/React Native Integration
import { DeviceAuthService } from '@umituz/web-cloudflare/auth';
const authService = new DeviceAuthService('https://your-worker.workers.dev');
// App launch - register device
const deviceInfo = await authService.getDeviceInfo();
const response = await authService.registerDevice({
deviceId: deviceInfo.deviceId,
deviceInfo: deviceInfo,
});
// User now has 10 free credits!
console.log('Credits:', response.user.credits_remaining); // 10
// Later - upgrade to real account
await authService.upgradeAccount({
email: '[email protected]',
password: 'secure-password',
displayName: 'John Doe',
});
// User is now a real user with same ID and credits preserved!API Endpoints
| Endpoint | Method | Description |
|----------|--------|-------------|
| /api/auth/register-device | POST | Create/get anonymous user by device ID |
| /api/auth/upgrade-account | POST | Upgrade anonymous to real account |
| /api/auth/signup | POST | Create new real account |
| /api/auth/login | POST | Login with email/password |
| /api/auth/me | GET | Get current user info |
| /api/auth/refresh-token | POST | Refresh session token |
| /api/auth/logout | POST | Logout and revoke session |
| /api/auth/credits | GET | Get credit balance |
| /api/auth/credits/consume | POST | Consume credits |
| /api/auth/credits/history | GET | Get credit transaction history |
Cost Tracking & Budget Management
import { AIGatewayService } from '@umituz/web-cloudflare/ai';
const gateway = new AIGatewayService(config, env.KV);
// AI calls are automatically tracked
await gateway.route({
model: '@cf/meta/llama-3.1-8b-instruct',
prompt: 'Generate content',
});
// Get cost summary by period
const dailyCosts = await gateway.getCostSummary('day');
console.log('Daily cost:', dailyCosts.totalCost);
console.log('By model:', dailyCosts.byModel);
console.log('By provider:', dailyCosts.byProvider);
// Check budget before expensive operations
const withinBudget = gateway.enforceBudget(100); // $100 limit
if (!withinBudget) {
return json({ error: 'Budget exceeded' }, 402);
}
// Get detailed analytics
const analytics = await gateway.getAnalytics();
console.log('Cache hit rate:', analytics.cacheHitRate);
console.log('Total requests:', analytics.totalRequests);
console.log('Total neurons:', analytics.totalNeurons);📚 Subpath Exports
AI Building Blocks ⭐ NEW
// AI services
import { WorkersAIService } from '@umituz/web-cloudflare/ai';
import { EmbeddingService } from '@umituz/web-cloudflare/ai';
import { VectorizeService } from '@umituz/web-cloudflare/ai';
import { LLMStreamingService } from '@umituz/web-cloudflare/ai';
import { AIGatewayService } from '@umituz/web-cloudflare/ai';
import { aiGatewayService } from '@umituz/web-cloudflare/ai';Enhanced Core Services
// D1 with migrations, transactions, query builder
import { D1Service, D1QueryBuilder } from '@umituz/web-cloudflare/d1';
// R2 with presigned URLs, multipart upload, D1 integration
import { R2Service, R2MetadataWithD1 } from '@umituz/web-cloudflare/r2';
// KV with AI caching and hierarchical L1/L2
import { KVService, AIResponseCacheOptions } from '@umituz/web-cloudflare/kv';
// Workflows with AI pipeline templates
import { WorkflowService, WORKFLOW_TEMPLATES } from '@umituz/web-cloudflare/workflows';Middleware & Auth
// Enhanced middleware
import { requireAuth, requireAIQuota, SessionManager } from '@umituz/web-cloudflare/middleware';
import { checkUserQuota, checkAIQuota } from '@umituz/web-cloudflare/middleware';Config & Patterns
// Pre-built configs
import { aiReadyConfig, socialMediaConfig, ecommerceConfig } from '@umituz/web-cloudflare/config';
// Config builder with AI methods
import { ConfigBuilder } from '@umituz/web-cloudflare/config';
// TypeScript types
import type { WorkerConfig, AIConfig } from '@umituz/web-cloudflare/types';React Hooks ⭐ NEW
// React hooks for Cloudflare Pages
import { useAuth, useAI, useFileUpload, useWorkflow } from '@umituz/web-cloudflare/pages/react';
// React components
import { FileUpload, AIChat } from '@umituz/web-cloudflare/pages/react';
// API client utility
import { APIClient, apiClient } from '@umituz/web-cloudflare/pages/react';Multi-Tenant Support ⭐ NEW
// Multi-tenant service
import { multiTenantService, MultiTenantService } from '@umituz/web-cloudflare/multi-tenant';
// Tenant types
import type { Tenant, TenantContext, TenantRoute } from '@umituz/web-cloudflare/multi-tenant';📋 Available Pre-built Configs
aiReadyConfig⭐ NEW - Optimized for AI applicationssocialMediaConfig- Social media platforms with AIecommerceConfig- E-commerce with conservative cachingsaasConfig- SaaS with tight rate limitingapiGatewayConfig- High-throughput API gatewaycdnConfig- Static asset deliveryaiFirstConfig- Multi-provider AI setupminimalConfig- Development-friendly
🤖 AI Features
Supported AI Models
Text Generation:
@cf/meta/llama-3.1-8b-instruct- General purpose (208 neurons/1K tokens)@cf/meta/llama-3.3-70b-instruct- High quality (1110 neurons/1K tokens)@cf/mistral/mistral-7b-instruct- Fast & efficient (208 neurons/1K tokens)
Image Generation:
@cf/stabilityai/stable-diffusion-xl-base-1.0- Image generation (2778 neurons/1K tokens)
Embeddings:
@cf/openai/clip-vit-base-patch32- Text/image embeddings (52 neurons/1K tokens)
Text-to-Speech (TTS):
@cf/myshell-ai/melotts- MeloTS multilingual TTS (500 neurons/1K tokens)@cf/deepgram/aura-1- Aura TTS v1 (400 neurons/1K tokens)@cf/deepgram/aura-asteria-en- Aura Asteria English (400 neurons/1K tokens)@cf/deepgram/aura-luna-en- Aura Luna English (400 neurons/1K tokens)@cf/deepgram/aura-stella-en- Aura Stella English (400 neurons/1K tokens)
Automatic Speech Recognition (ASR):
@cf/deepgram/nova-2- Deepgram Nova-2 transcription (300 neurons/1K tokens)@cf/openai/whisper- OpenAI Whisper transcription (350 neurons/1K tokens)
AI Pipeline Templates
rag-pipeline- RAG (Retrieval-Augmented Generation)batch-embeddings- Batch embedding generationai-content-pipeline- Multi-step content generationai-multi-step-reasoning- Chain-of-thought reasoningai-data-enrichment- AI-powered data enrichment
🎵 Audio, TTS & Voice Features ⭐ NEW
Package: @umituz/web-cloudflare/ai
Comprehensive audio and voice capabilities powered by Workers AI and Cloudflare services.
Text-to-Speech (TTS)
import { WorkersAIService } from '@umituz/web-cloudflare/ai';
const ai = new WorkersAIService({ bindings: { AI: env.AI } });
// Generate speech from text
const result = await ai.generateSpeech('Hello, world!', {
model: '@cf/myshell-ai/melotts',
lang: 'en',
speed: 1.0,
pitch: 0,
emotion: 'neutral',
});
// result.audio contains base64-encoded MP3
const audioBuffer = atob(result.audio);Supported TTS Models:
@cf/myshell-ai/melotts- Multilingual TTS with emotion control@cf/deepgram/aura-1- Fast English TTS@cf/deepgram/aura-asteria-en- Female voice English@cf/deepgram/aura-luna-en- Calm female voice@cf/deepgram/aura-stella-en- Professional female voice
TTS Options:
{
model?: string; // TTS model to use
lang?: string; // Language code (en, es, fr, etc.)
voice?: string; // Voice style
speed?: number; // 0.25 - 4.0 (1.0 = normal)
pitch?: number; // -20 to 20
emotion?: string; // neutral, happy, sad, angry, etc.
}Automatic Speech Recognition (ASR)
// Transcribe audio to text
const transcription = await ai.transcribeAudio(audioBuffer, {
model: '@cf/openai/whisper',
detectLanguage: true,
});
console.log(transcription.text);
// "Hello, this is a test recording."
console.log(transcription.language);
// "en"Supported ASR Models:
@cf/openai/whisper- Multilingual transcription (99 languages)@cf/deepgram/nova-2- Fast English transcription
Audio Project Management
import { AudioProjectService } from '@umituz/web-cloudflare/ai';
const audioProject = new AudioProjectService(env.KV, env.DB);
// Create a new voice project
const project = await audioProject.createProject({
name: 'Podcast Production',
description: 'My podcast voiceovers',
userId: 'user123',
settings: {
defaultTTSEngine: 'workers-ai',
audioQuality: 'high',
outputFormat: 'mp3',
enableEmotionControl: true,
maxDuration: 600, // 10 minutes
},
});
// Add voice profiles
const narratorVoice = await audioProject.addVoiceProfile(project.id, {
name: 'Narrator',
type: 'preset',
settings: {
ttsModel: '@cf/deepgram/aura-stella-en',
language: 'en',
emotion: 'professional',
speed: 1.0,
},
});
// List projects
const projects = await audioProject.listProjects('user123');Audio Streaming & Range Requests
import { AudioStreamingService } from '@umituz/web-cloudflare/ai';
import { R2Service } from '@umituz/web-cloudflare/r2';
const r2 = new R2Service();
const streaming = new AudioStreamingService(r2);
// Handle range requests for audio streaming
export default {
async fetch(request, env) {
const url = new URL(request.url);
const key = url.pathname.slice(1);
if (request.method === 'GET') {
const rangeHeader = request.headers.get('Range');
return await streaming.handleRangeRequest(key, rangeHeader, 'audio');
}
},
};Features:
- ✅ HTTP Range requests (byte serving)
- ✅ Progressive download
- ✅ Chunked transfer encoding
- ✅ HLS playlist generation
- ✅ Waveform visualization data
- ✅ Progress callbacks
Audio Format Utilities
import {
detectAudioFormat,
extractAudioMetadata,
generateAudioWaveform,
optimizeAudioForWeb,
} from '@umituz/web-cloudflare/ai';
// Detect audio format
const format = detectAudioFormat(audioBuffer);
// "mp3", "wav", "ogg", etc.
// Extract metadata
const metadata = await extractAudioMetadata(audioBuffer);
// { format, duration, bitrate, sampleRate, channels, codec, size }
// Generate waveform for visualization
const waveform = generateAudioWaveform(audioBuffer, 1000);
// [0.5, 0.8, 0.3, ...] - 1000 samples normalized 0-1
// Optimize for web streaming
const optimized = await optimizeAudioForWeb(audioBuffer);Voice Workflows
import { WorkflowService, WORKFLOW_TEMPLATES } from '@umituz/web-cloudflare/workflows';
const workflows = new WorkflowService({ KV: env.KV, D1: env.DB });
// Voice cloning complete pipeline
await workflows.createWorkflow({
...WORKFLOW_TEMPLATES['voice-cloning-complete'],
id: 'my-voice-clone',
});
// Execute workflow
const execution = await workflows.startExecution('my-voice-clone', {
text: 'Hello, this is a test of my cloned voice!',
emotion: 'friendly',
speed: 1.0,
});
// Resume from any step (idempotent)
await workflows.resumeExecution(execution.id, 'generate-tts');Available Voice Workflows:
voice-cloning-complete- Record sample → Clone voice → Generate script → TTSaudio-processing-pipeline- Download → Validate → Convert → Optimize → Uploadbatch-tts-generation- Batch TTS with parallel processingpodcast-automation- Script → TTS → Music → Master → RSSaudiobook-creation- Parse chapters → TTS → Combine → Metadata
⚛️ React Hooks for Cloudflare Pages
Package: @umituz/web-cloudflare/pages/react
Production-ready React hooks for building Cloudflare Pages applications with Workers backend.
Authentication Hook
import { useAuth } from '@umituz/web-cloudflare/pages/react';
function App() {
const { authState, login, logout } = useAuth();
return authState.isAuthenticated ? (
<div>
<p>Welcome, {authState.user?.email}!</p>
<button onClick={logout}>Logout</button>
</div>
) : (
<button onClick={() => login({ email: '[email protected]', password: 'password' })}>
Login
</button>
);
}AI Hook
import { useAI } from '@umituz/web-cloudflare/pages/react';
function AIGenerator() {
const { aiState, generateText, streamText } = useAI();
const handleGenerate = async () => {
await generateText('Write a story about edge computing');
};
return (
<div>
<button onClick={handleGenerate}>Generate</button>
{aiState.response && <p>{aiState.response.content}</p>}
</div>
);
}File Upload Hook
import { useFileUpload } from '@umituz/web-cloudflare/pages/react';
function FileUploader() {
const { uploadState, selectFile } = useFileUpload();
return (
<div>
<input
type="file"
onChange={(e) => e.target.files && selectFile(e.target.files[0])}
/>
{uploadState.isLoading && <div>Uploading: {uploadState.progress}%</div>}
{uploadState.url && <a href={uploadState.url}>View File</a>}
</div>
);
}Components
import { FileUpload, AIChat } from '@umituz/web-cloudflare/pages/react';
// File upload with dropzone
<FileUpload
onUploadComplete={(data) => console.log('Uploaded:', data)}
maxSize={100 * 1024 * 1024}
accept="image/*"
/>
// AI chat interface
<AIChat
systemPrompt="You are a helpful assistant"
onMessageSend={(msg) => console.log('Sent:', msg)}
/>🔐 Device-Based Authentication ⭐ NEW
Package: @umituz/web-cloudflare/auth
Firebase-style anonymous user authentication with device ID support and account upgrade functionality. Perfect for mobile apps where users can start using the app immediately and create an account later.
Quick Start
import { DeviceAuthService } from '@umituz/web-cloudflare/auth';
const authService = new DeviceAuthService(env.DB, env.CACHE, {
initialCredits: 10,
sessionTTL: 86400,
});
// Register device (anonymous user with 10 free credits)
const { user, sessionToken } = await authService.registerDevice({
deviceId: 'ios-device-123',
deviceInfo: { model: 'iPhone 15', os: 'iOS 17' },
});
// User is anonymous but authenticated
console.log(user.isAnonymous); // true
console.log(user.creditsRemaining); // 10
// Later - upgrade to real account
await authService.upgradeAccount(user.id, {
email: '[email protected]',
password: 'secure-pass',
displayName: 'John Doe',
});
// User is now real, same ID preserved
console.log(user.isAnonymous); // false
console.log(user.email); // '[email protected]'
console.log(user.creditsRemaining); // Still 10 (preserved!)Use Cases
- Mobile Apps - Users start immediately, sign up later
- Freemium Models - 10 free credits, then pay
- Progressive Web Apps - Anonymous browsing → account creation
- Gaming - Guest play → account sync
🏢 Multi-Tenant Support
Package: @umituz/web-cloudflare/multi-tenant
Manage multiple D1, R2, KV, and Vectorize bindings for multi-tenant applications.
Setup Tenants
import { multiTenantService } from '@umituz/web-cloudflare/multi-tenant';
// Register tenant
const tenant = await multiTenantService.registerTenant({
name: 'Acme Corp',
slug: 'acme',
domain: 'acme.example.com',
});
// Bind resources
multiTenantService.bindD1(tenant.id, 'DB', env.DB);
multiTenantService.bindR2(tenant.id, 'STORAGE', env.STORAGE);
multiTenantService.bindKV(tenant.id, 'CACHE', env.CACHE);Tenant Routing
// Set routing strategy
multiTenantService.setTenantRoute(tenant.id, {
hostname: 'acme.example.com',
});
// Resolve tenant from request
export default {
async fetch(request, env, ctx) {
const result = await multiTenantService.resolveTenant(request);
if (!result) return new Response('Not found', { status: 404 });
const context = multiTenantService.getTenantContext(result.tenant.id);
const db = context.d1?.get('DB');
// Use tenant-specific database
const data = await db.prepare('SELECT * FROM users').all();
return Response.json(data);
},
};Use Cases
- SaaS Platforms: Isolated databases per customer
- White-Label Apps: Custom domains per brand
- Multi-Region: Region-specific routing
- Environment Isolation: Dev/Staging/Prod separation
🔧 Wrangler CLI Integration
import { WranglerService } from '@umituz/web-cloudflare/wrangler';
const wrangler = new WranglerService();
// Authentication
await wrangler.login();
const authInfo = await wrangler.whoami();
// Project management
await wrangler.init('my-worker', 'typescript');
await wrangler.deploy({ env: 'production' });
// Start development server
await wrangler.dev({ port: 8787, local: true });
// KV operations
const namespace = await wrangler.kvNamespaceCreate('MY_KV');
await wrangler.kvKeyPut(namespace.id, 'key', 'value');
const value = await wrangler.kvKeyGet(namespace.id, 'key');
// R2 operations
await wrangler.r2BucketCreate('my-bucket');
const buckets = await wrangler.r2BucketList();
await wrangler.r2ObjectPut('my-bucket', 'file.txt', './local-file.txt');
// D1 operations
const db = await wrangler.d1Create('my-database');
const result = await wrangler.d1Execute('my-database', 'SELECT * FROM users');
// Secrets management
await wrangler.secretPut('API_KEY', 'secret-value');
const secrets = await wrangler.secretList();
// Monitoring
await wrangler.tail({ format: 'json' });
// Version management
const versions = await wrangler.versionsList();
await wrangler.versionsRollback(versions[0].id);📁 Package Structure
@umituz/web-cloudflare/
├── src/
│ ├── config/ # Config patterns and types
│ ├── domains/ # Domain-driven design structure
│ │ ├── ai/ # ⭐ NEW AI building blocks
│ │ │ ├── entities/
│ │ │ ├── services/
│ │ │ │ ├── workers-ai.service.ts
│ │ │ │ ├── embedding.service.ts
│ │ │ │ ├── vectorize.service.ts
│ │ │ │ ├── llm-streaming.service.ts
│ │ │ │ └── ai-gateway.service.ts
│ │ │ └── types/
│ │ ├── workers/ # Workers domain
│ │ ├── kv/ # KV storage domain
│ │ ├── r2/ # R2 storage domain
│ │ ├── d1/ # D1 database domain
│ │ ├── images/ # Images optimization domain
│ │ ├── analytics/ # Analytics domain
│ │ ├── workflows/ # Workflows domain
│ │ ├── pages/ # Pages deployment domain
│ │ ├── wrangler/ # Wrangler CLI domain
│ │ ├── middleware/ # Middleware domain
│ │ ├── auth/ # ⭐ NEW Device-based authentication
│ │ └── multi-tenant/ # ⭐ NEW Multi-tenant support
│ ├── infrastructure/
│ │ ├── router/ # Express-like router
│ │ ├── middleware/ # Middleware collection
│ │ └── utils/ # Helper functions
│ └── presentation/
│ └── hooks/ # React hooks
└── package.json🎯 Use Cases
AI-Powered Applications
- RAG Applications: Document search, knowledge bases, Q&A systems
- Content Generation: Blogs, social media, marketing copy
- Data Enrichment: Entity extraction, classification, summarization
- Multi-Step Reasoning: Complex problem solving, analysis tasks
E-Commerce
- Product recommendations with AI
- Dynamic pricing
- Inventory forecasting
- Customer support chatbots
SaaS
- AI-powered feature recommendations
- Usage analytics with AI insights
- Automated content moderation
- Intelligent search
📊 Performance Benchmarks
| Operation | Speed | Improvement | |-----------|-------|-------------| | Route matching | 0.1ms | 80% faster | | Cache hit (L1) | <0.01ms | 99% faster | | AI response caching | Variable | 90%+ cost reduction | | Workflow step execution | 30ms | 40% faster | | D1 transaction | Variable | ACID compliant | | Memory usage | Stable | No leaks |
📝 Version Strategy
Important: This package follows a patch-only versioning strategy. Only the patch version will increment (e.g., 1.5.0 → 1.5.1 → 1.5.2). Major version bumps (2.0.0) will never occur. This ensures stability and prevents breaking changes from version updates.
📄 License
MIT
🤝 Contributing
Contributions are welcome!
🔗 Links
- GitHub: https://github.com/umituz/web-cloudflare
- NPM: https://www.npmjs.com/package/@umituz/web-cloudflare
- Issues: https://github.com/umituz/web-cloudflare/issues
Made with ❤️ by umituz
