🚀 DAY 5 OF LAUNCH WEEK:Introducing Webhook Events for Alert Changes.Learn more →
Socket
Book a DemoInstallSign in
Socket

@flaconi/metadata-mapper

Package Overview
Dependencies
Maintainers
54
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@flaconi/metadata-mapper

A TypeScript library for parsing and mapping Flaconi metadata including stores, languages, currencies, and channels configuration

latest
Source
npmnpm
Version
1.0.0
Version published
Maintainers
54
Created
Source

@flaconi/metadata-mapper

Standardized TypeScript library for Flaconi's metadata processing

npm version CI Status Coverage License: MIT

A comprehensive TypeScript library for parsing and mapping Flaconi metadata including stores, languages, currencies, and channels configuration. This library provides a robust, type-safe interface for working with Flaconi's multi-regional store setup.

Features

  • Store Management: Map between store codes, languages, currencies, and price channels
  • Website Mapping: Convert between website identifiers and store configurations
  • LocaleMapper Compatible: Drop-in replacement for existing LocaleMapper functionality
  • Bidirectional Mapping: Get store info from websites and vice versa
  • Multi-Currency Support: Automatic currency mapping per store
  • Performance: Lightweight synchronous operations with embedded data
  • Type Safe: Full TypeScript support with strict typing
  • 100% Test Coverage: Comprehensive test suite with realistic fixtures
  • Dual Package: Supports both ESM and CommonJS
  • Zero Dependencies: No external runtime dependencies

Installation

# Using npm
npm install @flaconi/metadata-mapper

# Using yarn
yarn add @flaconi/metadata-mapper

Quick Start

import { MetadataMapper, defaultFlaconiMetadata } from '@flaconi/metadata-mapper';

// Initialize with default embedded metadata
const mapper = new MetadataMapper(defaultFlaconiMetadata);

// Get language by store code (uppercase format)
const language = mapper.getLanguageByStore('DE');
console.log(language); // 'de-DE'

// Get language by website identifier (this is the key use case!)
const websiteLanguage = mapper.getLanguageByWebsite('base');
console.log(websiteLanguage); // 'de-DE'

// Map store to website identifier
const websiteId = mapper.mapStoreToWebsiteId('de');
console.log(websiteId); // 'base'

Migration from LocaleMapper

This library is a drop-in replacement for LocaleMapper. Simply replace your import and instance:

// Before
import { LocaleMapper } from 'path/to/locale-mapper';
const localeMapper = new LocaleMapper(metadata);

// After  
import { MetadataMapper, defaultFlaconiMetadata } from '@flaconi/metadata-mapper';
const localeMapper = new MetadataMapper(defaultFlaconiMetadata);

// All method calls remain the same!
const language = localeMapper.getLanguageByWebsite('base');
const store = localeMapper.getStoreByWebsite('flaconi_at');
const currency = localeMapper.getCurrencyByStore('CH');

Usage Examples

Basic Store Operations

import { MetadataMapper, defaultFlaconiMetadata } from '@flaconi/metadata-mapper';

const mapper = new MetadataMapper(defaultFlaconiMetadata);

// Get language by store (expects uppercase store codes)
const language = mapper.getLanguageByStore('AT');
console.log(language); // 'de-AT'

// Get currency by store
const currency = mapper.getCurrencyByStore('CH');
console.log(currency); // 'CHF'

// Get price channel by store
const channel = mapper.getChannelByStore('FR');
console.log(channel); // 'flaconi-fr'

// Get all available stores
const stores = mapper.getStores();
console.log(stores); // ['DE', 'AT', 'CH', 'FR', 'IT', 'PL', 'BERLIN_1', 'BERLIN_2']

Website Mapping (Migration from LocaleMapper)

This library provides full compatibility for website-based mapping operations:

// Real-world example: Processing price data with website identifiers
interface PriceData {
  websites: string; // e.g., 'base', 'flaconi_at', 'berlin_1'
  // ... other price fields
}

const newPrice: PriceData = {
  websites: 'base' // This is the website identifier for DE store
};

// Get language by website (replaces localeMapper.getLanguageByWebsite)
const language = mapper.getLanguageByWebsite(newPrice.websites);
console.log(language); // 'de-DE'

// Get store by website identifier
const store = mapper.getStoreByWebsite(newPrice.websites);
console.log(store); // 'DE'

