Extended Part9c of 12 (Sub-part C)
Main PartPart 9
Related Parts9a, 9b
Version0.1.0-draft
Last Updated2025-11-30
StatusDraft
TypeINFORMATIVE (Non-Normative)

WDP Part 9c: Implementation Guide

Practical implementation guidance for the WDP catalog system with code examples for generating catalogs, loading them on clients, and expanding compact diagnostics.

Abstract#

This document provides practical implementation guidance for the Waddling Diagnostic Protocol (WDP) catalog system. It includes code examples for generating catalogs, loading them on clients, and expanding compact diagnostics.

Key Points:

  • Server-side: Generate catalogs from error registries
  • Client-side: Load catalogs and expand compact diagnostics
  • Testing: Validate catalogs and test expansion
  • Multi-language: Rust, Python, TypeScript examples

Conformance

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

1. Introduction#

1.1 Implementation Checklist

Server-Side:

Client-Side:

1.2 Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Error Registry  β”‚  (Source code, config)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Catalog Generatorβ”‚  (Build-time tool)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  catalog.json    β”‚  (Artifact)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   CDN / Server   β”‚  (Distribution)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Client Cache   β”‚ ◄──► β”‚   Server API     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                         β”‚
         β”‚   {"xY9Kp":{"f":{...}}} β”‚
         β”‚ β—„β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Expanded Message β”‚
β”‚ "Token expired…" β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. Server-Side Implementation#

2.1 Catalog Generation (Rust)

Rust
use serde::{Deserialize, Serialize};
use serde_json::json;
use std::collections::HashMap;
use xxhash_rust::xxh64::xxh64;

// Compute namespace hash using xxHash64 with seed "wdp-ns-v1"
fn compute_namespace_hash(namespace: &str) -> String {
    let seed = xxh64(b"wdp-ns-v1", 0);
    let hash = xxh64(namespace.as_bytes(), seed);
    base62_encode(hash)
}

fn base62_encode(mut num: u64) -> String {
    const CHARS: &[u8] = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    let mut result = String::new();
    
    while num > 0 || result.is_empty() {
        result.insert(0, CHARS[(num % 62) as usize] as char);
        num /= 62;
    }
    
    // Pad to 5 characters
    while result.len() < 5 {
        result.insert(0, '0');
    }
    
    result.chars().take(5).collect()
}

#[derive(Serialize, Deserialize)]
struct ErrorEntry {
    code: String,
    severity: String,
    message: String,
    description: Option<String>,
    hints: Vec<String>,
    tags: Vec<String>,
    fields: Vec<String>,
}

struct CatalogGenerator {
    version: String,
    namespace: Option<String>,
    namespace_hash: Option<String>,
    diags: HashMap<String, ErrorEntry>,
}

impl CatalogGenerator {
    fn new(version: &str) -> Self {
        Self {
            version: version.to_string(),
            namespace: None,
            namespace_hash: None,
            diags: HashMap::new(),
        }
    }
    
    fn with_namespace(mut self, namespace: &str) -> Self {
        self.namespace_hash = Some(compute_namespace_hash(namespace));
        self.namespace = Some(namespace.to_string());
        self
    }
    
    fn add_error(&mut self, compact_id: &str, entry: ErrorEntry) {
        self.diags.insert(compact_id.to_string(), entry);
    }
    
    fn generate_compact(&self) -> String {
        let mut compact_diags = serde_json::Map::new();
        
        for (hash, entry) in &self.diags {
            compact_diags.insert(hash.clone(), json!({
                "c": entry.code,
                "s": entry.severity,
                "m": entry.message,
                "d": entry.description,
                "h": entry.hints,
                "t": entry.tags,
                "f": entry.fields,
            }));
        }
        
        let catalog = json!({
            "v": self.version,
            "wd": compact_diags
        });
        
        serde_json::to_string(&catalog).unwrap()
    }
}

// Usage
fn main() {
    let mut generator = CatalogGenerator::new("1.0.0");
    
    generator.add_error("jGKFp", ErrorEntry {
        code: "E.AUTH.TOKEN.001".to_string(),
        severity: "E".to_string(),
        message: "Token missing from Authorization header".to_string(),
        description: Some("The JWT token was not provided.".to_string()),
        hints: vec!["Include header: Authorization: Bearer <token>".to_string()],
        tags: vec!["auth".to_string(), "security".to_string()],
        fields: vec![],
    });
    
    let catalog_json = generator.generate_compact();
    std::fs::write("catalog.json", catalog_json).unwrap();
}

