npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@flatfile/mapping

v1.0.5

Published

A powerful data transformation engine for structured data records. This package provides a flexible system for transforming data using a comprehensive set of mapping rules that can handle simple assignments, complex transformations, conditional logic, and

Readme

@flatfile/mapping

A powerful data transformation engine for structured data records. This package provides a flexible system for transforming data using a comprehensive set of mapping rules that can handle simple assignments, complex transformations, conditional logic, and data restructuring.

Installation

npm install @flatfile/mapping

Quick Start

import { Run, MappingRule, MappingRuleType } from '@flatfile/mapping';

// Sample data
const records = [
  { firstName: 'John', lastName: 'Doe', email: '[email protected]' },
  { firstName: 'Jane', lastName: 'Smith', email: '[email protected]' }
];

// Define mapping rules
const rules: MappingRule[] = [
  {
    type: MappingRuleType.ASSIGN,
    sourceField: 'firstName',
    destinationField: 'first_name'
  },
  {
    type: MappingRuleType.CONCATENATE,
    sourceFields: ['firstName', 'lastName'],
    destinationField: 'fullName',
    separator: ' '
  }
];

// Create and run mapping
const mapper = new Run(rules);
const result = mapper.applyRules(records);

Core Concepts

Mapping Rules

All transformations are defined using MappingRule objects. Each rule specifies:

  • type: The transformation operation to perform
  • sourceField(s): Input field(s) from the source record
  • destinationField(s): Output field(s) in the transformed record
  • Additional configuration: Rule-specific options

Base Rule Properties

Every mapping rule extends the base interface:

interface BaseMappingRule {
  type: MappingRuleType;
  filter?: string;        // FFQL filter to conditionally apply rule
  name?: string;          // Optional rule name for debugging
  description?: string;   // Optional rule description
  timestamp?: number;     // Optional timestamp for rule differentiation
}

FFQL Filters

Rules can be conditionally applied using FFQL (Flatfile Query Language) filters:

// Apply rule only to records where status is 'active'
filter: "status eq 'active'"

// Reference destination fields with 'destination!' prefix
filter: "destination!processedStatus eq 'pending'"

// Reference source fields with 'source!' prefix  
filter: "source!originalValue eq 'test'"

Rule Types

1. ASSIGN - Direct Field Assignment

Assigns a source field value to a destination field.

{
  type: MappingRuleType.ASSIGN,
  sourceField: 'email',
  destinationField: 'emailAddress'
}

2. CONSTANT - Assign Static Values

Assigns a constant value to a destination field.

{
  type: MappingRuleType.CONSTANT,
  destinationField: 'status',
  value: 'active'
}

3. TRANSFORM - Text Transformations

Applies simple text transformations.

{
  type: MappingRuleType.TRANSFORM,
  sourceField: 'name',
  destinationField: 'name_upper',
  transform: 'uppercase' // or 'lowercase'
}

4. CONCATENATE - Join Multiple Fields

Combines multiple source fields into a single destination field.

{
  type: MappingRuleType.CONCATENATE,
  sourceFields: ['firstName', 'lastName'],
  destinationField: 'fullName',
  separator: ' ' // optional, defaults to empty string
}

5. INTERPOLATE - Template-Based Concatenation

Creates formatted strings using template syntax.

{
  type: MappingRuleType.INTERPOLATE,
  sourceFields: ['firstName', 'lastName'],
  destinationField: 'greeting',
  output: 'Hello {0} {1}!' // {0} = firstName, {1} = lastName
}

6. COALESCE - First Non-Empty Value

Takes the first non-null, non-undefined, non-empty value from a list of fields.

{
  type: MappingRuleType.COALESCE,
  sourceFields: ['preferredName', 'firstName', 'displayName'],
  destinationField: 'name',
  defaultValue: 'Unknown' // optional fallback
}

7. ARRAY - Create Arrays

Creates an array from multiple source fields.

{
  type: MappingRuleType.ARRAY,
  sourceFields: ['phone1', 'phone2', 'phone3'],
  destinationField: 'phoneNumbers'
}

