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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@edirect/template

v1.2.4

Published

Template Module

Downloads

275

Readme

@edirect/template

TemplateModule is a library that provides methods to transform a payload based on a given template. The transformation includes mapping fields, applying transformers, setting default values and so on.

Installation

$ npm i --save @edirect/template

Import

import { TemplateModule } from "./TemplateModule";

Methods

Constructor

The TemplateModule class does not have a constructor.

setContext(context): void

Sets the context object to be used during the transformation.

setTemplate(template): void

Sets the template object that describes the transformation to be performed.

setTransformers(transformers: ITransformer): void

Sets the transformers to be used during the transformation.

setOptions(transformers: ITemplateOptions): void

Sets the options to be used during and after the transformation.

verifyTransformer(transformer: ITransformer, methodName: string): boolean

Verifies if a given transformer method exists.

runTransformer(transformer: string, value?: unknown): unknown | null

Runs a transformer on a given value.

  • transformer - The name of the transformer to be used.
  • value - The value to be transformed.

checkValue(value: any): boolean

Checks if a given value is not null, undefined, or an empty string.

setValueByCondition(object, key: string, value: unknown)

Sets a value in an object after verify using the checkValue() method.

  • object - The object to be modified.
  • key - The key of the value to be set.
  • value - The value to be set.

transformPayload<T, U>(obj: T, template = this.template): U

Transforms a payload object on a given template.

Simple example

import { TemplateModule } from "@edirect/template";

const template = {
  edirect_firstname: "subscriber.firstName",
  edirect_lastname: "subscriber.lastName",
};

const dataSource = {
  subscriber: {
    firstName: "template",
    lastName: "service",
  },
};

const templateModule = new TemplateModule();
templateModule.setTemplate(template);

const result = templateModule.transformPayload(dataSource);

console.log(result);

// {
//   edirect_firstname: "template",
//   edirect_lastname: "service",
// }

Example with transformers

First of all, what's a transformer?

A transformer is a way to handle values with more detail and freedom.

For example:

  • Mapping
  • Validation
  • Formatting
  • Business rules
  • and so on ...

Each transformer receives two parameters:

  • value: specific value that you want to handle
  • context: all context (payload) that you can use to build any logical

To map a value that you'd like to use some transformer feature, you can use these options:

  • fields: it's an array with a data source path, and the first value that is found will be used.
  • transformer: it's a JS function, where you receive value and context as parameters and have all freedom to handle and return a value
  • defaultValue it's an option if the engine doesn't find any value in the fields data source array or the transformer doesn't return a value.
File name: baseTransformers.ts
import { ITransformer, ITransformerParams } from "@edirect/template";

const upperCase = ({ value }: ITransformerParams): string | null => {
  return value ? String(value).toUpperCase() : null;
};

const fullName = ({ context }: ITransformerParams): string | null => {
  try {
    const { firstName, lastName } = context.subscriber;
    return `${firstName} ${lastName}`;
  } catch (error) {
    return null;
  }
};

const transformers: ITransformer = {
  upperCase,
  fullName,
};

export default transformers;
File name: index.ts
import { TemplateModule } from "@edirect/template";
import baseTransformers from "./baseTransformers";

const template = {
  edirect_firstname: {
    fields: ["firstName", "subscriber.firstName"],
    transformer: "upperCase",
    defaultValue: "First Name - Default",
  },
  edirect_lastname: {
    fields: ["lastName", "subscriber.lastName"],
  },
  edirect_fullname: {
    transformer: "fullName",
  },
  edirect_phone: {
    fields: ["phoneNumber", "subscriber.phoneNumber"],
    defaultValue: "999999999",
  },
  timeZone: {
    defaultValue: "Time zone in Porto (GMT+1)",
  },
};

const dataSource = {
  subscriber: {
    firstName: "template",
    lastName: "service",
  },
};

const templateModule = new TemplateModule();

templateModule.setTemplate(template);
templateModule.setContext(dataSource);
templateModule.setTransformers(baseTransformers);

const result = templateModule.transformPayload(dataSource);
console.log(result);

// {
//   edirect_firstname: "TEMPLATE",
//   edirect_lastname: "service",
//   edirect_fullname: "template service",
//   edirect_phone: "999999999",
//   timeZone: "Time zone in Porto (GMT+1)",
// }

Example with nested object + transformers

Note: the transformer notation uses three keys to identify an object as being a transformer: fields, transformer, and defaultValue, if there are at least 1 of these keys, the engine will consider the object as being a transformer, on the other hand, if there isn't, the engine will consider as a nested object to mapper all information.

File name: baseTransformers.ts
import { ITransformer, ITransformerParams } from "@edirect/template";

