Skip to content

umituz/web-cloudflare

Repository files navigation

@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', 'user1@example.com']);
  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: 'user@example.com',
  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 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)

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

βš›οΈ 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';

// 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: 'user@example.com',
  password: 'secure-pass',
  displayName: 'John Doe',
});

// User is now real, same ID preserved
console.log(user.isAnonymous); // false
console.log(user.email); // 'user@example.com'
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


Made with ❀️ by umituz

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors