0.0.1 • Published 2 years ago

@beppobert/ts-template v0.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

template-ts

This is a small customizable typesafe template engine written in Typescript.

Setup

Quickstart

npm i @beppobert/ts-template
import {
  TypeDefinition,
  ArgDefinition,
  OperationDefinition,
  Pattern,
  createSchema,
  template,
} from "@beppobert/ts-template";

// create your custom types

const stringType = new TypeDefinition("string", {
  validator: (input: string) => typeof input === "string",
  parseValue: (value): string => value,
  pattern: new Pattern<`"${string}"`, '""'>(/^\"(.*)\"$/),
});
const numberType = new TypeDefinition("number", {
  validator: (input: number) => typeof input === "number",
  parseValue: (value): number => Number(value),
  pattern: new Pattern<`${number}`, "0">(new RegExp(`^${Number}$`)),
});

// create your custom operations

const uppercaseOperation = new OperationDefinition("upper", {
  args: [],
  input: stringType,
  return: stringType,
  operation: (input) => input.toUpperCase(),
});

const replaceOperation = new OperationDefinition("replace", {
  args: [
    new ArgDefinition("searchValue", stringType),
    new ArgDefinition("replaceValue", stringType),
  ],
  input: stringType,
  return: stringType,
  operation: (input, { searchValue, replaceValue }) =>
    input.replace(searchValue, replaceValue),
});

const toString = new OperationDefinition("toString", {
  args: [],
  input: numberType,
  return: stringType,
  operation: (input) => input.toString(),
});

// create your  schema

const schema = createSchema(
  {
    types: [stringType, numberType],
    defaultType: "string",
  },
  {
    // group the operation based on their input type into an object
    string: [uppercaseOperation, replaceOperation],
    number: [toString],
  }
);

// create your template function

const templateFn = template(schema);

const templateString = templateFn("Hello {{name|upper}}"); // enjoy auto completion

Create a custom type

import { TypeDefinition, Pattern } from "@beppobert/ts-template";
/***
 * The Pattern class defines a pattern that your string in your arguments has to match
 * The first generic will define the typescript side of your pattern.
 * Any arg of type string will be checked against this type.
 * e.g. {{...|...|replace("a","b")}} <- "a" and "b" have to match the pattern
 *
 * The second generic will define a default value if the pattern doesn't match.
 *
 * The pattern regex will be used to validate your arg string.
 * It's last match should also return the value you want to parse.
 *
 * /
const strPattern = new Pattern<`"${string}"`, '""'>(/^\"(.*)\"$/);

const stringType = new TypeDefinition("string", {
  pattern: strPattern,
  // is called after the parsing step
  validator: (input: string) => typeof input === "string",

  // receives the last match of the pattern regex and must return a value of the desired type
  parseValue: (value): string => value,
});

Create a custom operation

import { OperationDefinition, ArgDefinition } from "@beppobert/ts-template";
/**
 * The first argument is the key of your operation.
 * It will be used in your template string to call your operation.
 */
const replace = new OperationDefinition("replace", {
  // define the arguments of your operation
  args: [
    new ArgDefinition("searchValue", stringType),
    new ArgDefinition("replaceValue", stringType),
  ],
  // define the input type of your operation
  input: stringType,
  // define the return type of your operation
  return: stringType,
  // define the operation
  operation: (input, { searchValue, replaceValue }) =>
    input.replace(searchValue, replaceValue),
});

Create a custom schema

The schema runs multiple runtime checks to ensure that your schema is valid.

import { createSchema } from "@beppobert/ts-template";

const schema = createSchema(
  {
    // define your types
    types: [stringType, numberType],
    // define your default type
    defaultType: "string",
  },
  {
    // group the operation based on their input type into an object
    string: [uppercaseOperation, replaceOperation],
    number: [toString],
  }
);

Create a custom template function

import { template } from "@beppobert/ts-template";

const templateFn = template(schema);
/**
 * A value you want to get replaced needs to be wrapped in {{...}}
 *
 * The first part of the string is the name of the value you want to replace.
 * If the value is optional you can add a ? before the name.
 * e.g. {{?name}} will be replaced with the value of name if it exists
 *
 * The second part of the string is the type of the value.
 * The type is prefixed with #. If it's not prefixed the default type will be used.
 * e.g. {{name#string}} is the same as {{name}} if string is the default type
 *
 * the third part of the string is the operations you want to call on the value.
 * e.g. {{name#string|upper|replace("a","b")}}. The typesytem ensures that after each operation you can only * call operations that are defined for the return type of the previous operation.
 * e.g.{{name#string|upper|toString}} will result in an error
 */
const templateString = templateFn(
  'Hello {{name#string|upper|replace("O","i")}}'
); // enjoy auto completion
templateString({ name: "Bob" }); // Hello BiB

const templateString2 = templateFn("Hello {{name|upper}}");
0.0.1

2 years ago