const upperCase = ({ value }: ITransformerParams): string | null => {
  return value ? String(value).toUpperCase() : null;
};

const transformers: ITransformer = {
  upperCase,
};

export default transformers;
File name: index.ts
import { TemplateModule } from "@edirect/template";
import baseTransformers from "./baseTransformers";

const template = {
  order: {
    date: "order.date",
    value: "order.value",
    subscriber: {
      name: "sub.name",
      phone: "sub.phone",
      email: {
        fields: ["email", "sub.email"],
      },
      address: {
        street: "sub.add.stt",
        number: "sub.add.num",
        city: {
          fields: ["sub.add.city"],
          transformer: "upperCase",
        },
        state: {
          fields: ["sub.add.stt"],
          transformer: "upperCase",
        },
        zip: {
          fields: ["sub.add.zip"],
          defaultValue: "0000-000",
        },
      },
    },
  },
};

const dataSource = {
  order: {
    value: 1000.0,
    date: "2000-01-01",
  },
  sub: {
    name: "name-test",
    phone: "999999999",
    email: "[email protected]",
    add: {
      st: "st-test",
      num: 100,
      city: "city-test",
      stt: "state-test",
      zip: "zip-test",
    },
  },
};

const templateModule = new TemplateModule();

templateModule.setTemplate(template);
templateModule.setContext(dataSource);
templateModule.setTransformers(baseTransformers);

const result = templateModule.transformPayload(dataSource);
console.log(result);

// {
//   order: {
//     date: "2000-01-01",
//     value: 1000,
//     subscriber: {
//       name: "name-test",
//       phone: "999999999",
//       email: "[email protected]",
//       address: {
//         street: "state-test",
//         number: 100,
//         city: "CITY-TEST",
//         state: "STATE-TEST",
//         zip: "zip-test",
//       },
//     },
//   },
// }

Example with arrays + transformers

Note: When it comes to arrays mapper, we need to have in mind that is required use this two keys: arraySource and arrayTemplate.

  • arraySource: source path where the engine will seek the information to mapper
  • arrayTemplate: template that will be used for each object within the array
File name: baseTransformers.ts
import { ITransformer, ITransformerParams } from "@edirect/template";

const upperCase = ({ value }: ITransformerParams): string | null => {
  return value ? String(value).toUpperCase() : null;
};

const transformers: ITransformer = {
  upperCase,
};

export default transformers;
File name: index.ts
import { TemplateModule } from "@edirect/template";
import baseTransformers from "./baseTransformers";

const template = {
  quote: {
    orders: {
      arraySource: "order",
      arrayTemplate: {
        value: "value",
        date: "date",
        products: {
          arraySource: "products",
          arrayTemplate: {
            id: "id",
            value: "value",
            description: {
              fields: ["description"],
              transformer: "upperCase",
              defaultValue: "Default description",
            },
            categories: "categories",
          },
        },
      },
    },
  },
};

const dataSource = {
  order: [
    {
      value: 1000.0,
      date: "2000-01-01",
      products: [
        {
          id: "id-test-1",
          value: 1000,
          description: "description-test 1",
          categories: ["category-1"],
        },
        {
          id: "id-test-2",
          value: 2000,
          description: "description-test 2",
          categories: ["category-1", "category-2"],
        },
        {
          id: "id-test-3",
          value: 3000,
          categories: ["category-1", "category-2", "category-3"],
        },
      ],
    },
  ],
};

const templateModule = new TemplateModule();

templateModule.setTemplate(template);
templateModule.setContext(dataSource);
templateModule.setTransformers(baseTransformers);

const result = templateModule.transformPayload(dataSource);
console.log(result);

//{
//  quote: {
//     orders: [
//       {
//         value: 1000,
//         date: "2000-01-01",
//         products: [
//           {
//             id: "id-test-1",
//             value: 1000,
//             description: "DESCRIPTION-TEST 1",
//             categories: ["category-1"],
//           },
//           {
//             id: "id-test-2",
//             value: 2000,
//             description: "DESCRIPTION-TEST 2",
//             categories: ["category-1", "category-2"],
//           },
//           {
//             id: "id-test-3",
//             value: 3000,
//             description: "Default description",
//             categories: ["category-1", "category-2", "category-3"],
//           },
//         ],
//       },
//     ],
//   },
// }

Template example with transformer + transformerParams

File name: baseTransformers.ts
import { ITransformer, ITransformerParams } from "@edirect/template";

const concat = (
  { value }: ITransformerParams,
  ...itensToConcat: string[]
): string => {
  const arrayToConcat = [value, ...itensToConcat];
  return arrayToConcat.join("");
};

