### Bash Installation Command Source: https://github.com/dazld/tiny-multimethods/blob/main/README.md Provides the command to install the `tiny-multimethods` package using npm. This is a standard Node.js package manager command. ```bash npm install tiny-multimethods ``` -------------------------------- ### User Authorization with Role and Resource Dispatch (JavaScript) Source: https://context7.com/dazld/tiny-multimethods/llms.txt This example demonstrates a multi-method for user authorization based on the user's role and the resource they are trying to access. It defines specific permissions for different role-resource combinations and includes a default case for unhandled access attempts. ```javascript import { defmulti, DEFAULT } from 'tiny-multimethods'; // User authorization with role and resource type const authorize = defmulti( context => `${context.role}-${context.resource}`, ['admin-any', context => ({ allowed: true, reason: 'Admin access' })], ['editor-article', context => ({ allowed: true, reason: 'Editor can modify articles' })], ['editor-settings', context => ({ allowed: false, reason: 'Editors cannot modify settings' })], ['viewer-article', context => ({ allowed: true, reason: 'Viewer can read articles' })], [DEFAULT, context => ({ allowed: false, reason: `No permission rule for ${context.role} accessing ${context.resource}` })] ); console.log(authorize({ role: 'admin', resource: 'any' })); console.log(authorize({ role: 'editor', resource: 'settings' })); ``` -------------------------------- ### Default Fallback Implementation - JavaScript Source: https://context7.com/dazld/tiny-multimethods/llms.txt Illustrates the use of the `DEFAULT` symbol in `tiny-multimethods` to provide a fallback implementation when no specific method matches. This is crucial for handling unexpected inputs gracefully. The example shows an HTTP request handler where `DEFAULT` catches unsupported methods. ```javascript import { defmulti, DEFAULT } from 'tiny-multimethods'; // HTTP request handler with DEFAULT fallback const handleRequest = defmulti( request => request.method, ['GET', request => ({ status: 200, body: `Retrieved resource: ${request.path}`, headers: { 'Content-Type': 'application/json' } })], ['POST', request => ({ status: 201, body: `Created resource at: ${request.path}`, headers: { 'Content-Type': 'application/json' } })], ['DELETE', request => ({ status: 204, body: null, headers: {} })], // DEFAULT handles all other HTTP methods [DEFAULT, request => ({ status: 405, body: `Method ${request.method} not allowed`, headers: { 'Allow': 'GET, POST, DELETE' } })] ); // Supported methods const getResponse = handleRequest({ method: 'GET', path: '/users/123' }); console.log(getResponse); // Output: { status: 200, body: 'Retrieved resource: /users/123', headers: { 'Content-Type': 'application/json' } } // Unsupported method falls back to DEFAULT const patchResponse = handleRequest({ method: 'PATCH', path: '/users/123' }); console.log(patchResponse); // Output: { status: 405, body: 'Method PATCH not allowed', headers: { 'Allow': 'GET, POST, DELETE' } } // Example without DEFAULT - will throw error const strictHandler = defmulti( request => request.method, ['GET', request => ({ status: 200, body: 'OK' })] ); try { strictHandler({ method: 'POST', path: '/data' }); } catch (error) { console.log(error.message); // Output: No matching method found for {"method":"POST","path":"/data"}, and no DEFAULT value specified } ``` -------------------------------- ### Dynamically Extend Multimethods at Runtime (JavaScript) Source: https://context7.com/dazld/tiny-multimethods/llms.txt Illustrates `addMethod` for extending an existing multimethod (`renderContent`) at runtime. It shows how to add new content type handlers ('video', 'audio') after the multimethod has been initially defined, supporting both tuple and separate argument syntaxes for adding methods. This enables runtime extensibility for plugins or modules. ```javascript import { defmulti, DEFAULT } from 'tiny-multimethods'; // Create a content renderer with initial support for text and images const renderContent = defmulti( content => content.type, ['text', content => `

${content.value}