2.2 Catalog Generation (Python)

Python
import json
from typing import Dict, List, Optional
from dataclasses import dataclass, asdict
import xxhash

def compute_namespace_hash(namespace: str) -> str:
    """Generate 5-character Base62 hash for namespace."""
    seed_hash = xxhash.xxh64(b"wdp-ns-v1").intdigest()
    ns_hash = xxhash.xxh64(namespace.encode('utf-8'), seed=seed_hash).intdigest()
    return base62_encode(ns_hash)[:5]

def base62_encode(num: int) -> str:
    """Encode number as Base62 string."""
    chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
    if num == 0:
        return "00000"
    
    result = ""
    while num > 0:
        result = chars[num % 62] + result
        num //= 62
    
    return result.zfill(5)[:5]

@dataclass
class ErrorEntry:
    code: str
    severity: str
    message: str
    description: Optional[str] = None
    hints: List[str] = None
    tags: List[str] = None
    fields: List[str] = None
    
    def __post_init__(self):
        self.hints = self.hints or []
        self.tags = self.tags or []
        self.fields = self.fields or []

class CatalogGenerator:
    def __init__(self, version: str, namespace: Optional[str] = None):
        self.version = version
        self.namespace = namespace
        self.namespace_hash = compute_namespace_hash(namespace) if namespace else None
        self.diags: Dict[str, ErrorEntry] = {}
    
    def add_error(self, compact_id: str, entry: ErrorEntry):
        self.diags[compact_id] = entry
    
    def generate_compact(self) -> str:
        compact_diags = {}
        for cid, entry in self.diags.items():
            compact_diags[cid] = {
                "c": entry.code,
                "s": entry.severity,
                "m": entry.message,
                "d": entry.description,
                "h": entry.hints,
                "t": entry.tags,
                "f": entry.fields
            }
        
        catalog = {"v": self.version, "wd": compact_diags}
        return json.dumps(catalog, separators=(',', ':'))

# Usage
generator = CatalogGenerator("1.0.0")
generator.add_error("jGKFp", ErrorEntry(
    code="E.AUTH.TOKEN.001",
    severity="E",
    message="Token missing from Authorization header",
    description="The JWT token was not provided.",
    hints=["Include header: Authorization: Bearer <token>"],
    tags=["auth", "security"],
    fields=[]
))

catalog_json = generator.generate_compact()
with open("catalog.json", "w") as f:
    f.write(catalog_json)

2.3 Generating Diagnostic Responses (TypeScript)

Typescript
interface Diagnostic {
  compactId: string;  // CompactID (5 chars) or CombinedID (11 chars)
  fields?: Record<string, any>;
}

class DiagnosticResponse {
  /**
   * Generate WDP diagnostic response
   * Use standalone format when diagnostics are the only content
   */
  static standalone(diagnostics: Diagnostic[]): object {
    const response: Record<string, any> = {};
    
    for (const diag of diagnostics) {
      if (diag.fields && Object.keys(diag.fields).length > 0) {
        response[diag.compactId] = { f: diag.fields };
      } else {
        response[diag.compactId] = {};
      }
    }
    
    return response;
  }
  
  /**
   * Generate WDP diagnostic response mixed with application data
   * Use "wd" wrapper to avoid key conflicts
   */
  static withData(data: object, diagnostics: Diagnostic[]): object {
    const wd: Record<string, any> = {};
    
    for (const diag of diagnostics) {
      if (diag.fields && Object.keys(diag.fields).length > 0) {
        wd[diag.compactId] = { f: diag.fields };
      } else {
        wd[diag.compactId] = {};
      }
    }
    
    return { ...data, wd };
  }
}

// Usage - Express.js example
app.post('/api/login', async (req, res) => {
  const errors: Diagnostic[] = [];
  
  if (!req.body.email) {
    errors.push({
      compactId: 'aG8eT',
      fields: { field: 'email' }
    });
  }
  
  if (!req.body.password || req.body.password.length < 8) {
    errors.push({
      compactId: 'mN3Yr',
      fields: { field: 'password', min_length: 8 }
    });
  }
  
  if (errors.length > 0) {
    return res.status(422).json(
      DiagnosticResponse.standalone(errors)
    );
  }
  
  res.json({ token: '...' });
});

3. Client-Side Implementation#

3.1 Catalog Loading (TypeScript)

Typescript
interface CatalogEntry {
  code: string;
  severity: string;
  message: string;
  description?: string;
  hints?: string[];
  tags?: string[];
  fields?: string[];
}

interface Catalog {
  version: string;
  diags: Record<string, CatalogEntry>;
}

interface ExpandedDiagnostic {
  compactId: string;
  code: string;
  severity: string;
  message: string;
  description?: string;
  hints?: string[];
}

class WDPCatalog {
  private catalog: Catalog | null = null;
  
  async load(url: string): Promise<void> {
    const response = await fetch(url);
    this.catalog = await response.json();
  }
  
  /**
   * Expand diagnostics from wire protocol format
   * Handles both standalone and "wd" wrapped formats
   */
  expand(response: any): ExpandedDiagnostic[] {
    if (!this.catalog) {
      throw new Error("Catalog not loaded");
    }
    
    // Extract diagnostics (handle both formats)
    let diagnostics: Record<string, any>;
    
    if (response.wd) {
      diagnostics = response.wd;
    } else {
      diagnostics = {};
      for (const [key, value] of Object.entries(response)) {
        // Match CompactID (5 chars) or CombinedID (11 chars)
        if (/^[0-9A-Za-z]{5}(-[0-9A-Za-z]{5})?$/.test(key)) {
          diagnostics[key] = value;
        }
      }
    }
    
    const results: ExpandedDiagnostic[] = [];
    
    for (const [wireKey, data] of Object.entries(diagnostics)) {
      const entry = this.lookupDiag(wireKey);
      
      if (!entry) {
        results.push({
          compactId: wireKey,
          code: 'UNKNOWN',
          severity: 'E',
          message: `Unknown diagnostic: ${wireKey}`
        });
        continue;
      }
      
      let message = entry.message;
      
      // Interpolate fields
      if (data.f) {
        for (const [field, value] of Object.entries(data.f)) {
          message = message.replace(`{{${field}}}`, String(value));
        }
      }
      
      results.push({
        compactId: wireKey,
        code: entry.code,
        severity: entry.severity,
        message,
        description: entry.description,
        hints: entry.hints
      });
    }
    
    return results;
  }
  
  private lookupDiag(wireKey: string): CatalogEntry | null {
    if (!this.catalog) return null;
    
    // Direct lookup
    if (this.catalog.diags[wireKey]) {
      return this.catalog.diags[wireKey];
    }
    
    // Handle over-qualified (CombinedID β†’ single-namespace)
    if (wireKey.includes('-')) {
      const [nsHash, compactId] = wireKey.split('-');
      return this.catalog.diags[compactId] || null;
    }
    
    return null;
  }
}

// Usage
const catalog = new WDPCatalog();
await catalog.load('https://cdn.example.com/catalog.json');

const response = await fetch('/api/login', {
  method: 'POST',
  body: JSON.stringify({ email: '', password: '123' })
});

const diagnostics = catalog.expand(await response.json());

diagnostics.forEach(diag => {
  const icon = {
    'E': '❌', 'W': '⚠️', 'C': 'πŸ”΄', 'I': 'ℹ️', 'H': 'πŸ’‘'
  }[diag.severity] || 'β€’';
  
  console.log(`${icon} ${diag.severity}: ${diag.message}`);
});

3.2 Catalog Loading (Python)

Python
import requests
import json
from typing import Dict, List, Optional