// Map website back to other store properties
const currency = mapper.getCurrencyByStore(store);
console.log(currency); // 'EUR'

Store to Website Mapping

// Map store codes to website identifiers (special logic for DE and Berlin stores)
const websiteId1 = mapper.mapStoreToWebsiteId('de');
console.log(websiteId1); // 'base' (special case)

const websiteId2 = mapper.mapStoreToWebsiteId('at');
console.log(websiteId2); // 'flaconi_at'

const websiteId3 = mapper.mapStoreToWebsiteId('berlin_1');
console.log(websiteId3); // 'berlin_1' (special case)

// Get all available websites
const websites = mapper.getWebsites();
console.log(websites); // ['base', 'flaconi_at', 'flaconi_ch', 'flaconi_fr', 'flaconi_it', 'flaconi_pl', 'berlin_1', 'berlin_2']

Complete Migration Example

// Before: Using LocaleMapper in your service
// const language = this.localeMapper.getLanguageByWebsite(newPrice.websites);
// const store = this.localeMapper.getStoreByWebsite(newPrice.websites);
// const currency = this.localeMapper.getCurrencyByStore(store);

// After: Using MetadataMapper (drop-in replacement)
const language = mapper.getLanguageByWebsite(newPrice.websites);
const store = mapper.getStoreByWebsite(newPrice.websites);
const currency = mapper.getCurrencyByStore(store);

console.log(`Website: ${newPrice.websites}`); // 'base'
console.log(`Language: ${language}`);         // 'de-DE'
console.log(`Store: ${store}`);              // 'DE'
console.log(`Currency: ${currency}`);        // 'EUR'

Real-World Price Processing Example

import { MetadataMapper, defaultFlaconiMetadata } from '@flaconi/metadata-mapper';

// Initialize the mapper (replaces your LocaleMapper instance)
const mapper = new MetadataMapper(defaultFlaconiMetadata);

// Example: Processing price data objects
interface PriceData {
  websites: string; // e.g., 'base', 'flaconi_at', 'berlin_1'
  price: number;
  // ... other fields
}

function processPriceData(newPrice: PriceData) {
  // This exact line from your codebase now works with MetadataMapper:
  const language = mapper.getLanguageByWebsite(newPrice.websites);
  
  // Get additional context for processing
  const store = mapper.getStoreByWebsite(newPrice.websites);
  const currency = mapper.getCurrencyByStore(store);
  const channel = mapper.getChannelByStore(store);
  
  console.log(`Processing price for website: ${newPrice.websites}`);
  console.log(`→ Language: ${language}`);
  console.log(`→ Store: ${store}`);
  console.log(`→ Currency: ${currency}`);
  console.log(`→ Channel: ${channel}`);
  
  return {
    language,
    store,
    currency,
    channel
  };
}

// Example usage with different website identifiers
processPriceData({ websites: 'base', price: 29.99 });       // German store
processPriceData({ websites: 'flaconi_at', price: 29.99 }); // Austrian store
processPriceData({ websites: 'berlin_1', price: 29.99 });   // Berlin physical store

Configuration Options

import { MetadataMapper, defaultFlaconiMetadata } from '@flaconi/metadata-mapper';

// Use with default embedded data (no external dependencies)
const mapper = new MetadataMapper(defaultFlaconiMetadata);

// Or use with custom metadata (useful for testing)
const customMetadata = {
  stores: {
    us: {
      languages: ['en-US'],
      currency: 'USD',
      priceChannel: 'flaconi-us'
    }
  }
};
const customMapper = new MetadataMapper(customMetadata);

// Methods return values directly or throw errors for invalid input
try {
  const language = mapper.getLanguageByStore('US'); // Throws if 'US' doesn't exist
  console.log(language);
} catch (error) {
  console.error('Store not found:', error.message);
}

Error Handling

// The library throws descriptive errors for invalid input
try {
  const language = mapper.getLanguageByStore('INVALID_STORE');
} catch (error) {
  console.error('Store not found:', error.message);
  // Error: Language not found for store: INVALID_STORE
}

try {
  const store = mapper.getStoreByWebsite('invalid_website');
} catch (error) {
  console.error('Website not found:', error.message);
  // Error: Store not found for website: invalid_website
}

Utility Methods