`], ['image', content => `${content.alt || 'Image'}` ], [DEFAULT, content => `
Content type ${content.type} not supported
` ] ); // Initial usage console.log(renderContent({ type: 'text', value: 'Hello World' })); // Output:

Hello World

console.log(renderContent({ type: 'image', url: '/photo.jpg', alt: 'Photo' })); // Output: Photo // Extend with video support later (e.g., in a plugin) renderContent.addMethod('video', content => { return ( ` `).trim(); }); // Now video content works console.log(renderContent({ type: 'video', url: '/demo.mp4', width: 800 })); // Output: // Alternative syntax: separate arguments renderContent.addMethod('audio', content => { return ``; }); ``` -------------------------------- ### Inspect Multimethods - JavaScript Source: https://context7.com/dazld/tiny-multimethods/llms.txt Demonstrates how to use the `methods()` function to inspect available dispatch values for a multimethod. This is useful for debugging and dynamic validation. It shows how to create a multimethod for notification handling and then inspect its registered priorities. ```javascript import { defmulti, DEFAULT } from 'tiny-multimethods'; // Create a notification handler const notifyUser = defmulti( notification => notification.priority, ['critical', n => { console.error('🚨 CRITICAL:', n.message); return { status: 'sent', channel: 'push' }; }], ['high', n => { console.warn('âš ī¸ HIGH:', n.message); return { status: 'sent', channel: 'email' }; }], ['medium', n => { console.info('â„šī¸ MEDIUM:', n.message); return { status: 'queued', channel: 'email' }; }], [DEFAULT, n => { console.log('📝 LOW:', n.message); return { status: 'queued', channel: 'none' }; }] ); // Inspect available priority levels const availablePriorities = notifyUser.methods(); console.log('Supported priorities:', availablePriorities); // Output: Supported priorities: [ 'critical', 'high', 'medium', Symbol(DEFAULT_DEFMULTI) ] // Validate incoming notification function validateNotification(notification) { const methods = notifyUser.methods().filter(m => typeof m === 'string'); if (notification.priority && !methods.includes(notification.priority)) { console.log(`Warning: Priority '${notification.priority}' will use default handler`); console.log(`Valid priorities: ${methods.join(', ')}`); } } validateNotification({ priority: 'urgent', message: 'System down' }); // Output: Warning: Priority 'urgent' will use default handler // Valid priorities: critical, high, medium // Use the multimethod notifyUser({ priority: 'critical', message: 'Database unreachable' }); // Output: 🚨 CRITICAL: Database unreachable // Returns: { status: 'sent', channel: 'push' } ``` -------------------------------- ### Calculate Shipping Costs with Multi-factor Dispatch (JavaScript) Source: https://context7.com/dazld/tiny-multimethods/llms.txt This code defines a multi-method for calculating shipping costs based on the combination of shipping method ('express' or 'standard') and package type ('fragile' or 'standard'). It uses factors like weight, distance, and value to compute the final cost, with a default case for unknown combinations. ```javascript import { defmulti, DEFAULT } from 'tiny-multimethods'; // Shipping cost calculator based on method and package type const calculateShipping = defmulti( // Dispatch on combination of shipping method and package type order => `${order.method}-${order.packageType}`, ['express-fragile', order => { const baseCost = order.weight * 0.15 + order.distance * 0.08; const handling = 15.00; const insurance = order.value * 0.02; return Math.round((baseCost * 2.5 + handling + insurance) * 100) / 100; }], ['express-standard', order => { const baseCost = order.weight * 0.15 + order.distance * 0.08; return Math.round((baseCost * 2.0) * 100) / 100; }], ['standard-fragile', order => { const baseCost = order.weight * 0.10 + order.distance * 0.05; const handling = 10.00; const insurance = order.value * 0.01; return Math.round((baseCost + handling + insurance) * 100) / 100; }], ['standard-standard', order => { const baseCost = order.weight * 0.10 + order.distance * 0.05; return Math.round(baseCost * 100) / 100; }], [DEFAULT, order => { throw new Error(`Unknown shipping: ${order.method}-${order.packageType}`); }] ); // Calculate various shipping scenarios const order1 = { method: 'express', packageType: 'fragile', weight: 5, // kg distance: 500, // km value: 200 // dollars }; console.log(`Express fragile: $${calculateShipping(order1)}`); const order2 = { method: 'standard', packageType: 'standard', weight: 10, distance: 300, value: 50 }; console.log(`Standard: $${calculateShipping(order2)}`); ``` -------------------------------- ### JavaScript Dynamic Method Addition for Version Processing Source: https://github.com/dazld/tiny-multimethods/blob/main/README.md Illustrates dynamic method addition to a multimethod. Initially, a 'processor' multimethod only supports 'v1'. A new method for 'v2' is added at runtime using `addMethod`, and the available methods can be inspected using `.methods()`. ```javascript const processor = defmulti( data => data.version, ['v1', data => ({ ...data, upgraded: true })] ); // inspect available methods processor.methods() // => ['v1'] // Add support for new version later processor.addMethod('v2', data => ({ ...data, upgraded: true, timestamp: Date.now() })); // observe new method is available processor.methods() // => ['v1', 'v2'] ``` -------------------------------- ### Handle Different Event Types with Multimethods in JavaScript Source: https://context7.com/dazld/tiny-multimethods/llms.txt Implements an event handler using `defmulti` that dispatches based on event type. It defines specific logic for 'user.created', 'user.deleted', and 'payment.completed' events, with a catch-all for unhandled event types. This showcases dynamic behavior based on event context. ```javascript import { defmulti, DEFAULT } from 'tiny-multimethods'; // Event handler for different event types const handleEvent = defmulti( event => event.type, ['user.created', event => { console.log(`New user: ${event.data.email}`); return { action: 'send_welcome_email', to: event.data.email }; }], ['user.deleted', event => { console.log(`User deleted: ${event.data.userId}`); return { action: 'cleanup_user_data', userId: event.data.userId }; }], ['payment.completed', event => { console.log(`Payment received: $${event.data.amount}`); return { action: 'fulfill_order', orderId: event.data.orderId }; }], [DEFAULT, event => { console.log(`Unhandled event: ${event.type}`); return { action: 'log_only' }; }] ); // Process events const events = [ { type: 'user.created', data: { email: 'user@example.com' } }, { type: 'payment.completed', data: { amount: 99.99, orderId: 'ORD-123' } }, { type: 'unknown.event', data: {} } ]; events.forEach(event => { const result = handleEvent(event); console.log('Action:', result); }); // Output: New user: user@example.com // Action: { action: 'send_welcome_email', to: 'user@example.com' } // Payment received: $99.99 // Action: { action: 'fulfill_order', orderId: 'ORD-123' } // Unhandled event: unknown.event // Action: { action: 'log_only' } ``` -------------------------------- ### Process API Responses with Version Handling in JavaScript Source: https://context7.com/dazld/tiny-multimethods/llms.txt Defines a multimethod to process API responses, dynamically transforming data based on the 'version' field. It handles different data formats for 'v1', 'v2', and 'v3', with a default fallback for unknown versions. This demonstrates flexible data adaptation for evolving APIs. ```javascript import { defmulti, DEFAULT } from 'tiny-multimethods'; // API response processor that handles different version formats const processApiResponse = defmulti( response => response.version || 'v1', ['v1', response => { // Legacy format: uppercase keys, timestamp in seconds return { id: response.ID, name: response.NAME, createdAt: new Date(response.CREATED * 1000).toISOString(), version: 'v1' }; }], ['v2', response => { // v2 format: camelCase, ISO timestamps return { id: response.userId, name: response.fullName, createdAt: response.createdAt, version: 'v2' }; }], ['v3', response => { // v3 format: nested structure return { id: response.user.id, name: `${response.user.firstName} ${response.user.lastName}`, createdAt: response.metadata.created, version: 'v3', extra: response.user.preferences }; }], [DEFAULT, response => { console.warn(`Unknown version: ${response.version}, using as-is`); return response; }] ); // Process different API versions const v1Response = { version: 'v1', ID: '12345', NAME: 'John Doe', CREATED: 1640000000 }; console.log(processApiResponse(v1Response)); // Output: { id: '12345', name: 'John Doe', createdAt: '2021-12-20T13:46:40.000Z', version: 'v1' } const v3Response = { version: 'v3', user: { id: '67890', firstName: 'Jane', lastName: 'Smith', preferences: { theme: 'dark' } }, metadata: { created: '2024-01-15T10:30:00Z' } }; console.log(processApiResponse(v3Response)); // Output: { id: '67890', name: 'Jane Smith', createdAt: '2024-01-15T10:30:00Z', version: 'v3', extra: { theme: 'dark' } } ``` -------------------------------- ### Create Multimethod with Dispatch Function (JavaScript) Source: https://context7.com/dazld/tiny-multimethods/llms.txt Demonstrates `defmulti` to create a polymorphic function that dispatches implementations based on a shape's `type` property. It handles specific shapes like 'circle', 'rectangle', and 'triangle', with a `DEFAULT` fallback for unknown types. Errors are thrown for unrecognized shapes. ```javascript import { defmulti, DEFAULT } from 'tiny-multimethods'; // Create a shape area calculator that dispatches on shape type const calculateArea = defmulti( // Dispatch function - extracts the decision value shape => shape.type, // Method implementations as [dispatchValue, implementation] pairs ['circle', shape => { const area = Math.PI * shape.radius ** 2; return Math.round(area * 100) / 100; // Round to 2 decimals }], ['rectangle', shape => { return shape.width * shape.height; }], ['triangle', shape => { return (shape.base * shape.height) / 2; }], // DEFAULT handler for unknown shapes [DEFAULT, shape => { throw new Error(`Unknown shape type: ${shape.type}`); }] ); // Usage examples const circle = { type: 'circle', radius: 5 }; console.log(calculateArea(circle)); // Output: 78.54 const rectangle = { type: 'rectangle', width: 10, height: 5 }; console.log(calculateArea(rectangle)); // Output: 50 const triangle = { type: 'triangle', base: 8, height: 6 }; console.log(calculateArea(triangle)); // Output: 24 // Unknown shape triggers DEFAULT try { calculateArea({ type: 'pentagon', sides: 5 }); } catch (error) { console.log(error.message); // Output: Unknown shape type: pentagon } ``` -------------------------------- ### JavaScript Complex Dispatch Multimethod for Shipping Source: https://github.com/dazld/tiny-multimethods/blob/main/README.md Demonstrates a multimethod for calculating shipping costs where the dispatch value is a combination of shipping method and order type (e.g., 'express-fragile'). This allows for more granular control over implementation selection based on multiple criteria. ```javascript const calculateShipping = defmulti( // Dispatch based on multiple factors order => `${order.method}-${order.type}`, ['express-fragile', order => { const baseCost = order.weight * 0.1 + order.distance * 0.05; return baseCost * 2.5 + 15; // Extra handling + insurance }], ['standard-regular', order => { return order.weight * 0.1 + order.distance * 0.05; }] ); ``` -------------------------------- ### JavaScript Content Rendering Multimethod Source: https://github.com/dazld/tiny-multimethods/blob/main/README.md Implements a multimethod for rendering different content types (text, image, video). The `defmulti` function dispatches based on the 'type' property of the content object, providing specific HTML rendering for each type and a fallback for unsupported types. ```javascript const renderContent = defmulti( content => content.type, ['text', content => `