class WDPCatalog:
    def __init__(self):
        self.catalog: Optional[Dict] = None
    
    def load(self, url: str):
        """Load catalog from URL"""
        response = requests.get(url)
        self.catalog = response.json()
    
    def load_file(self, path: str):
        """Load catalog from local file"""
        with open(path, 'r') as f:
            self.catalog = json.load(f)
    
    def expand(self, response: Dict) -> List[Dict]:
        """Expand diagnostics from wire protocol format"""
        if not self.catalog:
            raise ValueError("Catalog not loaded")
        
        # Extract diagnostics
        if 'wd' in response:
            diagnostics = response['wd']
        else:
            diagnostics = {
                k: v for k, v in response.items()
                if len(k) == 5 and k.isalnum()
            }
        
        results = []
        
        for compact_id, data in diagnostics.items():
            entry = self.catalog['diags'].get(compact_id)
            
            if not entry:
                results.append({
                    'compact_id': compact_id,
                    'code': 'UNKNOWN',
                    'severity': 'E',
                    'message': f"Unknown diagnostic: {compact_id}"
                })
                continue
            
            message = entry['message']
            
            # Interpolate fields
            if 'f' in data:
                for field, value in data['f'].items():
                    message = message.replace(f"{{{{{field}}}}}", str(value))
            
            results.append({
                'compact_id': compact_id,
                'code': entry['code'],
                'severity': entry['severity'],
                'message': message,
                'description': entry.get('description'),
                'hints': entry.get('hints', [])
            })
        
        return results

# Usage
catalog = WDPCatalog()
catalog.load('https://cdn.example.com/catalog.json')

response = requests.post('/api/login', json={
    'email': '',
    'password': '123'
})

diagnostics = catalog.expand(response.json())

severity_icons = {'E': '❌', 'W': '⚠️', 'C': 'πŸ”΄', 'I': 'ℹ️', 'H': 'πŸ’‘'}

for diag in diagnostics:
    icon = severity_icons.get(diag['severity'], 'β€’')
    print(f"{icon} {diag['severity']}: {diag['message']}")

3.3 Browser Implementation with Caching

Javascript
class WDPCatalogClient {
  constructor(catalogUrl, cacheKey = 'wdp-catalog') {
    this.catalogUrl = catalogUrl;
    this.cacheKey = cacheKey;
    this.catalog = null;
  }
  
  async load() {
    // Try to load from cache first
    const cached = this.loadFromCache();
    if (cached) {
      this.catalog = cached;
      // Update in background
      this.updateCache().catch(console.error);
      return;
    }
    
    await this.updateCache();
  }
  
  loadFromCache() {
    try {
      const cached = localStorage.getItem(this.cacheKey);
      if (!cached) return null;
      
      const data = JSON.parse(cached);
      
      // Check if cache is still valid (< 7 days old)
      const age = Date.now() - data.timestamp;
      if (age > 7 * 24 * 60 * 60 * 1000) {
        return null;
      }
      
      return data.catalog;
    } catch (e) {
      console.error('Failed to load cached catalog:', e);
      return null;
    }
  }
  
  async updateCache() {
    const response = await fetch(this.catalogUrl);
    this.catalog = await response.json();
    
    localStorage.setItem(this.cacheKey, JSON.stringify({
      catalog: this.catalog,
      timestamp: Date.now()
    }));
  }
  
  expand(response) {
    if (!this.catalog) {
      throw new Error('Catalog not loaded');
    }
    
    let diagnostics;
    if (response.wd) {
      diagnostics = response.wd;
    } else {
      diagnostics = {};
      for (const [key, value] of Object.entries(response)) {
        if (/^[0-9A-Za-z]{5}(-[0-9A-Za-z]{5})?$/.test(key)) {
          diagnostics[key] = value;
        }
      }
    }
    
    const results = [];
    
    for (const [wireKey, data] of Object.entries(diagnostics)) {
      const entry = this.catalog.diags[wireKey];
      
      if (!entry) {
        results.push({
          compactId: wireKey,
          severity: 'E',
          message: `Unknown diagnostic: ${wireKey}`
        });
        continue;
      }
      
      let message = entry.message;
      
      if (data.f) {
        for (const [field, value] of Object.entries(data.f)) {
          message = message.replace(`{{${field}}}`, value);
        }
      }
      
      results.push({
        compactId: wireKey,
        code: entry.code,
        severity: entry.severity,
        message,
        hints: entry.hints
      });
    }
    
    return results;
  }
}

4. Testing#

4.1 Catalog Validation Tests (Python)

Python
import pytest
import json
import re

def test_catalog_structure():
    """Test catalog has required fields and valid structure"""
    with open('catalog.json') as f:
        catalog = json.load(f)
    
    # Required top-level fields
    assert 'version' in catalog
    assert 'diags' in catalog
    
    # Version format
    assert re.match(r'^\d+\.\d+\.\d+$', catalog['version'])

