Mapstronaut is a lightweight and flexible JavaScript/TypeScript library for transforming objects. It simplifies complex object manipulation by defining mapping rules, letting you focus on the data, not the boilerplate code.
- Declarative Approach: Define your mapping structure as an array of rules. It's easy to read, understand, and maintain.
- Advanced Data Selection: Uses JSONPath to precisely select source properties, even from complex nested objects and arrays. Uses dot-prop to select target properties.
- Automapping: Can automatically map properties with matching names and types, saving you from defining obvious mappings.
- High-Performance Async: Supports parallel asynchronous mapping, offering a significant performance boost for I/O-heavy transformations.
Developer's note: I used Typescript for a long time before having to switch to Java a few years ago. I love using the popular object mapper Mapstruct and was inspired by it for Mapstronaut.
npm i mapstronautAll examples will use the following space mission data:
const spaceMissionData = {
  mission: {
    id: "artemis-3",
    name: "Artemis III",
    status: "planned",
    launch: {
      date: "2027-07-15T14:30:00Z",
      site: "Kennedy Space Center",
    },
  },
  crew: [
    { id: "cmdr-001", name: "Sarah Chen", role: "commander", experience: 2840 },
    {
      id: "plt-002",
      name: "Marcus Rodriguez",
      role: "pilot",
      experience: 1650,
    },
  ],
  spacecraft: {
    name: "Orion",
    modules: ["crew", "service"],
    fuel: { type: "liquid", amount: 95.5 },
  },
};import { mapObject } from "mapstronaut";
const structure = [
  ["mission.name", "missionTitle"],
  ["mission.launch.date", "scheduledDate"],
  ["crew[0].name", "commander"],
  ["spacecraft.fuel.amount", "spacecraft.fuelLevel"],
];
const result = mapObject(structure, spaceMissionData);
// Result:
// {
//   missionTitle: "Artemis III",
//   scheduledDate: "2027-07-15T14:30:00Z",
//   commander: "Sarah Chen"
//   spacecraft: {
//     fuelLevel: 95.5
//   }
// }Apply transformations and conditional logic during mapping:
import { mapObject } from "mapstronaut";
const structure = [
  {
    source: "mission.launch.date",
    target: "launchYear",
    transform: (date) => new Date(date).getFullYear(),
  },
  {
    source: "crew",
    target: "activeCrew",
    filter: (crew, source) => source.mission.status === "in-progress",
  },
  {
    source: "spacecraft.fuel.amount",
    target: "fuelStatus",
    transform: (amount) => (amount > 90 ? "ready" : "needs-refuel"),
  },
];
const result = mapObject(structure, spaceMissionData);
// Result:
// {
//   launchYear: 2027,
//   fuelStatus: "ready"
// }
// // activeCrew is filtered outimport { mapObjectAsync } from "mapstronaut";
// Simulate external API calls
const fetchWeatherData = (site) =>
  new Promise((resolve) =>
    setTimeout(() => resolve({ temp: 22, conditions: "clear" }), 100),
  );
const fetchCrewCertification = (crewId) =>
  new Promise((resolve) =>
    setTimeout(() => resolve({ certified: true, expires: "2027-01-01" }), 150),
  );
const structure = [
  ["mission.name", "title"],
  {
    source: "mission.launch.site",
    target: "weather",
    transform: async (site) => await fetchWeatherData(site),
  },
  {
    source: "crew[0].id",
    target: "commanderStatus",
    transform: async (id) => await fetchCrewCertification(id),
  },
];
const result = await mapObjectAsync(structure, spaceMissionData, undefined, {
  parallelRun: true,
});
// Result:
// {
//   title: "Artemis III",
//   weather: { temp: 22, conditions: 'clear' },
//   commanderStatus: { certified: true, expires: '2027-01-01' }
// }- Basic Usage
- Options reference
- Mapping rules
- Defining sources
- Defining targets
- Async mapping
- Automapping
- Advanced Usage
- Using dot-prop for better target properties selection
- Improved automapping with deep merging of object and arrays
- Added maximum number of parallel jobs option in async mapping
- Improved and tested documentation to help you get the most out of the library
Contributions are welcome! If you have a feature request, bug report, or want to improve the code, please feel free to open an issue or submit a pull request.
This project is licensed under the MIT License.
Built by Jonathan Prevost.
