Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

transmutant

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

transmutant - npm Package Compare versions

Comparing version 2.0.0 to 2.1.0

11

dist/index.js

@@ -29,9 +29,6 @@ "use strict";

*/
const transmute = (schema, source, extra) => schema.reduce((acc, { from, to, fn }) => {
var _a;
return ({
...acc,
[to]: fn ? fn({ source, extra }) : (_a = source[from]) !== null && _a !== void 0 ? _a : null
});
}, {});
const transmute = (schema, source, extra) => schema.reduce((acc, { from, to }) => ({
...acc,
[to]: typeof from === 'function' ? from({ source, extra }) : source[from]
}), {});
exports.transmute = transmute;
/**
* Arguments passed to a mutation function
* @template From - The source type being transmuted from
* @template Source - The source type being transmuted from
* @template TExtra - Type of additional data for transmutation
*/

@@ -13,21 +14,21 @@ export type TransmuteFnArgs<Source, TExtra> = {

* Function that performs a custom transmutation on a source object
* @template From - The source type being transmuted from
* @template Source - The source type being transmuted from
* @template Target - The target type being transmuted to
* @template TargetKey - The specific key of the target property being set
* @template TExtra - Type of additional data for transmutation
*/
export type TransmuteFn<Source, TExtra = unknown> = (args: TransmuteFnArgs<Source, TExtra>) => unknown;
export type TransmuteFn<Source, Target, TargetKey extends keyof Target, TExtra = unknown> = (args: TransmuteFnArgs<Source, TExtra>) => Target[TargetKey];
/**
* Defines how a property should be transmuted from source to target type
* @template From - The source type being transmuted from
* @template To - The target type being transmuted to
* @template Source - The source type being transmuted from
* @template Target - The target type being transmuted to
* @template TExtra - Type of additional data for transmutation
*/
export type Schema<Source, Target, TExtra = unknown> = {
/** Target property key */
to: keyof Target;
} & ({
/** Source property key for direct mapping */
from: keyof Source;
fn?: never;
} | {
/** Custom transmutation function */
fn: TransmuteFn<Source, TExtra>;
from?: never;
});
[TargetKey in keyof Target]: {
/** Target property key */
to: TargetKey;
/** Source property key for direct mapping or a custom transmutation function */
from: keyof Source | TransmuteFn<Source, Target, TargetKey, TExtra>;
};
}[keyof Target];
{
"name": "transmutant",
"version": "2.0.0",
"version": "2.1.0",
"main": "dist/index.js",

@@ -29,2 +29,10 @@ "types": "dist/index.d.ts",

"description": "Powerful type transmutations for TypeScript 🧬",
"repository": {
"type": "git",
"url": "git+https://github.com/tonioriol/transmutant.git"
},
"homepage": "https://github.com/tonioriol/transmutant#readme",
"bugs": {
"url": "https://github.com/tonioriol/transmutant/issues"
},
"devDependencies": {

@@ -31,0 +39,0 @@ "@types/jest": "^29.5.14",

@@ -1,5 +0,19 @@

# Transmutant
# 🧬 Transmutant 🧬
A lightweight TypeScript library for flexible object transmutation with type safety.
A powerful, type-safe TypeScript library for transforming objects through flexible schema definitions.
[![npm version](https://badge.fury.io/js/transmutant.svg)](https://www.npmjs.com/package/transmutant)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![GitHub issues](https://img.shields.io/github/issues/tonioriol/transmutant)](https://github.com/tonioriol/transmutant/issues)
[![GitHub stars](https://img.shields.io/github/stars/tonioriol/transmutant)](https://github.com/tonioriol/transmutant/stargazers)
## Features
- 🔒 **Type-safe**: Full TypeScript support with strong type inference
- 🎯 **Flexible mapping**: Direct property mapping or custom transformation functions
- ⚡ **High performance**: Minimal overhead and zero dependencies
- 🔄 **Extensible**: Support for custom transformation logic and external data
- 📦 **Lightweight**: Zero dependencies, small bundle size
- 🛠️ **Predictable**: Transparent handling of undefined values
## Installation

@@ -11,15 +25,67 @@

## Features
## Quick Start
- 🔒 Type-safe transmutations
- 🎯 Direct property mapping
- ⚡ Custom transmutation functions
- 🔄 Flexible schema definition
- 📦 Zero dependencies
```typescript
import { transmute, Schema } from 'transmutant';
## Usage
// Source type
interface User {
firstName: string;
lastName: string;
email: string;
}
### Direct Property Mapping
// Target type
interface UserDTO {
fullName: string;
contactEmail: string;
}
// Define transformation schema
const schema: Schema<User, UserDTO>[] = [
{
to: 'fullName',
from: ({ source }) => `${source.firstName} ${source.lastName}`
},
{
from: 'email',
to: 'contactEmail'
}
];
// Transform the object
const user: User = {
firstName: 'John',
lastName: 'Doe',
email: 'john@example.com'
};
const userDTO = transmute(schema, user);
// Result: { fullName: 'John Doe', contactEmail: 'john@example.com' }
```
## Core Concepts
### Schema Definition
A schema is an array of transformation rules that define how properties should be mapped from the source to the target type. Each rule specifies the target property key and either a source property key for direct mapping or a transformation function that produces the correct type for that target property.
```typescript
type Schema<Source, Target, TExtra = unknown> = {
[TargetKey in keyof Target]: {
/** Target property key */
to: TargetKey
/** Source property key for direct mapping or a custom transformation function */
from: keyof Source | TransmuteFn<Source, Target, TargetKey, TExtra>
}
}[keyof Target]
```
### Transformation Types
#### 1. Direct Property Mapping
Map a property directly from source to target:
```typescript
interface Source {

@@ -36,19 +102,15 @@ email: string;

];
```
const source: Source = { email: 'john@example.com' };
const target = transmute(schema, source);
#### 2. Custom Transformation Functions
// Result: { contactEmail: 'john@example.com' }
```
Transform properties using custom logic with type safety:
### Using Custom Transmutation Functions
```typescript
interface Source {
firstName: string;
lastName: string;
age: number;
}
interface Target {
fullName: string;
isAdult: boolean;
}

@@ -58,104 +120,211 @@

{
to: 'fullName',
fn: ({ source }) => `${source.firstName} ${source.lastName}`
to: 'isAdult',
from: ({ source }) => source.age >= 18
}
];
```
const source: Source = { firstName: 'John', lastName: 'Doe' };
const target = transmute(schema, source);
#### 3. External Data Transformations
// Result: { fullName: 'John Doe' }
```
Include additional context in transformations:
### Using Extra Data
```typescript
interface Source {
city: string;
country: string;
price: number;
}
interface Target {
location: string;
formattedPrice: string;
}
interface Extra {
separator: string;
interface ExtraData {
currency: string;
}
const schema: Schema<Source, Target, Extra>[] = [
const schema: Schema<Source, Target, ExtraData>[] = [
{
to: 'location',
fn: ({ source, extra }) =>
`${source.city}, ${source.country}${extra?.separator}`
to: 'formattedPrice',
from: ({ source, extra }) =>
`${source.price.toFixed(2)} ${extra.currency}`
}
];
```
const source: Source = {
city: 'New York',
country: 'USA'
};
### Handling Undefined Values
const target = transmute(schema, source, { separator: ' | ' });
When a source property doesn't exist or a transformation function returns undefined, the target property will remain undefined:
// Result: { location: 'New York, USA | ' }
```typescript
interface Source {
existingField: string;
}
interface Target {
mappedField: string;
computedField: string;
}
const schema: Schema<Source, Target>[] = [
{
from: 'nonExistentField' as keyof Source, // Property doesn't exist
to: 'mappedField'
},
{
to: 'computedField',
from: ({ source }) => undefined // Transformation returns undefined
}
];
const result = transmute(schema, { existingField: 'value' });
// Result: { mappedField: undefined, computedField: undefined }
```
This allows you to:
- Distinguish between unset values (`undefined`) and explicitly set null values
- Handle optional properties naturally
- Process partial transformations as needed
## API Reference
### `transmute(schema, source, extra?)`
### `transmute<Source, Target, TExtra = unknown>`
Transmutes a source object into a target type based on the provided schema.
Main transformation function.
#### Parameters
- `schema`: Array of transmutation rules defining how properties should be transmuted
- `source`: Source object to transmute
- `extra`: (Optional) Additional data to pass to transmutation functions
| Parameter | Type | Description |
|-----------|------------------------------------|-------------------------------|
| schema | `Schema<Source, Target, TExtra>[]` | Array of transformation rules |
| source | `Source` | Source object to transform |
| extra? | `TExtra` | Optional additional data |
#### Schema Types
#### Returns
Each schema entry must specify the target property and use either direct mapping OR a custom function:
Returns an object of type `Target`.
### Type Definitions
```typescript
type Schema<Source, Target, TExtra> = {
/** Target property key */
to: keyof Target;
} & (
| {
/** Source property key for direct mapping */
from: keyof Source;
fn?: never;
}
| {
/** Custom transmutation function */
fn: TransmuteFn<Source, TExtra>;
from?: never;
}
);
/**
* Schema entry defining how a property should be transformed
*/
type Schema<Source, Target, TExtra = unknown> = {
[TargetKey in keyof Target]: {
/** Target property key */
to: TargetKey
/** Source property key for direct mapping or a custom transformation function */
from: keyof Source | TransmuteFn<Source, Target, TargetKey, TExtra>
}
}[keyof Target]
/**
* Function that performs property transformation
*/
type TransmuteFn<Source, Target, TargetKey extends keyof Target, TExtra = unknown> =
(args: TransmuteFnArgs<Source, TExtra>) => Target[TargetKey]
/**
* Arguments passed to transformation function
*/
type TransmuteFnArgs<Source, TExtra> = {
source: Source
extra?: TExtra
}
```
The `TransmuteFn` type is defined as:
### Type Safety Examples
```typescript
type TransmuteFn<Source, TExtra> = (args: {
source: Source;
extra?: TExtra;
}) => unknown;
interface Source {
firstName: string;
lastName: string;
age: number;
}
interface Target {
fullName: string; // TargetKey = 'fullName', type = string
isAdult: boolean; // TargetKey = 'isAdult', type = boolean
}
// TypeScript enforces correct return types
const schema: Schema<Source, Target>[] = [
{
to: 'fullName',
from: ({ source }) => `${source.firstName} ${source.lastName}` // Must return string
},
{
to: 'isAdult',
from: ({ source }) => source.age >= 18 // Must return boolean
}
];
// Type error example:
const invalidSchema: Schema<Source, Target>[] = [
{
to: 'isAdult',
from: ({ source }) => source.age // Type error: number is not assignable to boolean
}
];
```
#### Behavior Notes
### Direct Property Mapping
- Direct mapping uses the `from` property to copy values directly from source to target
- Custom functions receive the entire source object and optional extra data
- If a direct mapping property is undefined or null, it will be set to `null` in the target object
- Empty schemas result in an empty object
- Each schema entry must use either `from` OR `fn`, but not both
- The schema is processed sequentially, with each rule contributing to the final object
When using direct property mapping, TypeScript ensures type compatibility:
## License
```typescript
interface Source {
email: string;
age: number;
}
MIT
interface Target {
contactEmail: string;
yearOfBirth: number;
}
const schema: Schema<Source, Target>[] = [
{ from: 'email', to: 'contactEmail' }, // OK: string -> string
{ from: 'age', to: 'yearOfBirth' } // OK: number -> number
];
```
### Using Extra Data
Extra data is fully typed:
```typescript
interface ExtraData {
currentYear: number;
}
interface Source {
age: number;
}
interface Target {
yearOfBirth: number;
}
const schema: Schema<Source, Target, ExtraData>[] = [
{
to: 'yearOfBirth',
from: ({ source, extra }) => extra.currentYear - source.age
}
];
const result = transmute(schema, { age: 25 }, { currentYear: 2024 });
```
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Contributions are welcome! Feel free to submit a Pull Request.
## License
MIT © Antoni Oriol
---
<div align="center">
<sub>Built with ❤️ by <a href="https://github.com/tonioriol">Antoni Oriol</a></sub>
</div>
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc