### Install Propforge using npm, yarn, pnpm, or bun Source: https://github.com/flavio-ever/propforge/blob/main/README.md Install the propforge library using your preferred package manager. ```bash # Using npm npm install propforge # Using yarn yarn add propforge # Using pnpm pnpm add propforge # Using bun bun add propforge ``` -------------------------------- ### Conventional Commit Example Source: https://github.com/flavio-ever/propforge/blob/main/CONTRIBUTING.md A sample commit message following the conventional commit specification. ```text feat(parser): add support for nested templates - Implement nested template parsing - Add tests for nested templates - Update documentation Closes #123 ``` -------------------------------- ### Propforge Property Operations: getProp, setProp, hasProp, removeProp Source: https://github.com/flavio-ever/propforge/blob/main/README.md Demonstrates basic property operations including accessing, setting, checking for existence, and removing nested properties and array elements. Includes examples with default values and array manipulation. ```typescript import { getProp, setProp, hasProp, removeProp } from 'propforge'; const user = { name: 'Flavio Ever', profile: { age: 30, skills: ['JavaScript', 'TypeScript'] } }; // Access properties getProp(user, 'name'); // 'Flavio Ever' getProp(user, 'profile.age'); // 30 getProp(user, 'profile.email', 'n/a'); // 'n/a' (default value) // Access arrays getProp(user, 'profile.skills.0'); // 'JavaScript' getProp(user, 'profile.skills.1'); // 'TypeScript' getProp(user, 'profile.skills.2'); // undefined // Set properties setProp(user, 'name', 'John'); // Update name setProp(user, 'profile.email', 'john@example.com'); // Create email // Work with arrays setProp(user, 'profile.skills.2', 'React'); // Add to array setProp(user, 'profile.skills', ['JavaScript', 'TypeScript', 'React']); // Replace array // Check properties hasProp(user, 'name'); // true hasProp(user, 'profile.age'); // true hasProp(user, 'profile.email'); // true hasProp(user, 'profile.skills.0'); // true hasProp(user, 'profile.skills.3'); // false // Remove properties removeProp(user, 'profile.email'); // Remove email removeProp(user, 'profile.skills.1'); // Remove 'TypeScript' from array hasProp(user, 'profile.email'); // false hasProp(user, 'profile.skills.1'); // false ``` -------------------------------- ### Define Property Transformers Source: https://github.com/flavio-ever/propforge/blob/main/README.md Configures global transformers for get, set, remove, and has operations to normalize data. Requires the User interface type for TypeScript support. ```typescript import { props, getProp, setProp } from 'propforge'; // Define transformers for different operations and properties props.use({ // Global fallback value for missing properties fallback: 'N/A', transformers: { // Transformers for getProp operations getProp: { name: (value) => typeof value === 'string' ? value.trim() : value, 'profile.email': (value) => typeof value === 'string' ? value.trim() : value, 'profile.age': (value) => { const num = Number(value); return Number.isNaN(num) ? value : num; } }, // Transformers for setProp operations setProp: { name: (value) => typeof value === 'string' ? value.trim() : value, 'profile.email': (value) => typeof value === 'string' ? value.trim().toLowerCase() : value }, // Transformers for removeProp operations removeProp: { // Cleanup transformers before removal name: (value) => typeof value === 'string' ? value.trim() : value, }, // Transformers for hasProp operations hasProp: { // Normalize paths before checking 'profile.email': (value) => typeof value === 'string' ? value.trim() : value, } } }); const user = { name: ' Flavio Ever ', profile: { age: '30' } }; // Automatic transformations applied getProp(user, 'name'); // 'Flavio Ever' (trimmed) getProp(user, 'profile.age'); // 30 (converted to number) setProp(user, 'profile.email', ' FLAVIO@EXAMPLE.COM '); // Will be stored as 'flavio@example.com' ``` -------------------------------- ### Documentation Generation Commands Source: https://github.com/flavio-ever/propforge/blob/main/CONTRIBUTING.md Commands to generate project documentation or run it in watch mode. ```bash npm run docs ``` ```bash npm run docs:watch ``` -------------------------------- ### Configure Propforge with Transformers and Templates Source: https://github.com/flavio-ever/propforge/blob/main/README.md Demonstrates setting up debug mode, configuring global fallback and transformers for property operations (getProp, setProp), and configuring template transformers. Ensure to define interfaces for type safety and pass them to props.use. ```typescript import { configureDebug, props, getProp, setProp, template } from 'propforge'; // Define user interface interface User { name: string; profile: { age: number; email?: string; bio?: string; }; } // Enable debug mode configureDebug({ enabled: true, colors: true }); // Configure property transformers props.use({ // Global fallback fallback: 'N/A', transformers: { // GetProp transformers getProp: { name: (value) => typeof value === 'string' ? value.trim() : value, 'profile.email': (value) => typeof value === 'string' ? value.trim() : value, 'profile.age': (value) => { const num = Number(value); return Number.isNaN(num) ? value : num; } }, // SetProp transformers setProp: { name: (value) => typeof value === 'string' ? value.trim() : value, 'profile.email': (value) => typeof value === 'string' ? value.trim().toLowerCase() : value } } }); // Configure template transformers template.use({ fallback: 'N/A', transformers: { capitalize: async (value) => String(value).charAt(0).toUpperCase() + String(value).slice(1), uppercase: async (value) => String(value).toUpperCase(), lowercase: async (value) => String(value).toLowerCase() } }); // Create user object with explicit typing for TypeScript autocomplete and validation const user: User = { name: ' Flavio Ever ', profile: { age: 30 } }; // Property operations with transformers setProp(user, 'profile.email', ' FLAVIO@EXAMPLE.COM '); // Stored as 'flavio@example.com' const name = getProp(user, 'name'); // Returns 'Flavio Ever' (trimmed) // Process template with transformers const result = await template(` Name: {{name | capitalize}} Age: {{profile.age}} Email: {{profile.email | uppercase}} Bio: {{profile.bio}} `)(user); // Output: /* Name: Flavio ever Age: 30 Email: FLAVIO@EXAMPLE.COM Bio: N/A */ ``` -------------------------------- ### Code Quality and Formatting Commands Source: https://github.com/flavio-ever/propforge/blob/main/CONTRIBUTING.md Commands for maintaining code style and verifying quality using Biome. ```bash npm run format ``` ```bash npm run check ``` ```bash npm run fix ``` -------------------------------- ### Template Engine Syntax Source: https://github.com/flavio-ever/propforge/blob/main/README.md Demonstrates the syntax for applying single transformers, arguments, and chains within templates. ```typescript {{value | transformer}} ``` ```typescript {{value | transformer:arg1,arg2,arg3}} ``` ```typescript {{value | transformer1:arg1 | transformer2:arg1,arg2 | transformer3}} ``` -------------------------------- ### Testing Commands Source: https://github.com/flavio-ever/propforge/blob/main/CONTRIBUTING.md Commands to execute the test suite and generate coverage reports. ```bash npm test ``` ```bash npm run test:coverage ``` -------------------------------- ### Handle Missing Properties with Fallbacks Source: https://github.com/flavio-ever/propforge/blob/main/README.md Demonstrates function-level and global fallback configurations for property access and template variables. ```typescript // Provide fallback as third argument to getProp getProp(user, 'profile.email', 'No email provided'); ``` ```typescript import { props } from 'propforge'; // Set global fallback for all getProp operations props.use({ fallback: 'N/A' }); // Now all missing properties will return 'N/A' instead of undefined getProp(user, 'profile.email'); // Returns 'N/A' if email doesn't exist ``` ```typescript import { template } from 'propforge'; // Set global fallback for all template variables template.use({ fallback: 'N/A' }); // Now all missing template variables will show 'N/A' const result = await template(` Email: {{profile.email}} `)(user); // Shows "Email: N/A" if email doesn't exist ``` -------------------------------- ### Configure global operations with props.use Source: https://context7.com/flavio-ever/propforge/llms.txt Sets global fallbacks and transformers for property operations. Supports TypeScript generics for type-safe configuration. ```typescript import { props, getProp, setProp } from 'propforge'; // Define your data interface for type safety interface User { name: string; profile: { age: number; email?: string; phone?: string; }; } // Configure with full type support props.use({ // Global fallback for undefined properties fallback: 'N/A', transformers: { // Transformers for getProp operations getProp: { name: (value) => typeof value === 'string' ? value.trim() : value, 'profile.email': (value) => typeof value === 'string' ? value.toLowerCase() : value, 'profile.age': (value) => { const num = Number(value); return Number.isNaN(num) ? 0 : num; } }, // Transformers for setProp operations setProp: { name: (value) => typeof value === 'string' ? value.trim().toUpperCase() : value, 'profile.email': (value) => typeof value === 'string' ? value.trim().toLowerCase() : value, 'profile.phone': (value) => typeof value === 'string' ? value.replace(/\D/g, '') : value }, // Transformers for removeProp operations removeProp: { name: (value) => value // Pre-removal processing }, // Transformers for hasProp operations hasProp: { 'profile.email': (value) => value // Pre-check processing } } }); // Get current configuration const config = props.getConfig(); console.log(config.fallback); // 'N/A' // Usage with transformers applied automatically const user: User = { name: ' john doe ', profile: { age: 25 } }; setProp(user, 'name', ' jane doe '); console.log(user.name); // 'JANE DOE' (trimmed and uppercased) setProp(user, 'profile.phone', '(11) 99999-9999'); console.log(user.profile.phone); // '11999999999' (digits only) console.log(getProp(user, 'profile.email')); // 'N/A' (fallback) ``` -------------------------------- ### Basic Interpolation with Propforge Source: https://context7.com/flavio-ever/propforge/llms.txt Perform basic variable interpolation using the `{{path}}` syntax. The template function is called with the data object to resolve variables. ```typescript // Basic interpolation const greeting = await template('Hello, {{user.name}}!')(data); // Result: "Hello, flavio ever!" ``` -------------------------------- ### Configure and Use Template Engine Source: https://github.com/flavio-ever/propforge/blob/main/README.md Registers asynchronous transformers and renders templates with data, supporting chaining and context variables. ```typescript import { template } from 'propforge'; template.use({ // Define global fallback value for missing properties in templates fallback: 'N/A', transformers: { formatCurrency: async (value, currency = 'BRL', locale = 'pt-BR') => new Intl.NumberFormat(locale, { style: 'currency', currency }).format(value), formatDate: async (value, locale = 'pt-BR') => new Date(value).toLocaleDateString(locale), truncate: async (value, length = 50, suffix = '...') => String(value).length > length ? String(value).slice(0, length) + suffix : value, capitalize: async (value) => String(value).charAt(0).toUpperCase() + String(value).slice(1) } }); const data = { price: 1000.50, date: '2024-01-15', description: ' this is a very long description that needs to be truncated and formatted ' }; const result = await template(` // Single transformer Price: {{price | formatCurrency}} // Transformer with multiple arguments Price in USD: {{price | formatCurrency:USD,en-US}} // Transformer chain Description: {{description | truncate:20,! | capitalize}} // Using context variables as arguments Date: {{date | formatDate:user.locale}} // Missing property with fallback Notes: {{notes}} `)({ ...data, user: { locale: 'en-US' } }); // Output: /* Price: R$ 1.000,50 Price in USD: $1,000.50 Description: This is a very long! Date: 1/15/2024 Notes: N/A */ ``` -------------------------------- ### Manage Git Flow Features Source: https://github.com/flavio-ever/propforge/blob/main/CONTRIBUTING.md Commands to initialize, commit, and finalize feature branches within the project's Git Flow workflow. ```bash npm run feature:start feature-name ``` ```bash npm run commit ``` ```bash npm run feature:finish ``` -------------------------------- ### Enable and Configure Debug Logging Source: https://context7.com/flavio-ever/propforge/llms.txt Configure debug output for tracking property operations and template processing. Options include enabling/disabling, color output, and custom formatting. ```typescript import { configureDebug, getProp, setProp, template } from 'propforge'; // Enable debug mode with colored output configureDebug({ enabled: true, colors: true // Enable ANSI colors in terminal }); const user = { name: 'Flavio Ever', profile: { age: 30 } }; // Property operations now show debug logs getProp(user, 'name'); // Debug: [12:34:56.789] [props] get: name → "Flavio Ever" setProp(user, 'profile.email', 'flavio@example.com'); // Debug: [12:34:56.790] [props] set: profile.email → "flavio@example.com" // Template processing shows transformation steps template.use({ transformers: { capitalize: async (v) => v.charAt(0).toUpperCase() + v.slice(1) } }); await template('Hello, {{name | capitalize}}!')(user); // Debug: [12:34:56.791] [template] transform: start // Debug: [12:34:56.791] [template] get: name → "Flavio Ever" // Debug: [12:34:56.792] [template] transform: capitalize → "Flavio Ever" // Debug: [12:34:56.792] [template] transform: complete // Custom format function configureDebug({ enabled: true, colors: false, format: (data) => `[${data.module}] ${data.operation}: ${data.path} = ${data.value}` }); // Disable debug mode configureDebug({ enabled: false }); ``` -------------------------------- ### Enable Debug Mode in Propforge Source: https://github.com/flavio-ever/propforge/blob/main/README.md Configures detailed logging for property operations and template processing. ```typescript import { configureDebug } from 'propforge'; // Enable debug mode configureDebug({ enabled: true, colors: true // Optional: enable colored output }); // Example with debug output const user = { name: 'Flavio Ever', profile: { age: 30 } }; // Property operations will now show debug logs getProp(user, 'name'); // Debug output: [props] get: name → "Flavio Ever" setProp(user, 'profile.email', 'flavio@example.com'); // Debug output: [props] set: profile.email → "flavio@example.com" // Template processing will show transformation steps const result = await template(` Name: {{name | capitalize}} Age: {{profile.age}} `)(user); // Debug output: // [template] transform: start // [template] get: name → "Flavio Ever" // [template] transform: capitalize → "Flavio Ever" // [template] get: profile.age → 30 // [template] transform: complete ``` -------------------------------- ### Context Variables as Transformer Arguments Source: https://context7.com/flavio-ever/propforge/llms.txt Use context variables as arguments for transformers. This allows dynamic configuration of transformer behavior based on the provided data. ```typescript // Context variables as arguments const localizedDate = await template('Date: {{order.date | formatDate:user.locale}}')(data); // Result: "Date: 15/01/2024" ``` -------------------------------- ### getProp - Retrieve Nested Property Source: https://context7.com/flavio-ever/propforge/llms.txt Retrieves a value from an object using a dot-notation path, supporting default values and automatic transformation. ```APIDOC ## getProp(object, path, defaultValue?) ### Description Retrieves a value from an object using a dot-notation path. Supports default values when the property doesn't exist and applies configured transformers automatically. ### Parameters - **object** (Object) - Required - The source object to query. - **path** (String) - Required - The dot-notation path to the property (e.g., 'profile.address.city'). - **defaultValue** (Any) - Optional - The value to return if the property is undefined. ### Response - **value** (Any) - The retrieved value, the default value, or the global fallback if configured. ``` -------------------------------- ### Integrate External APIs with Templates Source: https://context7.com/flavio-ever/propforge/llms.txt Register async transformers to fetch data from external APIs for real-time template data transformation. Ensure proper error handling for API calls. ```typescript import { template } from 'propforge'; // Register async transformers with external API calls template.use({ fallback: 'Data unavailable', transformers: { // Fetch address from ZIP code (Brazilian CEP API) fetchAddress: async (zipCode) => { try { const response = await fetch(`https://viacep.com.br/ws/${zipCode}/json/`); const data = await response.json(); if (data.erro) return 'Invalid ZIP code'; return `${data.logradouro}, ${data.bairro} - ${data.localidade}/${data.uf}`; } catch (error) { return 'Failed to fetch address'; } }, // Currency conversion convertCurrency: async (value, from = 'USD', to = 'EUR') => { try { const response = await fetch( `https://api.exchangerate-api.com/v4/latest/${from}` ); const data = await response.json(); const rate = data.rates[to]; return (Number(value) * rate).toFixed(2) + ` ${to}`; } catch (error) { return `${value} ${from}`; } }, // Translate text translate: async (text, targetLang = 'es') => { // Mock translation - replace with actual API const translations: Record> = { es: { 'Hello': 'Hola', 'Goodbye': 'Adiós' }, pt: { 'Hello': 'Olá', 'Goodbye': 'Adeus' } }; return translations[targetLang]?.[text] || text; } } }); const orderData = { zipCode: '01001000', amount: 100, greeting: 'Hello' }; // Template with external API calls (all async) const result = await template(` Delivery Address: {{zipCode | fetchAddress}} Price in EUR: {{amount | convertCurrency:USD,EUR}} Greeting: {{greeting | translate:es}} `)(orderData); // Result (example): // Delivery Address: Praça da Sé, Sé - São Paulo/SP // Price in EUR: 92.50 EUR // Greeting: Hola ``` -------------------------------- ### Register Custom Transformers in Propforge Source: https://context7.com/flavio-ever/propforge/llms.txt Use the `template.use` method to register custom asynchronous transformers. Transformers can be chained and accept arguments. Ensure transformers are registered before use. ```typescript import { template } from 'propforge'; // Register transformers template.use({ fallback: 'N/A', transformers: { uppercase: async (value) => String(value).toUpperCase(), lowercase: async (value) => String(value).toLowerCase(), capitalize: async (value) => String(value).charAt(0).toUpperCase() + String(value).slice(1).toLowerCase(), truncate: async (value, length = 50, suffix = '...') => String(value).length > length ? String(value).slice(0, length) + suffix : value, formatCurrency: async (value, currency = 'USD', locale = 'en-US') => new Intl.NumberFormat(locale, { style: 'currency', currency }).format(value), formatDate: async (value, locale = 'en-US') => new Date(value).toLocaleDateString(locale), formatNumber: async (value, decimals = 2) => Number(value).toFixed(decimals), trim: async (value) => String(value).trim() } }); const data = { user: { name: 'flavio ever', email: 'FLAVIO@EXAMPLE.COM', locale: 'pt-BR' }, order: { total: 1234.56, date: '2024-01-15', description: ' This is a very long product description that needs truncation ' } }; ``` -------------------------------- ### Chained Transformers in Propforge Source: https://context7.com/flavio-ever/propforge/llms.txt Chain multiple transformers together using the pipe `|` symbol. Transformers are applied sequentially in the order they appear. ```typescript // Chained transformers const processed = await template( 'Description: {{order.description | trim | truncate:30,... | capitalize}}' )(data); // Result: "Description: This is a very long product..." ``` -------------------------------- ### Transformer with Arguments in Propforge Source: https://context7.com/flavio-ever/propforge/llms.txt Pass arguments to transformers using the `| transformerName:arg1,arg2` syntax. Ensure the arguments match the transformer's expected signature. ```typescript // Transformer with arguments const price = await template('Total: {{order.total | formatCurrency:BRL,pt-BR}}')(data); // Result: "Total: R$ 1.234,56" ``` -------------------------------- ### Implement Validation and Formatting Transformers Source: https://github.com/flavio-ever/propforge/blob/main/README.md Uses custom transformers to validate email formats and format phone numbers. ```typescript import { template } from 'propforge'; template.use({ transformers: { validateEmail: async (value) => { const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return regex.test(value) ? value : 'Invalid email'; }, formatPhone: async (value) => { const numbers = String(value).replace(/\D/g, ''); return numbers.replace(/(\d{2})(\d{5})(\d{4})/, '($1) $2-$3'); } } }); const data = { email: 'user@example.com', phone: '11999999999' }; const result = await template(` Email: {{email | validateEmail}} Phone: {{phone | formatPhone}} `)(data); // Output: /* Email: user@example.com Phone: (11) 99999-9999 */ ``` -------------------------------- ### Conventional Commit Format Source: https://github.com/flavio-ever/propforge/blob/main/CONTRIBUTING.md The required structure for commit messages using the Commitizen standard. ```text type(scope): description [optional body] [optional footer] ``` -------------------------------- ### Check property existence with hasProp Source: https://context7.com/flavio-ever/propforge/llms.txt Verifies if a property exists at a specific dot-notation path. Returns true even if the value is null or false. ```typescript import { hasProp } from 'propforge'; const user = { name: 'Flavio Ever', profile: { age: 30, skills: ['JavaScript', 'TypeScript'], active: false, bio: null } }; // Check existing properties hasProp(user, 'name'); // true hasProp(user, 'profile.age'); // true hasProp(user, 'profile.active'); // true (value is false but property exists) hasProp(user, 'profile.bio'); // true (value is null but property exists) // Check array elements hasProp(user, 'profile.skills.0'); // true hasProp(user, 'profile.skills.1'); // true hasProp(user, 'profile.skills.2'); // false (index out of bounds) // Check non-existing properties hasProp(user, 'profile.email'); // false hasProp(user, 'profile.address.city'); // false hasProp(user, 'settings'); // false ``` -------------------------------- ### setProp - Set Nested Property Source: https://context7.com/flavio-ever/propforge/llms.txt Sets a value at a nested property path, automatically creating intermediate objects and applying configured transformers. ```APIDOC ## setProp(object, path, value) ### Description Sets a value at a nested property path, automatically creating intermediate objects as needed. Applies configured transformers before setting the value. ### Parameters - **object** (Object) - Required - The target object to modify. - **path** (String) - Required - The dot-notation path where the value should be set. - **value** (Any) - Required - The value to assign to the specified path. ### Response - **object** (Object) - The modified object. ``` -------------------------------- ### Integrate External APIs in Transformers Source: https://github.com/flavio-ever/propforge/blob/main/README.md Performs asynchronous API calls within template transformers to fetch dynamic data. ```typescript import { template } from 'propforge'; template.use({ transformers: { fetchAddress: async (zipCode) => { const response = await fetch(`https://viacep.com.br/ws/${zipCode}/json/`); const data = await response.json(); if (data.erro) throw new Error('Invalid ZIP code'); return `${data.logradouro}, ${data.bairro} - ${data.localidade}/${data.uf}`; }, fetchWeather: async (city) => { const response = await fetch(`https://api.weather.com/${city}`); const data = await response.json(); return `${data.temp}°C, ${data.conditions}`; } } }); const data = { zipCode: '01001000', city: 'São Paulo' }; const result = await template(` Address: {{zipCode | fetchAddress}} Weather: {{city | fetchWeather}} `)(data); // Output: /* Address: Praça da Sé, Sé - São Paulo/SP Weather: 25°C, Sunny */ ``` -------------------------------- ### Fallback for Missing Properties Source: https://context7.com/flavio-ever/propforge/llms.txt Define a fallback value using the `template.use` configuration. This value is used when a requested property is not found in the data object. ```typescript // Missing property with fallback const notes = await template('Notes: {{order.notes}}')(data); // Result: "Notes: N/A" ``` -------------------------------- ### Multi-line Template String Source: https://context7.com/flavio-ever/propforge/llms.txt Utilize multi-line template strings for more complex layouts. The `template` function correctly handles embedded variables and transformers within these strings. ```typescript // Multi-line template const invoice = await template(` Invoice Summary =============== Customer: {{user.name | capitalize}} Email: {{user.email | lowercase}} Date: {{order.date | formatDate}} Total: {{order.total | formatCurrency}} `)(data); ``` -------------------------------- ### Prevent Prototype Pollution Source: https://context7.com/flavio-ever/propforge/llms.txt Propforge automatically blocks operations attempting to access dangerous properties like `__proto__`, `constructor`, or `prototype` to prevent prototype pollution attacks. ```typescript import { getProp, setProp, hasProp } from 'propforge'; const obj = { name: 'test' }; // These operations throw security errors try { getProp(obj, '__proto__.polluted'); } catch (error) { console.error(error.message); // "Security violation detected: Access to __proto__ is not allowed" } try { setProp(obj, 'constructor.prototype.hack', 'malicious'); } catch (error) { console.error(error.message); // "Security violation detected: Access to constructor is not allowed" } try { hasProp(obj, 'prototype'); } catch (error) { console.error(error.message); // "Security violation detected: Access to prototype is not allowed" } // Blocked security terms: // - __proto__ // - constructor // - prototype // - get // - set // - defineProperty // Safe operations work normally getProp(obj, 'name'); // 'test' setProp(obj, 'data.value', 123); // Creates nested object safely hasProp(obj, 'data.value'); // true ``` -------------------------------- ### Retrieve nested properties with getProp Source: https://context7.com/flavio-ever/propforge/llms.txt Access nested object values using dot notation, handle missing properties with defaults, and apply global transformers. ```typescript import { getProp, props } from 'propforge'; // Basic usage const user = { name: 'Flavio Ever', profile: { age: 30, skills: ['JavaScript', 'TypeScript'], address: { city: 'New York', country: 'USA' } } }; // Access nested properties getProp(user, 'name'); // 'Flavio Ever' getProp(user, 'profile.age'); // 30 getProp(user, 'profile.address.city'); // 'New York' // Access array elements getProp(user, 'profile.skills.0'); // 'JavaScript' getProp(user, 'profile.skills.1'); // 'TypeScript' // Default value for missing properties getProp(user, 'profile.email', 'no-email'); // 'no-email' getProp(user, 'profile.phone'); // undefined // Configure global fallback and transformers interface User { name: string; profile: { age: number; email?: string; }; } props.use({ fallback: 'N/A', transformers: { getProp: { name: (value) => typeof value === 'string' ? value.trim() : value, 'profile.age': (value) => { const num = Number(value); return Number.isNaN(num) ? value : num; } } } }); const userData = { name: ' John Doe ', profile: { age: '25' } }; getProp(userData, 'name'); // 'John Doe' (trimmed) getProp(userData, 'profile.age'); // 25 (converted to number) getProp(userData, 'profile.email'); // 'N/A' (global fallback) ``` -------------------------------- ### Define Custom Data Transformers Source: https://github.com/flavio-ever/propforge/blob/main/README.md Registers custom transformation functions for use within template strings. ```typescript import { template } from 'propforge'; template.use({ transformers: { formatDate: async (value, locale = 'pt-BR') => new Date(value).toLocaleDateString(locale), formatCurrency: async (value, currency = 'BRL', locale = 'pt-BR') => new Intl.NumberFormat(locale, { style: 'currency', currency }).format(value) } }); const data = { price: 1000.50, date: '2024-01-15' }; const result = await template(` Price: {{price | formatCurrency}} Date: {{date | formatDate}} `)(data); // Output: /* Price: R$ 1.000,50 Date: 15/01/2024 */ ``` -------------------------------- ### Tagged Template with Functions Source: https://context7.com/flavio-ever/propforge/llms.txt Embed functions directly within tagged template literals. These functions receive the data context and can perform dynamic operations. ```typescript // Tagged template with functions const dynamicResult = await template` User: ${'user.name'} Custom: ${(d) => d.user.name.toUpperCase()} `(data); // Result: "User: flavio ever\nCustom: FLAVIO EVER" ``` -------------------------------- ### Modify nested properties with setProp Source: https://context7.com/flavio-ever/propforge/llms.txt Update or create nested object paths automatically, with support for intermediate object creation and configured value normalization. ```typescript import { setProp, props } from 'propforge'; const user = { name: 'Flavio Ever', profile: { age: 30 } }; // Update existing property setProp(user, 'name', 'John Doe'); // Result: user.name = 'John Doe' // Create nested property (intermediate objects created automatically) setProp(user, 'profile.email', 'john@example.com'); // Result: user.profile.email = 'john@example.com' // Create deeply nested structure setProp(user, 'profile.social.twitter', '@johndoe'); // Result: user.profile.social = { twitter: '@johndoe' } // Work with arrays setProp(user, 'profile.skills', ['JavaScript', 'TypeScript']); setProp(user, 'profile.skills.2', 'React'); // Result: user.profile.skills = ['JavaScript', 'TypeScript', 'React'] // Configure transformers for automatic normalization interface User { name: string; profile: { email?: string; }; } props.use({ transformers: { setProp: { name: (value) => typeof value === 'string' ? value.trim() : value, 'profile.email': (value) => typeof value === 'string' ? value.trim().toLowerCase() : value } } }); setProp(user, 'name', ' Jane Doe '); // Result: user.name = 'Jane Doe' (trimmed) setProp(user, 'profile.email', ' JANE@EXAMPLE.COM '); // Result: user.profile.email = 'jane@example.com' (trimmed and lowercased) ``` -------------------------------- ### Tagged Template Literal Syntax Source: https://context7.com/flavio-ever/propforge/llms.txt Use tagged template literals for a more concise way to define templates. Variables are interpolated directly within the template string. ```typescript // Tagged template literal syntax const taggedResult = await template` Hello, ${'user.name'}! Your total is ${'order.total'}. `(data); // Result: "Hello, flavio ever!\nYour total is 1234.56." ``` -------------------------------- ### Single Transformer Usage in Propforge Source: https://context7.com/flavio-ever/propforge/llms.txt Apply a single transformer to a variable using the `| transformerName` syntax. The transformer is applied to the value before interpolation. ```typescript // Single transformer const formatted = await template('Name: {{user.name | capitalize}}')(data); // Result: "Name: Flavio ever" ``` -------------------------------- ### Remove nested properties with removeProp Source: https://context7.com/flavio-ever/propforge/llms.txt Deletes a property or array element at a given dot-notation path and returns the modified object. ```typescript import { removeProp, hasProp } from 'propforge'; const user = { name: 'Flavio Ever', profile: { age: 30, email: 'flavio@example.com', skills: ['JavaScript', 'TypeScript', 'React'] } }; // Remove simple property removeProp(user, 'profile.email'); hasProp(user, 'profile.email'); // false // Remove array element (uses splice) removeProp(user, 'profile.skills.1'); // Result: user.profile.skills = ['JavaScript', 'React'] // Safe removal of non-existing property (no error) removeProp(user, 'profile.nonExistent'); // Remove nested object removeProp(user, 'profile.age'); // Result: user = { name: 'Flavio Ever', profile: { skills: [...] } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.