8. REGEX_EXTRACT - Pattern Extraction

Extracts values using regular expressions.

{
  type: MappingRuleType.REGEX_EXTRACT,
  sourceField: 'fullName',
  destinationFields: ['firstName', 'lastName'],
  regex: ['(\\w+)', '(\\w+)$'] // or single regex string
}

9. FIND_REPLACE - Value Substitution

Replaces specific values with other values.

{
  type: MappingRuleType.FIND_REPLACE,
  destinationField: 'country',
  values: [
    { find: 'US', replace: 'United States' },
    { find: 'UK', replace: 'United Kingdom' }
  ]
}

10. NORMALIZE_LIST - List Processing

Converts delimited strings into normalized arrays.

{
  type: MappingRuleType.NORMALIZE_LIST,
  sourceField: 'tags',
  destinationField: 'tagList',
  separator: ',',
  values: [ // optional value normalization
    { find: 'js', replace: 'JavaScript' }
  ],
  unique: true,  // remove duplicates (default: true)
  trim: true     // trim whitespace (default: true)
}

11. ARITHMETIC - Mathematical Operations

Performs mathematical calculations on numeric fields.

{
  type: MappingRuleType.ARITHMETIC,
  sourceFields: ['price', 'tax', 'discount'],
  destinationField: 'total',
  equation: 'price + tax - discount'
}

12. NEST - Create Nested Objects

Groups related fields into nested objects using regex patterns.

{
  type: MappingRuleType.NEST,
  destinationField: 'addresses',
  subfields: [
    {
      sourceRegex: 'address\\.([0-9]+)\\.street',
      destinationSubfield: 'street'
    },
    {
      sourceRegex: 'address\\.([0-9]+)\\.city', 
      destinationSubfield: 'city'
    }
  ]
}
// Transforms: { 'address.1.street': '123 Main', 'address.1.city': 'NYC' }
// Into: { addresses: [{ street: '123 Main', city: 'NYC', __control: '1' }] }

13. FUNCTION - Custom Transformations

Executes custom JavaScript functions for complex transformations.

{
  type: MappingRuleType.FUNCTION,
  sourceFields: ['birthDate'],
  destinationFields: ['age'],
  function: 'calculateAge' // Function name to execute
}

14. SPLIT - Field Splitting

Splits single fields into multiple destination fields.

{
  type: MappingRuleType.SPLIT,
  sourceFields: ['fullName'],
  destinationFields: ['firstName', 'lastName'],
  function: 'splitName'
}

15. SUBPROGRAM - Conditional Rule Groups

Groups multiple rules to be applied conditionally.

{
  type: MappingRuleType.SUBPROGRAM,
  filter: "userType eq 'premium'",
  rules: [
    { type: MappingRuleType.CONSTANT, destinationField: 'priority', value: 'high' },
    { type: MappingRuleType.CONSTANT, destinationField: 'support', value: 'premium' }
  ]
}

16. UNPIVOT - Reshape Data

Transforms wide-format data into long-format.

{
  type: MappingRuleType.UNPIVOT,
  destinationFields: ['metric', 'value'],
  columnMapping: [
    { 'sales_q1': 'Q1 Sales', 'sales_q2': 'Q2 Sales' },
    { 'sales_q1': 'revenue', 'sales_q2': 'revenue' }
  ]
}

17. Utility Rules

Additional utility rules for data management:

  • DELETE: Remove fields from destination
  • IGNORE: Explicitly ignore source fields
  • ADD_FIELD: Add empty fields to destination
  • APPLY_CHANGES: Apply batch modifications
  • DEDUPE: Remove duplicate records

Advanced Features

Custom VM Functions

For FUNCTION and SPLIT rules, provide custom JavaScript execution:

const customFunctions = {
  calculateAge: (birthDate: string) => {
    const birth = new Date(birthDate);
    const today = new Date();
    return today.getFullYear() - birth.getFullYear();
  },
  
  splitName: (fullName: string) => {
    const parts = fullName.split(' ');
    return [parts[0], parts.slice(1).join(' ')];
  }
};

const mapper = new Run(rules, {
  getVM: (functionName: string) => customFunctions[functionName]
});

Calculations in Function Rules

Function rules support aggregation calculations:

{
  type: MappingRuleType.FUNCTION,
  sourceFields: ['scores'],
  destinationFields: ['totalScore', 'avgScore'],
  function: 'processScores',
  calculations: [
    { key: 'total', type: CalculationType.SUM, fieldKey: 'scores', value: null },
    { key: 'average', type: CalculationType.AVERAGE, fieldKey: 'scores', value: null }
  ]
}

Entry Processing

For individual record processing, use the Entry class:

import { Entry } from '@flatfile/mapping';

const entry = new Entry(singleRecord, rules, { vm: customVMProvider });
const transformedRecord = entry.getTransformed();

API Reference

Run Class

Main class for bulk record processing.

Constructor

new Run(rules: MappingRule[], vm?: { getVM?: (code: string) => Function })

Methods

  • applyRules(records: Record<string, any>[]): Record<string, any>[]
  • getKeyHierarchy(options?: { includeUnused?: boolean }): KeyNode[]

Entry Class

Class for individual record processing.

Constructor

new Entry(record: Record<string, any>, rules: MappingRule[], options?: EntryOptions)

Methods

  • getTransformed(): Record<string, any>
  • getOriginal(): Record<string, any>

Error Handling

The mapping engine includes comprehensive error handling:

import { parseAsMappingRule } from '@flatfile/mapping';

try {
  const rule = parseAsMappingRule(ruleObject);
} catch (error) {
  console.error('Invalid rule format:', error.message);
}

Performance Considerations

  • Rules are processed in the order they appear in the array
  • Use filters to conditionally apply expensive transformations
  • Consider using SUBPROGRAM rules to group related transformations
  • Custom VM functions should be optimized for performance

Examples

Complete Transformation Example

import { Run, MappingRule, MappingRuleType } from '@flatfile/mapping';

const sourceData = [
  {
    first_name: 'john',
    last_name: 'doe', 
    email_address: '[email protected]',
    phone_primary: '555-1234',
    phone_secondary: '555-5678',
    user_type: 'premium',
    birth_date: '1990-01-15'
  }
];

const rules: MappingRule[] = [
  // Basic assignments with transformations
  {
    type: MappingRuleType.TRANSFORM,
    sourceField: 'first_name',
    destinationField: 'firstName',
    transform: 'uppercase'
  },
  {
    type: MappingRuleType.ASSIGN,
    sourceField: 'last_name', 
    destinationField: 'lastName'
  },
  
  // Create full name
  {
    type: MappingRuleType.CONCATENATE,
    sourceFields: ['first_name', 'last_name'],
    destinationField: 'fullName',
    separator: ' '
  },
  
  // Create phone array
  {
    type: MappingRuleType.ARRAY,
    sourceFields: ['phone_primary', 'phone_secondary'],
    destinationField: 'phoneNumbers'
  },
  
  // Conditional processing for premium users
  {
    type: MappingRuleType.SUBPROGRAM,
    filter: "user_type eq 'premium'",
    rules: [
      {
        type: MappingRuleType.CONSTANT,
        destinationField: 'priority',
        value: 'high'
      },
      {
        type: MappingRuleType.FUNCTION,
        sourceFields: ['birth_date'],
        destinationFields: ['age'],
        function: 'calculateAge'
      }
    ]
  }
];

// Custom function for age calculation
const customFunctions = {
  calculateAge: (birthDate: string) => {
    const birth = new Date(birthDate);
    const today = new Date();
    let age = today.getFullYear() - birth.getFullYear();
    const monthDiff = today.getMonth() - birth.getMonth();
    if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) {
      age--;
    }
    return age;
  }
};

const mapper = new Run(rules, {
  getVM: (functionName: string) => customFunctions[functionName]
});

const result = mapper.applyRules(sourceData);
console.log(JSON.stringify(result, null, 2));

Contributing

This package is part of the Flatfile Platform monorepo. See the main repository for contribution guidelines.

License

ISC License