const concatWithSeparator = (
  { value }: ITransformerParams,
  separator: string,
  ...itensToConcat: string[]
): string => {
  const arrayToConcat = [value, ...itensToConcat];
  return arrayToConcat.join(separator);
};

const transformers: ITransformer = {
  concat,
  concatWithSeparator,
};

export default transformers;
File name: index.ts
import { TemplateModule } from "@edirect/template";
import baseTransformers from "./baseTransformers";

const template = {
  status: "status",
  concatenated_result: {
    fields: ["lead_id"],
    transformer: "concat",
    transformerParams: [
      "-",
      "${person_number}",
      "/",
      "${person_number2}",
      "_",
      "${person_number3}",
    ],
  },
  concatenated_result2: {
    fields: ["lead_id"],
    transformer: "concatWithSeparator",
    transformerParams: [
      "-",
      "${person_number}",
      "${person_number2}",
      "${person_number3}",
    ],
  },
};

const dataSource = {
  status: true,
  lead_id: "FR-14af3f",
  person_number: 123,
  person_number2: 456,
  person_number3: 789,
};

const templateModule = new TemplateModule();

templateModule.setTemplate(template);
templateModule.setContext(dataSource);
templateModule.setTransformers(baseTransformers);

const result = templateModule.transformPayload(dataSource);
console.log(result);

// {
//   status: true,
//   concatenated_result: "FR-14af3f-123/456_789",
//   concatenated_result2: "FR-14af3f-123-456-789"
// }

Template example with transformer + transformerParams + complexParams

File name: baseTransformers.ts
import { ITransformer, ITransformerParams } from "@edirect/template";

const translator = ({ value }: ITransformerParams, translateDict: Record<string, string>): string => {
    const translated = translateDict.?[value];
    if (!translated) return null;
    return translated;
};

const transformers: ITransformer = {
    translator,
};

export default transformers;
File name: index.ts
import { TemplateModule } from "@edirect/template";
import baseTransformers from "./baseTransformers";

const template = {
  status: {
    fields: ["status"],
    transformer: "translator",
    transformerParams: [
      {
        ERROR: "ERROR",
        RECHAZADA: "REJECTED",
      },
    ],
  },
};

const dataSource = {
  status: "RECHAZADA",
};

const templateModule = new TemplateModule();

templateModule.setTemplate(template);
templateModule.setContext(dataSource);
templateModule.setTransformers(baseTransformers);

const result = templateModule.transformPayload(dataSource);
console.log(result);

// {
//   status: "REJECTED",
// }

Example inferring types to transformPayload

import { TemplateModule } from "@edirect/template";

interface DataSource {
  subscriber: {
    firstName: string;
    lastName: string;
  };
}

interface TransformedData {
  edirect_firstname: string;
  edirect_lastname: string;
}

function transformData(dataSource: DataSource): TransformedData {
  const template = {
    edirect_firstname: "subscriber.firstName",
    edirect_lastname: "subscriber.lastName",
  };

  const templateModule = new TemplateModule();
  templateModule.setTemplate(template);

  return templateModule.transformPayload<TransformedData>(dataSource);
}

const dataSource = {
  subscriber: {
    firstName: "template",
    lastName: "service",
  },
};

console.log(transformData(dataSource));

// {
//   edirect_firstname: "template",
//   edirect_lastname: "service",
// }

Example with Options

Options:

  • omitEmptyFields?: boolean;
import { TemplateModule } from "@edirect/template";

const template = {
  edirect_firstname: "subscriber.firstName",
  edirect_lastname: "subscriber.lastName",
  edirect_age: "subscriber.age",
};

const dataSource = {
  subscriber: {
    firstName: "template",
    lastName: "service",
    age: "",
  },
};

const options = { omitEmptyFields: true };

const templateModule = new TemplateModule();
templateModule.setTemplate(template);
templateModule.setOptions(options);

const result = templateModule.transformPayload(dataSource);

console.log(result);

// {
//   edirect_firstname: "template",
//   edirect_lastname: "service",
// }

Example using simple arrays

import { TemplateModule } from "@edirect/template";

const template = {
  emails: {
    arraySource: "subscriber.emails",
    simpleArray: true,
    arrayTemplate: {
      type: {
        defaultValue: "personal",
      },
      value: "value",
    },
  },
};

const dataSource = {
  subscriber: {
    emails: ["[email protected]", "[email protected]"],
  },
};

const templateModule = new TemplateModule();
templateModule.setTemplate(template);

const result = templateModule.transformPayload(dataSource);

console.log(result);

/*
  {
    "emails": [
      {
        "type": "personal",
        "value": "[email protected]"
      },
      {
        "type": "personal",
        "value": "[email protected]"
      }
    ]
  }
*/