def test_catalog_entries():
    """Test each catalog entry is valid"""
    with open('catalog.json') as f:
        catalog = json.load(f)
    
    for compact_id, entry in catalog['diags'].items():
        # Compact ID format
        assert len(compact_id) == 5
        assert re.match(r'^[0-9A-Za-z]{5}$', compact_id)
        
        # Required fields
        assert 'code' in entry
        assert 'severity' in entry
        assert 'message' in entry
        
        # Severity matches code
        assert entry['code'].startswith(entry['severity'])

def test_field_placeholders():
    """Test message placeholders match fields list"""
    with open('catalog.json') as f:
        catalog = json.load(f)
    
    for compact_id, entry in catalog['diags'].items():
        message = entry['message']
        fields = entry.get('fields', [])
        
        # Extract placeholders from message
        placeholders = re.findall(r'\{\{([a-zA-Z_][a-zA-Z0-9_]*)\}\}', message)
        
        # All placeholders should be in fields list
        for placeholder in placeholders:
            assert placeholder in fields

def test_key_format_consistency():
    """Test catalog doesn't mix CompactID and CombinedID formats"""
    with open('catalog.json') as f:
        catalog = json.load(f)
    
    has_hyphen = any('-' in key for key in catalog['diags'].keys())
    no_hyphen = all('-' not in key for key in catalog['diags'].keys())
    
    assert has_hyphen or no_hyphen, \
        "Catalog cannot mix CompactID and CombinedID formats"

4.2 Expansion Tests (TypeScript)

Typescript
import { describe, it, expect } from 'vitest';

describe('WDPCatalog', () => {
  it('should expand diagnostic with fields', () => {
    const catalog = new WDPCatalog();
    catalog.catalog = {
      version: '1.0.0',
      diags: {
        'xY9Kp': {
          code: 'E.AUTH.TOKEN.EXPIRED',
          severity: 'E',
          message: 'Token expired at {{timestamp}}'
        }
      }
    };
    
    const response = {
      'xY9Kp': { f: { timestamp: '2024-01-15T10:30:00Z' } }
    };
    
    const results = catalog.expand(response);
    
    expect(results).toHaveLength(1);
    expect(results[0].message).toBe('Token expired at 2024-01-15T10:30:00Z');
  });
  
  it('should handle "wd" wrapper format', () => {
    const catalog = new WDPCatalog();
    catalog.catalog = {
      version: '1.0.0',
      diags: {
        'wN4Qm': {
          code: 'W.STORAGE.QUOTA.APPROACHING',
          severity: 'W',
          message: 'Storage quota at {{quota_used}}/{{quota_limit}} MB'
        }
      }
    };
    
    const response = {
      data: { id: '12345' },
      wd: {
        'wN4Qm': { f: { quota_used: '850', quota_limit: '1000' } }
      }
    };
    
    const results = catalog.expand(response);
    
    expect(results).toHaveLength(1);
    expect(results[0].message).toBe('Storage quota at 850/1000 MB');
  });
  
  it('should handle unknown compact ID', () => {
    const catalog = new WDPCatalog();
    catalog.catalog = { version: '1.0.0', diags: {} };
    
    const response = { 'ZZZZZ': {} };
    const results = catalog.expand(response);
    
    expect(results).toHaveLength(1);
    expect(results[0].message).toContain('Unknown diagnostic');
  });
});

5. Best Practices#

5.1 Catalog Generation

Recommended practices:

  • Generate catalogs at build time (not runtime)
  • Version catalogs with semantic versioning
  • Use Compact format for production
  • Host on CDN with long cache headers
  • Generate separate catalogs per language
  • Validate catalog structure before deploying

