@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';
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);
const worker = new WorkerService({
...aiReadyConfig,
env: {
KV: env.KV,
R2: env.R2,
D1: env.D1,
AI: env.AI,
VECTORIZE: env.VECTORIZE,
},
});
const router = createRouter()
.use(cors)
.use((req) => requireAIQuota(req, {
enabled: true,
quota: 10000000,
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,
},
});
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)
.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);
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 },
}]);
}
router.post('/api/rag', async (req) => {
const { query } = await req.json();
const queryEmbedding = await embeddings.generateTextEmbedding(query);
const ragResult = await vectorize.ragQuery(
queryEmbedding,
docs.map(d => ({ id: d.id, text: d.text, metadata: { source: d.source } })),
{ topK: 3 }
);
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,
});
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'] },
],
});
const execution = await workflows.startExecution('blog-post-generator', {
topic: 'Cloudflare Workers AI',
tone: 'professional',
});
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);
await d1.createTable('_migrations', {
id: 'TEXT PRIMARY KEY',
name: 'TEXT NOT NULL',
sql: 'TEXT NOT NULL',
applied_at: 'INTEGER',
rolled_back_at: 'INTEGER',
}, 'main');
await d1.runMigration(`
CREATE TABLE users (
id TEXT PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
created_at INTEGER
)
`, 'main');
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');
await d1.runInTransaction(async (txn) => {
await txn.query(`INSERT INTO users (id, email) VALUES (?, ?)`, ['user1', 'user1@example.com']);
await txn.query(`INSERT INTO profiles (user_id, bio) VALUES (?, ?)`, ['user1', 'Bio']);
await txn.commit();
}, 'main');
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);
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' });
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' },
]);
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);
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'] });
const cached = await kv.getCachedAIResponse('ai:prompt:hello');
await kv.invalidateTagged('greeting');
const data = await kv.getWithCache<DataType>('key', { ttl: 3600 });
await kv.warmCache([
{ key: 'popular:1', value: data1, ttl: 3600 },
{ key: 'popular:2', value: data2, ttl: 3600 },
]);
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);
const sessionId = await sessions.createSession('user123', {
ttl: 86400,
data: { role: 'admin', permissions: ['read', 'write'] },
});
const sessionData = await sessions.validateSession(sessionId);
if (sessionData) {
console.log('User:', sessionData.userId);
}
await sessions.refreshSession(sessionId, 86400);
await sessions.destroySession(sessionId);
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,
sessionTTL: 86400,
tokenSecret: 'your-secret-key',
});
const router = createRouter()
.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');
})
.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');
})
.post('/api/generate', async (req) => {
const authHeader = req.headers.get('Authorization');
const token = authHeader?.replace('Bearer ', '');
const session = await authService.validateSession(token!);
if (session!.user.creditsRemaining < 1) {
return new Response('Insufficient credits', { status: 402 });
}
await authService.consumeCredits(session!.user.id, 1, 'AI generation');
return success({ generated: '...' });
});
iOS/React Native Integration
import { DeviceAuthService } from '@umituz/web-cloudflare/auth';
const authService = new DeviceAuthService('https://your-worker.workers.dev');
const deviceInfo = await authService.getDeviceInfo();
const response = await authService.registerDevice({
deviceId: deviceInfo.deviceId,
deviceInfo: deviceInfo,
});
console.log('Credits:', response.user.credits_remaining);
await authService.upgradeAccount({
email: 'user@example.com',
password: 'secure-password',
displayName: 'John Doe',
});
API Endpoints
/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);
await gateway.route({
model: '@cf/meta/llama-3.1-8b-instruct',
prompt: 'Generate content',
});
const dailyCosts = await gateway.getCostSummary('day');
console.log('Daily cost:', dailyCosts.totalCost);
console.log('By model:', dailyCosts.byModel);
console.log('By provider:', dailyCosts.byProvider);
const withinBudget = gateway.enforceBudget(100);
if (!withinBudget) {
return json({ error: 'Budget exceeded' }, 402);
}
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
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
import { D1Service, D1QueryBuilder } from '@umituz/web-cloudflare/d1';
import { R2Service, R2MetadataWithD1 } from '@umituz/web-cloudflare/r2';
import { KVService, AIResponseCacheOptions } from '@umituz/web-cloudflare/kv';
import { WorkflowService, WORKFLOW_TEMPLATES } from '@umituz/web-cloudflare/workflows';
Middleware & Auth
import { requireAuth, requireAIQuota, SessionManager } from '@umituz/web-cloudflare/middleware';
import { checkUserQuota, checkAIQuota } from '@umituz/web-cloudflare/middleware';
Config & Patterns
import { aiReadyConfig, socialMediaConfig, ecommerceConfig } from '@umituz/web-cloudflare/config';
import { ConfigBuilder } from '@umituz/web-cloudflare/config';
import type { WorkerConfig, AIConfig } from '@umituz/web-cloudflare/types';
React Hooks ā NEW
import { useAuth, useAI, useFileUpload, useWorkflow } from '@umituz/web-cloudflare/pages/react';
import { FileUpload, AIChat } from '@umituz/web-cloudflare/pages/react';
import { APIClient, apiClient } from '@umituz/web-cloudflare/pages/react';
Multi-Tenant Support ā NEW
import { multiTenantService, MultiTenantService } from '@umituz/web-cloudflare/multi-tenant';
import type { Tenant, TenantContext, TenantRoute } from '@umituz/web-cloudflare/multi-tenant';
š Available Pre-built Configs
aiReadyConfig ā NEW - Optimized for AI applications
socialMediaConfig - Social media platforms with AI
ecommerceConfig - E-commerce with conservative caching
saasConfig - SaaS with tight rate limiting
apiGatewayConfig - High-throughput API gateway
cdnConfig - Static asset delivery
aiFirstConfig - Multi-provider AI setup
minimalConfig - 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 generation
ai-content-pipeline - Multi-step content generation
ai-multi-step-reasoning - Chain-of-thought reasoning
ai-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 } });
const result = await ai.generateSpeech('Hello, world!', {
model: '@cf/myshell-ai/melotts',
lang: 'en',
speed: 1.0,
pitch: 0,
emotion: 'neutral',
});
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;
lang?: string;
voice?: string;
speed?: number;
pitch?: number;
emotion?: string;
}
Automatic Speech Recognition (ASR)
const transcription = await ai.transcribeAudio(audioBuffer, {
model: '@cf/openai/whisper',
detectLanguage: true,
});
console.log(transcription.text);
console.log(transcription.language);
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);
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,
},
});
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,
},
});
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);
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';
const format = detectAudioFormat(audioBuffer);
const metadata = await extractAudioMetadata(audioBuffer);
const waveform = generateAudioWaveform(audioBuffer, 1000);
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 });
await workflows.createWorkflow({
...WORKFLOW_TEMPLATES['voice-cloning-complete'],
id: 'my-voice-clone',
});
const execution = await workflows.startExecution('my-voice-clone', {
text: 'Hello, this is a test of my cloned voice!',
emotion: 'friendly',
speed: 1.0,
});
await workflows.resumeExecution(execution.id, 'generate-tts');
Available Voice Workflows:
voice-cloning-complete - Record sample ā Clone voice ā Generate script ā TTS
audio-processing-pipeline - Download ā Validate ā Convert ā Optimize ā Upload
batch-tts-generation - Batch TTS with parallel processing
podcast-automation - Script ā TTS ā Music ā Master ā RSS
audiobook-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: 'user@example.com', 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';
<FileUpload
onUploadComplete={(data) => console.log('Uploaded:', data)}
maxSize={100 * 1024 * 1024}
accept="image/*"
/>
<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,
});
const { user, sessionToken } = await authService.registerDevice({
deviceId: 'ios-device-123',
deviceInfo: { model: 'iPhone 15', os: 'iOS 17' },
});
console.log(user.isAnonymous);
console.log(user.creditsRemaining);
await authService.upgradeAccount(user.id, {
email: 'user@example.com',
password: 'secure-pass',
displayName: 'John Doe',
});
console.log(user.isAnonymous);
console.log(user.email);
console.log(user.creditsRemaining);
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';
const tenant = await multiTenantService.registerTenant({
name: 'Acme Corp',
slug: 'acme',
domain: 'acme.example.com',
});
multiTenantService.bindD1(tenant.id, 'DB', env.DB);
multiTenantService.bindR2(tenant.id, 'STORAGE', env.STORAGE);
multiTenantService.bindKV(tenant.id, 'CACHE', env.CACHE);
Tenant Routing
multiTenantService.setTenantRoute(tenant.id, {
hostname: 'acme.example.com',
});
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');
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();
await wrangler.login();
const authInfo = await wrangler.whoami();
await wrangler.init('my-worker', 'typescript');
await wrangler.deploy({ env: 'production' });
await wrangler.dev({ port: 8787, local: true });
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' });
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
| 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
Made with ā¤ļø by umituz