### Install Project Dependencies Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md Installs the necessary project dependencies using npm. This is typically the first step before configuring or deploying the worker. ```bash npm install ``` -------------------------------- ### Start Local Development Server Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md Starts a local development server for the Cloudflare Worker using the 'wrangler dev' command. This allows for testing the worker locally before deploying. ```bash npm run dev ``` -------------------------------- ### Basic API Call Example Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md A JavaScript example demonstrating how to fetch data from an API endpoint and parse the JSON response. This illustrates a typical client-side interaction with an API that the worker might be caching. ```javascript // Your API endpoint fetch('https://api.yourdomain.com/users') .then(response => response.json()) .then(data => console.log(data)); ``` -------------------------------- ### tRPC Client Setup and Component Integration in TypeScript Source: https://context7.com/jjwprotozoa/dmoc/llms.txt Sets up the tRPC client and integrates it with React Query for type-safe API operations. Demonstrates usage in a React component to fetch and display manifest data. Includes default options for queries like staleTime and refetchOnWindowFocus. ```typescript // src/app/providers.tsx 'use client'; import { trpc, trpcClient } from '@/lib/trpc'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useState } from 'react'; export function Providers({ children }: { children: React.ReactNode }) { const [queryClient] = useState(() => new QueryClient({ defaultOptions: { queries: { staleTime: 60 * 1000, refetchOnWindowFocus: false, }, }, })); return ( {children} ); } // Usage in components function ManifestsList() { const { data: manifests, isLoading, error } = trpc.manifest.getAll.useQuery({ status: 'IN_PROGRESS', }); if (isLoading) return
Loading...
; if (error) return
Error: {error.message}
; return ( ); } ``` -------------------------------- ### Authentication System Setup and Usage in TypeScript Source: https://context7.com/jjwprotozoa/dmoc/llms.txt Handles user authentication and session management using NextAuth. Provides functions to sign in users, retrieve current user session details on the server-side, and check user roles like ADMIN. It ensures tenant isolation and role-based access control. ```typescript // src/lib/auth.ts import { authOptions } from '@/lib/auth'; import { getServerSession } from 'next-auth'; // Sign in a user async function signIn(email: string, password: string) { const result = await signIn('credentials', { email, password, redirect: false, }); if (result?.error) { throw new Error('Invalid credentials'); } return result; } // Get current session on server side async function getCurrentUser() { const session = await getServerSession(authOptions); if (!session) { throw new Error('Unauthorized'); } return { id: session.user.id, email: session.user.email, role: session.user.role, tenantId: session.user.tenantId, tenantSlug: session.user.tenantSlug, }; } // Check if user is admin function isAdmin(session: Session) { return session.user.role === 'ADMIN'; } ``` -------------------------------- ### PWA Configuration and Features (TypeScript) Source: https://context7.com/jjwprotozoa/dmoc/llms.txt Implements Progressive Web App (PWA) capabilities for offline-first functionality. It includes PWA configuration for app metadata, icons, and theme colors, as well as Content Security Policy (CSP) generation. A service worker configuration is provided for caching API requests and other assets, leveraging `next-pwa` for automatic setup. ```typescript // src/lib/pwa.ts import { PWA_CONFIG, generateNonce, getCSPHeader } from '@/lib/pwa'; // Install prompt hook import { useInstallPrompt } from '@/hooks/useInstallPrompt'; function InstallButton() { const { canInstall, installApp } = useInstallPrompt(); if (!canInstall) return null; return ( ); } // PWA configuration const pwaConfig = { name: 'LogisticsController', shortName: 'LogisticsCtrl', description: 'Secure Transport & Manifest Management PWA', themeColor: '#3b82f6', backgroundColor: '#ffffff', display: 'standalone', icons: [ { src: '/icon-192.png', sizes: '192x192', type: 'image/png' }, { src: '/icon-512.png', sizes: '512x512', type: 'image/png' }, ], }; // Content Security Policy const nonce = generateNonce(); const cspHeader = getCSPHeader(nonce); // Service worker for offline support // Automatically configured via next-pwa const swConfig = { dest: 'public', register: true, skipWaiting: true, runtimeCaching: [ { urlPattern: /^https:\/\/dmoc\.example\.com\/api\/.*/, handler: 'NetworkFirst', options: { cacheName: 'api-cache', expiration: { maxEntries: 50, maxAgeSeconds: 300, }, }, }, ], }; ``` -------------------------------- ### Manifest Management API Operations in TypeScript Source: https://context7.com/jjwprotozoa/dmoc/llms.txt Provides client-side examples for interacting with the manifest management API using tRPC mutations and queries. Demonstrates creating new manifests, fetching manifests with filters, updating manifest status, and retrieving a specific manifest with its associated stops and company information. ```typescript // Client usage const { mutate: createManifest } = trpc.manifest.create.useMutation({ onSuccess: (data) => { console.log('Manifest created:', data.id); }, onError: (error) => { console.error('Failed to create manifest:', error.message); }, }); createManifest({ companyId: 'cly1234567890', title: 'Downtown Deliveries - Morning Route', scheduledAt: new Date('2025-10-16T08:00:00Z'), stops: [ { order: 1, location: { lat: 40.7128, lng: -74.0060 }, }, { order: 2, location: { lat: 40.7589, lng: -73.9851 }, }, { order: 3, location: { lat: 40.7614, lng: -73.9776 }, }, ], }); // Fetch manifests with filtering const { data: activeManifests } = trpc.manifest.getAll.useQuery({ companyId: 'cly1234567890', status: 'IN_PROGRESS', }); // Update manifest status const { mutate: updateStatus } = trpc.manifest.updateStatus.useMutation(); updateStatus({ id: 'clm1234567890', status: 'COMPLETED', }); // Get manifest by ID with stops and company info const { data: manifest } = trpc.manifest.getById.useQuery({ id: 'clm1234567890', }); console.log(manifest?.stops); // Ordered array of stops console.log(manifest?.company.name); // Company information ``` -------------------------------- ### Process WhatsApp Webhook Events (Bash & TypeScript) Source: https://context7.com/jjwprotozoa/dmoc/llms.txt Shows how to send messages and media from WhatsApp to the DMOC API via a webhook and how the system processes these events from a queue. It includes example cURL request and TypeScript code for handling image media and updating event statuses. Real-time notifications for new messages are also configured. ```bash # POST /api/webhook/whatsapp curl -X POST https://dmoc.example.com/api/webhook/whatsapp \ -H "Content-Type: application/json" \ -H "x-webhook-secret: your-whatsapp-secret" \ -d '{ "message": "Driver reported delay at stop 3", "phone": "+1234567890", "timestamp": "2025-10-15T14:35:00Z", "imageUrl": "https://whatsapp-media.example.com/image123.jpg", "mediaType": "image" }' # Response { "success": true, "webhookId": "clw1234567890" } ``` ```typescript // Process webhook events from queue const webhookEvents = await db.webhookEvent.findMany({ where: { status: 'PENDING', source: 'whatsapp' }, }); for (const event of webhookEvents) { const payload = JSON.parse(event.payload); // Process WhatsApp message if (payload.mediaType === 'image' && payload.imageUrl) { // Download and process image await processWhatsAppImage(payload.imageUrl, payload.phone); } // Mark as processed await db.webhookEvent.update({ where: { id: event.id }, data: { status: 'COMPLETED', processedAt: new Date(), }, }); } // Real-time notification socket.on('webhook:new', (event) => { if (event.source === 'whatsapp') { showNotification(`New message from ${event.payload.phone}`); } }); ``` -------------------------------- ### Set Custom Cache TTL via Wrangler Secret Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md An example of how to set a custom cache TTL (Time To Live) for the worker using the 'wrangler secret put' command. This allows overriding the default TTL defined in 'wrangler.toml'. ```bash wrangler secret put CACHE_TTL # Enter: 600 (for 10 minutes) ``` -------------------------------- ### Get Device Locations and History - TypeScript Source: https://context7.com/jjwprotozoa/dmoc/llms.txt Fetches real-time location data for GPS devices and retrieves historical location data for a specified device. It uses TRPC queries to interact with the backend. Ensure the TRPC client is properly configured and the 'tracking' module is available. ```typescript // Get all devices with latest location const { data: devices } = trpc.tracking.getDevices.useQuery(); devices?.forEach(device => { const latestPing = device.locationPings[0]; console.log(`Device ${device.externalId} at:`, { lat: latestPing.lat, lng: latestPing.lng, speed: latestPing.speed, heading: latestPing.heading, }); }); // Fetch location history for a device const { data: history } = trpc.tracking.getLocationHistory.useQuery({ deviceId: 'clx1234567890', from: new Date('2025-10-15T00:00:00Z'), to: new Date('2025-10-15T23:59:59Z'), limit: 500, }); // Get latest pings across multiple devices const { data: latestPings } = trpc.tracking.getLatestPings.useQuery({ deviceIds: ['clx1234567890', 'clx9876543210'], }); // Render on map latestPings?.forEach(ping => { addMarkerToMap({ position: [ping.lat, ping.lng], label: ping.device.externalId, speed: ping.speed, }); }); ``` -------------------------------- ### Deploy Worker to Production Environment Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md Deploys the Cloudflare Worker to the production environment using the 'wrangler deploy' command with the '--env production' flag. ```bash wrangler deploy --env production ``` -------------------------------- ### Run Project Tests Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md Executes the project's test suite using npm. This is crucial for ensuring the worker functions as expected. ```bash npm run test ``` -------------------------------- ### Deploy Worker to Staging and Production Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md Commands to deploy the Cloudflare Worker to staging and production environments using npm scripts. These scripts likely wrap 'wrangler deploy' commands. ```bash # Deploy to staging npm run deploy:staging # Deploy to production npm run deploy:production ``` -------------------------------- ### Deploy Worker to Staging Environment Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md Deploys the Cloudflare Worker to the staging environment using the 'wrangler deploy' command with the '--env staging' flag. ```bash wrangler deploy --env staging ``` -------------------------------- ### S3/MinIO File Upload and Retrieval (TypeScript) Source: https://context7.com/jjwprotozoa/dmoc/llms.txt Handles uploading files to and downloading files from S3-compatible storage like MinIO. It defines functions for uploading document buffers and downloading them by their key. Configuration is expected in environment variables. The `uploadOffenseEvidence` function demonstrates a complete upload workflow including saving attachment records to a database. ```typescript // src/lib/s3.ts import { uploadFile, getFile, s3Client } from '@/lib/s3'; // Upload file buffer async function uploadDocument( file: Buffer, entityType: string, entityId: string, fileName: string ) { const key = `${entityType}/${entityId}/${Date.now()}-${fileName}`; const url = await uploadFile(key, file, 'application/pdf'); return url; // Returns public URL } // Download file async function downloadDocument(url: string) { const key = url.split('/').slice(-3).join('/'); const buffer = await getFile(key); return buffer; } // Configuration in .env const s3Config = { S3_ENDPOINT: 'https://minio.example.com', S3_REGION: 'us-east-1', S3_BUCKET: 'dmoc-uploads', S3_ACCESS_KEY_ID: 'minioadmin', S3_SECRET_ACCESS_KEY: 'minioadmin', }; // Complete upload workflow async function uploadOffenseEvidence(offenseId: string, file: File) { // Convert to buffer const arrayBuffer = await file.arrayBuffer(); const buffer = Buffer.from(arrayBuffer); // Upload to S3 const key = `offenses/${offenseId}/${Date.now()}-${file.name}`; const url = await uploadFile(key, buffer, file.type); // Save attachment record await db.attachment.create({ data: { entityType: 'offense', entityId: offenseId, url, mime: file.type, meta: { fileName: file.name, size: file.size }, }, }); return url; } ``` -------------------------------- ### Connect to Socket.IO Server for Real-time Updates (TypeScript) Source: https://context7.com/jjwprotozoa/dmoc/llms.txt Establishes a WebSocket connection using Socket.IO to receive real-time updates such as location pings, manifest changes, and new webhook events. It handles connection status and cleans up event listeners on component unmount. Dependencies include Next.js authentication and a custom useSocket hook. ```typescript // src/hooks/useSocket.ts - Connect to socket server import { useSocket } from '@/hooks/useSocket'; import { useSession } from 'next-auth/react'; function DashboardComponent() { const { data: session } = useSession(); const { socket, isConnected } = useSocket(session?.user.tenantSlug); useEffect(() => { if (!socket || !isConnected) return; // Listen for location pings socket.on('ping:new', (ping) => { console.log('New location ping:', { deviceId: ping.device.externalId, lat: ping.lat, lng: ping.lng, speed: ping.speed, }); updateMapMarker(ping.device.externalId, ping); }); // Listen for manifest updates socket.on('manifest:update', (manifest) => { console.log('Manifest updated:', manifest.id, manifest.status); refetchManifests(); }); // Listen for webhook events socket.on('webhook:new', (event) => { console.log('Webhook received:', event.source, event.payload); }); return () => { socket.off('ping:new'); socket.off('manifest:update'); socket.off('webhook:new'); }; }, [socket, isConnected]); if (!isConnected) { return
Connecting to real-time server...
; } return
Real-time updates active
; } // Join specific rooms for filtered updates function ManifestDetailPage({ manifestId }: { manifestId: string }) { const { socket, isConnected } = useSocket(); useEffect(() => { if (socket && isConnected) { socket.emit('join-manifest', manifestId); return () => { socket.emit('leave-manifest', manifestId); }; } }, [socket, isConnected, manifestId]); } ``` -------------------------------- ### Tenant Management Operations - TypeScript Source: https://context7.com/jjwprotozoa/dmoc/llms.txt Provides functionality for administering multi-tenant organizations, including creating, retrieving, and updating tenant information. This API is intended for admin use only. It relies on TRPC for mutations and queries, and expects valid tenant data structures. ```typescript // Create a new tenant const { mutate: createTenant } = trpc.tenants.create.useMutation(); createTenant({ name: 'Acme Logistics', slug: 'acme-logistics', settings: { timezone: 'America/New_York', features: ['gps_tracking', 'offense_reporting'], }, }); // Get all tenants with counts const { data: tenants } = trpc.tenants.getAll.useQuery(); tenants?.forEach(tenant => { console.log({ name: tenant.name, slug: tenant.slug, userCount: tenant._count.users, deviceCount: tenant._count.devices, organizations: tenant.organizations.map(org => ({ name: org.name, companyCount: org.companies.length, })), }); }); // Get detailed tenant info const { data: tenant } = trpc.tenants.getById.useQuery({ id: 'clt1234567890', }); tenant?.organizations.forEach(org => { org.companies.forEach(company => { console.log({ companyName: company.name, drivers: company._count.drivers, vehicles: company._count.vehicles, manifests: company._count.manifests, }); }); }); // Update tenant settings const { mutate: updateTenant } = trpc.tenants.update.useMutation(); updateTenant({ id: 'clt1234567890', settings: { timezone: 'America/Los_Angeles', maxDevices: 100, }, }); ``` -------------------------------- ### Prisma ORM Usage for Data Querying in DMOC Source: https://context7.com/jjwprotozoa/dmoc/llms.txt Demonstrates how to interact with the database using Prisma ORM in a TypeScript environment. This snippet shows a typical query to find a specific manifest record and include its associated company and ordered stops, highlighting Prisma's capability for relational data fetching. ```typescript // Usage with Prisma client import { db } from '@/lib/db'; const manifest = await db.manifest.findUnique({ where: { id: 'clm1234567890' }, include: { company: true, stops: { orderBy: { order: 'asc' } }, }, }); ``` -------------------------------- ### Enable Debug Logging in Wrangler Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md Enables debug-level logging for the Cloudflare Worker by setting the log level in 'wrangler.toml'. This provides more detailed information for troubleshooting. ```toml [log] level = "debug" ``` -------------------------------- ### TypeScript Interfaces for DMOC Database Models Source: https://context7.com/jjwprotozoa/dmoc/llms.txt Defines the structure of key data models in the DMOC application, including Tenant, Organization, Company, Manifest, and Device. These interfaces represent the entities managed within the multi-tenant database schema and are used for type checking and data representation. ```typescript // Key models interface Tenant { id: string; name: string; slug: string; // Unique tenant identifier settings: Record; organizations: Organization[]; users: User[]; devices: Device[]; } interface Organization { id: string; tenantId: string; name: string; companies: Company[]; } interface Company { id: string; orgId: string; name: string; drivers: Driver[]; vehicles: Vehicle[]; manifests: Manifest[]; } interface Manifest { id: string; companyId: string; title: string; status: 'SCHEDULED' | 'IN_PROGRESS' | 'COMPLETED' | 'CANCELLED'; scheduledAt: Date; stops: Stop[]; } interface Device { id: string; tenantId: string; externalId: string; // Traccar device ID lastPingAt: Date | null; locationPings: LocationPing[]; } ``` -------------------------------- ### Configure API Routes for Worker Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md Specifies the API endpoints that the Cloudflare Worker should intercept and cache. Edit the 'wrangler.toml' file to include your target API routes. ```toml routes = [ "api.yourdomain.com/api/*", "yourdomain.com/api/v1/*" ] ``` -------------------------------- ### View Worker Logs via Wrangler CLI Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md Streams live logs from the Cloudflare Worker to the terminal using the 'wrangler tail' command. This is useful for real-time debugging. ```bash wrangler tail ``` -------------------------------- ### File Upload and Attachment Management - TypeScript Source: https://context7.com/jjwprotozoa/dmoc/llms.txt Handles S3-compatible file uploads and manages entity attachments. This snippet demonstrates uploading a file by converting it to base64 and attaching it to an entity, as well as retrieving existing attachments. It uses TRPC mutations and queries and requires a File object and entity details. ```typescript // Upload a file const { mutate: uploadFile } = trpc.uploads.uploadFile.useMutation({ onSuccess: (attachment) => { console.log('File uploaded:', attachment.url); }, }); // Convert file to base64 and upload async function handleFileUpload(file: File, entityType: string, entityId: string) { const reader = new FileReader(); reader.onload = () => { const base64 = reader.result?.toString().split(',')[1]; if (base64) { uploadFile({ entityType, entityId, fileName: file.name, mimeType: file.type, data: base64, }); } }; reader.readAsDataURL(file); } // Usage: attach image to offense const fileInput = document.getElementById('file-input') as HTMLInputElement; const file = fileInput.files?.[0]; if (file) { await handleFileUpload(file, 'offense', 'clo1234567890'); } // Get all attachments for an entity const { data: attachments } = trpc.uploads.getAttachments.useQuery({ entityType: 'offense', entityId: 'clo1234567890', }); attachments?.forEach(att => { console.log({ url: att.url, mime: att.mime, fileName: att.meta.fileName, size: att.meta.size, }); }); ``` -------------------------------- ### Cache Key Generation Pattern Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md Illustrates the pattern used to generate cache keys. The key combines the cache version, HTTP method, pathname, and query parameters to ensure unique caching for different requests. ```plaintext {CACHE_VERSION}:{METHOD}:{PATHNAME}{SEARCH} Example: v1:GET:/api/users?page=1&limit=10 ``` -------------------------------- ### Create and Query Offenses - TypeScript Source: https://context7.com/jjwprotozoa/dmoc/llms.txt Allows for the creation of driver and vehicle violations (offenses) and querying them with various filters. It leverages TRPC mutations for creation and queries for retrieval. Requires valid driver, vehicle IDs, and offense details. ```typescript // Create an offense const { mutate: createOffense } = trpc.offenses.create.useMutation({ onSuccess: (offense) => { console.log('Offense created:', offense.id); // offense includes driver and vehicle relations }, }); createOffense({ driverId: 'cld1234567890', vehicleId: 'clv1234567890', kind: 'SPEEDING', severity: 'MAJOR', notes: 'Exceeded speed limit by 25 mph on Highway 101', }); // Query offenses with filters const { data: offenses } = trpc.offenses.getAll.useQuery({ driverId: 'cld1234567890', severity: 'CRITICAL', }); // Get all offenses for a vehicle const { data: vehicleOffenses } = trpc.offenses.getAll.useQuery({ vehicleId: 'clv1234567890', }); // Display offense details vehicleOffenses?.forEach(offense => { console.log({ kind: offense.kind, // SPEEDING, PARKING_VIOLATION, etc. severity: offense.severity, // MINOR, MODERATE, MAJOR, CRITICAL driver: offense.driver?.name, vehicle: offense.vehicle?.plate, notes: offense.notes, createdAt: offense.createdAt, }); }); ``` -------------------------------- ### Configure Custom Domains in Wrangler Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md Configures custom domains for the production environment within the 'wrangler.toml' file. This allows the worker to be served from a specific domain. ```toml [[env.production.routes]] pattern = "api.yourdomain.com/*" custom_domain = true ``` -------------------------------- ### Perform Type Checking Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md Runs a type-checking process for the project, likely using TypeScript or a similar tool, to catch type-related errors. ```bash npm run type-check ``` -------------------------------- ### Ingest Traccar GPS Data via Webhook (Bash & TypeScript) Source: https://context7.com/jjwprotozoa/dmoc/llms.txt Demonstrates how to send GPS tracking data to the DMOC API using a cURL command and outlines the server-side processing in TypeScript. The webhook validates a secret, creates location records, updates device status, and emits real-time notifications. It requires a pre-existing device in the database. ```bash # POST /api/webhook/traccar curl -X POST https://dmoc.example.com/api/webhook/traccar \ -H "Content-Type: application/json" \ -H "x-webhook-secret: your-traccar-secret" \ -d '{ "deviceId": "tracker-12345", "latitude": 40.7128, "longitude": -74.0060, "speed": 45.5, "course": 180, "timestamp": "2025-10-15T14:30:00Z" }' # Response { "success": true, "pingId": "clp1234567890" } ``` ```typescript // Traccar webhook configuration const traccarConfig = { webhookUrl: 'https://dmoc.example.com/api/webhook/traccar', headers: { 'x-webhook-secret': process.env.TRACCAR_WEBHOOK_SECRET, }, events: ['position'], }; // Device must exist in database with matching externalId await db.device.create({ data: { tenantId: 'clt1234567890', externalId: 'tracker-12345', }, }); // Webhook automatically: // 1. Validates secret // 2. Creates LocationPing record // 3. Updates Device lastPingAt // 4. Emits real-time Socket.IO event to tenant room // 5. Returns pingId for tracking ``` -------------------------------- ### Enable Analytics in Wrangler Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md Enables analytics collection for the Cloudflare Worker by setting 'enabled = true' under the '[analytics]' section in 'wrangler.toml'. ```toml [analytics] enabled = true ``` -------------------------------- ### Cache Invalidation by Version Update Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md Demonstrates how to invalidate the cache by updating the 'CACHE_VERSION' in the 'wrangler.toml' file. Incrementing this version creates new cache keys, effectively clearing old cached data. ```toml [vars] CACHE_VERSION = "v2" # This will invalidate all cached responses ``` -------------------------------- ### Configure Worker Environment Variables Source: https://github.com/jjwprotozoa/dmoc/blob/master/README.md Sets environment variables for the Cloudflare Worker, specifically 'CACHE_TTL' for the cache expiration time in seconds and 'CACHE_VERSION' for cache invalidation. These can be set in 'wrangler.toml' or as secrets. ```toml [vars] CACHE_TTL = "300" # 5 minutes in seconds CACHE_VERSION = "v1" ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.