${content.value}

`], ['image', content => `${content.alt || ''}`], ['video', content => ( ` ` )], [DEFAULT, content => `
Unsupported content type: ${content.type}
`] ); // Usage renderContent({ type: 'text', value: 'Hello World' }); //

Hello World

``` -------------------------------- ### JavaScript Priority-based Notifications Multimethod Source: https://github.com/dazld/tiny-multimethods/blob/main/README.md Creates a multimethod for handling user notifications based on their priority ('high', 'medium', 'low'). The dispatch function uses the 'priority' property to select the appropriate logging and return message for each notification level. ```javascript const notifyUser = defmulti( notification => notification.priority, ['high', n => { console.log('🚨 URGENT:', n.message); return 'high-priority-handled'; }], ['medium', n => { console.log('â„šī¸ NOTICE:', n.message); return 'medium-priority-handled'; }], ['low', n => { console.log('📝 FYI:', n.message); return 'low-priority-handled'; }] ); notifyUser({ priority: 'high', message: 'System is down!' }); // 🚨 URGENT: System is down! ``` -------------------------------- ### JavaScript Multimethod Definition and Usage Source: https://github.com/dazld/tiny-multimethods/blob/main/README.md Defines a multimethod for calculating area based on shape type. It showcases how to create a multimethod using `defmulti`, register methods for specific types ('circle', 'rectangle'), and handle a default case. It also demonstrates dynamic addition of new methods. ```javascript import { defmulti, DEFAULT } from 'tiny-multimethods'; // Create a multimethod that dispatches based on shape type const calculateArea = defmulti( shape => shape.type, ['circle', shape => Math.PI * shape.radius ** 2], ['rectangle', shape => shape.width * shape.height], [DEFAULT, shape => { throw new Error(`Can't calculate area of ${shape.type}`); }] ); // Use it console.log(calculateArea({ type: 'circle', radius: 5 })); // 78.54... console.log(calculateArea({ type: 'rectangle', width: 4, height: 3 })); // 12 // Add new methods dynamically calculateArea.addMethod('triangle', shape => (shape.base * shape.height) / 2 ); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.