Built-in Transforms
The FDS Transformer includes a set of built-in transform functions for common data manipulation tasks. These can be used in the transform property of field mappings.
Transform Reference
slugify
Convert a string to a URL-safe slug.
Input: String
Output: String
{
"canonical.slug": {
"from": "name",
"transform": "slugify"
}
}
Examples:
| Input | Output |
|---|---|
"Barbell Bench Press" | "barbell-bench-press" |
"Cable Fly (Low)" | "cable-fly-low" |
"Push-Up" | "push-up" |
Behavior:
- Converts to lowercase
- Replaces spaces with hyphens
- Removes special characters
- Collapses multiple hyphens
titleCase
Convert a string to Title Case.
Input: String
Output: String
{
"canonical.name": {
"from": "name",
"transform": "titleCase"
}
}
Examples:
| Input | Output |
|---|---|
"barbell bench press" | "Barbell Bench Press" |
"DEADLIFT" | "Deadlift" |
"push-up" | "Push-Up" |
uuid
Generate a UUIDv4 string. FDS requires plain UUIDs for all identifiers.
Input: Any (ignored)
Output: String
{
"exerciseId": {
"from": null,
"transform": "uuid"
}
}
Example Output: "550e8400-e29b-41d4-a716-446655440000"
toArray
Ensure a value is wrapped in an array.
Input: Any
Output: Array
{
"targets.primary": {
"from": "target",
"transform": "toArray"
}
}
Examples:
| Input | Output |
|---|---|
"chest" | ["chest"] |
["chest", "shoulders"] | ["chest", "shoulders"] |
null | [] |
toMediaArray
Convert URLs to FDS media format.
Input: String, Array of strings, or Array of objects
Output: Array of MediaItem objects
Options:
| Option | Type | Default | Description |
|---|---|---|---|
defaultType | string | "image" | Default media type |
inferType | boolean | true | Infer type from file extension |
{
"media": {
"from": "images",
"transform": "toMediaArray",
"options": {
"defaultType": "image",
"inferType": true
}
}
}
Input:
["https://example.com/bench-press.jpg", "https://example.com/video.mp4"]
Output:
[
{ "type": "image", "uri": "https://example.com/bench-press.jpg" },
{ "type": "video", "uri": "https://example.com/video.mp4" }
]
Type Inference:
| Extension | Type |
|---|---|
.jpg, .jpeg, .png, .gif, .webp, .svg | image |
.mp4, .webm, .mov, .avi | video |
.pdf, .md, .txt | doc |
.glb, .gltf, .obj | 3d |
registryLookup
Look up a value in a registry with optional fuzzy matching.
Input: String or Array
Output: Object or Array of objects
Options:
| Option | Type | Default | Description |
|---|---|---|---|
registry | string | Required | Registry name: muscles, equipment, muscleCategories |
fuzzyMatch | boolean | false | Enable fuzzy matching |
threshold | number | 0.8 | Fuzzy match threshold (0-1) |
field | string | "canonical.name" | Field to match against |
returnFormat | string | "object" | Return format: object, array, ref |
includeAliases | boolean | true | Include aliases in matching |
{
"targets.primary": {
"from": "target",
"transform": "registryLookup",
"options": {
"registry": "muscles",
"fuzzyMatch": true,
"threshold": 0.8,
"returnFormat": "array"
}
}
}
Input: "pectorals"
Output:
[
{
"id": "mus.pectoralis-major",
"name": "Pectoralis Major",
"slug": "pectoralis-major",
"categoryId": "cat.chest"
}
]
Return Formats:
object- Full registry entryarray- Wrapped in arrayref- FDS reference format ({ id, name, slug, categoryId })
timestamp
Generate an ISO 8601 timestamp.
Input: Any (ignored)
Output: String
{
"metadata.createdAt": {
"from": null,
"transform": "timestamp"
}
}
Example Output: "2025-01-27T15:30:00.000Z"
autoGenerate
Auto-generate metadata fields.
Input: Any (ignored)
Output: Object
Options:
| Option | Type | Default | Description |
|---|---|---|---|
fields | string[] | All fields | Fields to generate |
{
"metadata": {
"from": null,
"transform": "autoGenerate",
"options": {
"fields": ["createdAt", "updatedAt", "status"]
}
}
}
Output:
{
"createdAt": "2025-01-27T15:30:00.000Z",
"updatedAt": "2025-01-27T15:30:00.000Z",
"status": "active"
}
Available Fields:
| Field | Generated Value |
|---|---|
createdAt | Current ISO timestamp |
updatedAt | Current ISO timestamp |
status | "active" |
version | "1.0.0" |
source | "fds-transformer" |
template
Apply a template string with variable substitution.
Input: Object (context)
Output: String
Options:
| Option | Type | Required | Description |
|---|---|---|---|
template | string | Yes | Template string with {{field}} placeholders |
defaultValue | string | No | Default for missing fields |
{
"canonical.description": {
"from": ["name", "target", "equipment"],
"transform": "template",
"options": {
"template": "{{name}} is an exercise targeting the {{target}} using {{equipment}}."
}
}
}
Context:
{
"name": "Barbell Bench Press",
"target": "chest",
"equipment": "barbell"
}
Output: "Barbell Bench Press is an exercise targeting the chest using barbell."
urlTransform
Transform URLs with pattern matching.
Input: String (URL)
Output: String
Options:
| Option | Type | Description |
|---|---|---|
pattern | string | Regex pattern to match |
replacement | string | Replacement string |
prefix | string | Prefix to add |
suffix | string | Suffix to add |
{
"media[0].uri": {
"from": "imageUrl",
"transform": "urlTransform",
"options": {
"pattern": "http://",
"replacement": "https://"
}
}
}
Input: "http://example.com/image.jpg"
Output: "https://example.com/image.jpg"
Chaining Transforms
Apply multiple transforms in sequence:
{
"canonical.slug": {
"from": "name",
"transform": ["titleCase", "slugify"]
}
}
Transforms are applied left to right. The output of each transform becomes the input of the next.
Example:
- Input:
"barbell BENCH press" - After
titleCase:"Barbell Bench Press" - After
slugify:"barbell-bench-press"
Using with Registry Lookup
Common pattern for muscle/equipment mapping:
{
"targets.primary": {
"from": "target",
"transform": ["toArray", "registryLookup"],
"options": {
"registry": "muscles",
"fuzzyMatch": true,
"returnFormat": "ref"
}
}
}
This:
- Wraps the value in an array if needed
- Looks up each value in the muscles registry
- Returns FDS reference format
Transform Context
All transforms receive a context object with:
interface TransformContext {
source: Record<string, unknown>; // Original source data
target: Record<string, unknown>; // Current FDS object being built
field: string; // Current field path
registries: {
muscles: RegistryEntry[];
equipment: RegistryEntry[];
muscleCategories: RegistryEntry[];
};
config: MappingConfig; // Full mapping configuration
}
This enables transforms to access other fields and configuration.
See Also
- Plugin Development - Create custom transforms
- Configuration - Mapping config reference
- Examples - Complete workflows