// Get all available stores (including special stores like BERLIN_1, BERLIN_2)
const stores = mapper.getStores();
console.log(stores); // ['DE', 'AT', 'CH', 'FR', 'IT', 'PL', 'BERLIN_1', 'BERLIN_2']

// Get all available website identifiers
const websites = mapper.getWebsites();
console.log(websites); // ['base', 'flaconi_at', 'flaconi_ch', 'flaconi_fr', 'flaconi_it', 'flaconi_pl', 'berlin_1', 'berlin_2']

// Direct mapping without additional lookups
const websiteId = mapper.mapStoreToWebsiteId('ch');
console.log(websiteId); // 'flaconi_ch'

API Reference

Core Methods

MethodParametersReturnsDescription
getLanguageByStore(store)store: stringstringGet language code by store (expects uppercase)
getCurrencyByStore(store)store: stringstringGet currency code by store
getChannelByStore(store)store: stringstringGet price channel by store
getLanguageByWebsite(website)website: stringstringGet language code by website identifier
getStoreByWebsite(website)website: stringstringGet store code by website identifier
mapStoreToWebsiteId(store)store: stringstringMap store code to website identifier
getStores()-string[]Get all available store codes
getWebsites()-string[]Get all available website identifiers

FlaconiMetadata Structure

interface FlaconiMetadata {
  stores: Record<string, {
    languages: string[];    // Array of supported languages (first is primary)
    currency: string;       // ISO 4217 currency code
    priceChannel: string;   // Price channel identifier
  }>;
  physicalStores?: Record<string, {
    languages: string[];    // Languages for physical stores
    currency: string;       // Currency for physical stores
    priceChannel: string;   // Price channel for physical stores
  }>;
}

Architecture

The library is built with the following principles:

  • Embedded Data: Uses embedded metadata by default (no external dependencies)
  • Synchronous Operations: All methods are synchronous for better performance
  • Type Safety: Comprehensive TypeScript interfaces and strict typing
  • Error Handling: Throws descriptive errors for invalid input
  • Memory Efficient: Lightweight with minimal memory footprint

Mapping Logic

  • Store Codes: Input normalized to uppercase for consistency
  • Website Mapping:
    • de store → base website
    • berlin_1 store → berlin_1 website (special case)
    • berlin_2 store → berlin_2 website (special case)
    • Other stores → flaconi_{storeCode} website
  • Store Merging: Combines regular stores with physical stores (e.g., BERLIN_1, BERLIN_2)
  • Language Fallback: Uses first language from the languages array

Testing

The library includes comprehensive tests with 100% coverage:

# Run tests
yarn test

# Run tests with coverage
yarn test:coverage

# Run tests in watch mode
yarn test:watch

Development

# Install dependencies
yarn install

# Run type checking
yarn type-check

# Run linting
yarn lint

# Build the library
yarn build

# Run all checks (used in CI)
yarn prepublishOnly

Build Outputs

The library provides multiple build formats:

  • ESM: dist/esm/ - ES Modules for modern bundlers
  • CommonJS: dist/cjs/ - CommonJS for Node.js
  • Types: dist/types/ - TypeScript declaration files

Release Process

Beta Releases

Beta versions are automatically published for feature branches:

git checkout -b feature/my-feature
git push origin feature/my-feature
# Publishes as @flaconi/metadata-mapper@x.x.x-beta.feature-my-feature.sha123

Stable Releases

Stable versions are published when merging to main/master:

  • Update version in package.json
  • Update CHANGELOG.md
  • Create PR and merge to main
  • Stable version is automatically published

Contributing

  • Fork the repository
  • Create a feature branch: git checkout -b feature/my-feature
  • Make changes and add tests
  • Run the test suite: yarn test
  • Run linting: yarn lint
  • Commit changes: git commit -am 'Add my feature'
  • Push to the branch: git push origin feature/my-feature
  • Create a Pull Request

Development Guidelines

  • Maintain 100% test coverage
  • Follow the existing code style
  • Add JSDoc comments for public APIs
  • Update README for new features
  • Use conventional commit messages

License

This project is licensed under the MIT License - see the LICENSE file for details.

About Flaconi

This library is developed and maintained by Flaconi GmbH. Flaconi is one of the leading online beauty retailers in Europe.

Need help? Create an issue in the GitHub repository.

Keywords

flaconi

FAQs

Package last updated on 21 Nov 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts