0.0.3 • Published 11 months ago

twilio-zod v0.0.3

Weekly downloads
-
License
MIT
Repository
github
Last release
11 months ago

Twilio Zod

Table of contents

Introduction

Twilio Zod is a collection of Zod helpers designed for making Twilio application development easier.

Twilio Zod aims to remove the guesswork of Twilio objects, increase predictability, extend type safety during development and offer helper utilities around common actions.

Installation

  • Typescript 4.5+
  • Enable strict mode in the tsconfig.json (Why wouldn't you?)

Popular package managers

npm install twilio-zod
yarn add twilio-zod
bun add twilio-zod
pnpm add zod

Deno

Not yet supported

Usage

If are not already familiar with Zod, please start here.

SIDS

The most common usage is validating various SIDs from Twilio.

import { schemas } from "twilio-zod";

schemas.sids.conversation.parse("CH5654396784325467987654345679543"); // => "CH5654396784325467987654345679543"

schemas.sids.conversation.parse("CH33246"); // => throws a ZodError

Extending

In some cases, the provided schemas do not sufficiently describe the data you are parsing. Where possible, all parsed objects utilise Zods .passthrough() utility to avoid stripping other unrecognised keys. This means you can still access properties however at your own risk since these have not been parsed.

As an alternative, you will likely want to extend the provided schema to add your own properties:

without extending

import { schemas } from "twilio-zod"

const taskAttributes = {
  roles: ["admin"],
  full_name: "John Doe",
  language: "en-GB" // This property is not described
}

let parsedTaskAttributes = schemas.taskRouter.taskAttributes.parse(taskAttributes) // { roles: ["admin"], ... }

parsedTaskAttributes.roles // => string[]
parsedTaskAttributes.language // => unknown ❌

extending

import { schemas } from "twilio-zod"

const taskAttributes = {
  roles: ["admin"],
  full_name: "John Doe",
  language: "en-GB" // This property is not described
}

let extendedSchema = schemas.taskRouter.taskAttributes.extend({ language: z.string() })

let parsedTaskAttributes = extendedSchema.parse(taskAttributes) // { roles: ["admin"], ... }

parsedTaskAttributes.roles // => string[]
parsedTaskAttributes.language // => string ✔

Utilities

String to JSON

In some events, Twilio will return a JSON as a string object. To predictably parse within a Zod schema a stringToJson() utility is exposed. This can be used to implicity parse as JSON string and validate it against an schema:

import { schemas, stringToJson } from "twilio-zod"

const attributesSchema = z.object({
  conversationSid: schemas.sids.conversation
});

/*
{
  name: "John Doe",
  attributes: "{\"avatarUrl\": \"http://....\", \"conversationSid\": \"CH....\"}"
}
*/
const eventSchema = z.object({
  name: z.string(),
  attributes: stringToJson.pipe(attributesSchema) // This will parse a JSON string then validate it against the attributes schema
})

Error handling

Parsing

All schemas will throw (or return if safe parsing) an instance of ZodError. See the Zod documentation for further detail.

ZodError is brilliant for debugging but is not very user-friendly. A generateErrorMessage() function is included which converts an instance of ZodError to a human-friendly, readable string. This takes the top-most error, ignoring the rest.

import { schemas, generateErrorMessage } from "twilio-zod"

let result = schemas.sids.conversation.safeParse("CH234");
if (!result.success) {
  console.error(error.generateErrorMessage(result.error)); // => "too_small: SID must be 34 characters in length"
} else {
  console.log("Good!");
}

NodeJS library

The Twilio NodeJS will throw on operations when an error is met. Generally, Twilio with throw a standard format similiar to:

{
  "message": "A description of the error",
  "status": "The HTTP status code matching the error",
  "code": "The Twilio specific error code from their dictionary",
  "details": "Additional information on the error",
  "moreInfo": "Further information - typically a link to the definition on the dictionary"
}

Naturally with TypeScript, an error caught in a catch block will be of a type any or unknown. There is two methods of dealing with this:

Zod Schema (preferred)

A schema is exposed that can parse the error returned much like you would parse any other object:

import { schemas } from "twilio-zod/error"

try {
  twilio.conversations.v1.conversations("CH1234").fetch() // 404 error thrown
} catch (err /* unknown */) {
  let parsedError = schemas.error.twilioError.parse(err)
  parsedError.data // TwilioError
}

Type guard

You can use the exposed isTwilioError() type guard function:

import { isTwilioError } from "twilio-zod"

try {
  twilio.conversations.v1.conversations("CH1234").fetch() // 404 error thrown
} catch (err /* unknown */) {
  if (isTwilioError(err)) {
    err // TwilioError
  }
}
0.0.3

11 months ago

0.0.2

1 year ago

0.0.1

1 year ago