Practices to avoid:

  • Generating catalogs on-the-fly for each request
  • Embedding sensitive data in catalogs (they're public)
  • Changing catalog content without bumping version
  • Making catalogs too large (keep < 500KB)

5.2 Client-Side Loading

Recommended practices:

  • Cache catalogs locally (localStorage, IndexedDB)
  • Load catalog asynchronously at app startup
  • Handle catalog loading failures gracefully
  • Update catalogs in the background
  • Validate catalog before using

Practices to avoid:

  • Blocking app initialization on catalog load
  • Loading catalog on every page load
  • Assuming catalog is always available
  • Caching catalogs indefinitely without updates

5.3 Diagnostic Generation

Recommended practices:

  • Use standalone format for pure diagnostic responses
  • Use "wd" wrapper when mixing with application data
  • Include all necessary fields for interpolation
  • Set appropriate HTTP status codes

5.4 Error Handling

Recommended practices:

  • Handle unknown compact IDs gracefully
  • Display fallback message if catalog unavailable
  • Log catalog loading failures
  • Provide clear error messages to users
  • Allow manual catalog refresh

5.5 Namespace Usage

Choosing Catalog Type:

Namespace Naming Best Practices:

  • Use descriptive, service-specific names: auth_service, payment_lib
  • Use lowercase with underscores
  • Keep names stable (hash doesn't change)
  • Document namespace meanings

Privacy Considerations:

Include namespaces index when:

  • βœ… Internal tools (ops dashboards, monitoring)
  • βœ… Human-readable attribution needed
  • βœ… Service names not sensitive

Omit namespaces index when:

  • βœ… Public-facing applications
  • βœ… Service architecture is confidential
  • βœ… Privacy-preserving mode desired

5.6 Performance

Recommended practices:

  • Compress catalogs (gzip/brotli)
  • Use CDN for catalog distribution
  • Cache catalog lookups in memory
  • Lazy-load catalog if not immediately needed
  • Minify JSON in production

Practices to avoid:

  • Parsing catalog on every diagnostic
  • Loading multiple catalogs simultaneously
  • Including unnecessary metadata in production catalogs
  • Re-downloading catalog unnecessarily

Appendix A: Complete Example Application#

Jsx
// Complete example: React application with WDP

import React, { useEffect, useState } from 'react';

// Initialize catalog client
const catalogClient = new WDPCatalogClient(
  'https://cdn.example.com/catalog.json'
);

function App() {
  const [catalogLoaded, setCatalogLoaded] = useState(false);
  
  useEffect(() => {
    catalogClient.load()
      .then(() => setCatalogLoaded(true))
      .catch(console.error);
  }, []);
  
  return (
    <div>
      {catalogLoaded ? (
        <LoginForm catalog={catalogClient} />
      ) : (
        <div>Loading...</div>
      )}
    </div>
  );
}

function LoginForm({ catalog }) {
  const [diagnostics, setDiagnostics] = useState([]);
  
  async function handleSubmit(e) {
    e.preventDefault();
    
    const formData = new FormData(e.target);
    const response = await fetch('/api/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        email: formData.get('email'),
        password: formData.get('password')
      })
    });
    
    const body = await response.json();
    
    if (!response.ok) {
      const expanded = catalog.expand(body);
      setDiagnostics(expanded);
    } else {
      window.location.href = '/dashboard';
    }
  }
  
  return (
    <form onSubmit={handleSubmit}>
      <DiagnosticList diagnostics={diagnostics} />
      <input type="email" name="email" placeholder="Email" />
      <input type="password" name="password" placeholder="Password" />
      <button type="submit">Login</button>
    </form>
  );
}

function Diagnostic({ diagnostic }) {
  const config = {
    'E': { icon: '❌', className: 'error' },
    'W': { icon: '⚠️', className: 'warning' },
    'C': { icon: 'πŸ”΄', className: 'critical' },
    'I': { icon: 'ℹ️', className: 'info' },
    'H': { icon: 'πŸ’‘', className: 'help' }
  };
  
  const { icon, className } = config[diagnostic.severity] || config['E'];
  
  return (
    <div className={`diagnostic ${className}`}>
      <div className="diagnostic-header">
        <span className="icon">{icon}</span>
        <span className="message">{diagnostic.message}</span>
      </div>
      
      {diagnostic.hints?.length > 0 && (
        <ul className="hints">
          {diagnostic.hints.map((hint, i) => (
            <li key={i}>πŸ’‘ {hint}</li>
          ))}
        </ul>
      )}
    </div>
  );
}

References#

Related Specifications:

  • Part 9a: Catalog Format - JSON catalog file format
  • Part 9b: Wire Protocol - HTTP transmission format
  • Part 5: Compact IDs - Hash generation algorithm
  • Part 7: Namespaces - Namespace hashing

End of Part 9c: Implementation Guide