Scrubbr
Serialize and sanitize JSON API data using your TypeScript as the schema.
Serializing and sanitizing data sent from the webserver to the client shouldn't be hard. If you're already using TypeScript, you have everything you need. Scrubbr will use your TypeScript types to deeply transform and sanitize your data.
Install
npm i -S scrubbr
Quickstart
- Define a TypeScript file as your master schema:
type UserList = {
users: User[];
};
type User = {
name: string;
image: string;
};
- Load it into Scrubbr and serialize your data:
import Scrubbr from 'scrubbr';
const scrubbr = new Scrubbr('./schema.ts');
async function api() {
const data = getUsers();
return await scrubbr.serialize(data, 'UserList');
}
function getUsers() {
return {
users: [
{
name: 'John Doe',
image: 'http://i.pravatar.cc/300',
email: 'donotspam@me.com',
password: 'xxxsecretxxx',
},
],
};
}
- Output
{
"users": [
{
"name": "John Doe",
"image": "http://i.pravatar.cc/300"
}
]
}
Custom Serializers
You can define custom functions to change how the data is serialized.
Type Serializer
This function is called every time a matching TypeScript type is encountered.
For example, if you want to use another type to serialize a user who is logged in:
import Scrubbr, { useType } from 'scrubbr';
scrubbr.addTypeSerializer('User', (data, state) => {
if (data.id === state.context.loggedInUserId) {
return useType('UserPrivileged');
}
return data;
});
const context = {
loggedInUserId: 10,
};
const serialized = await scrubbr.serialize(data, 'PostList', context);
Path serializer
This serializer is called at each node of the data object regardless of type. It's called a path serializer because you'll use the state.path
value to determine which node you're serializing.
In this example we want to convert every createdAt
date value to the local timezone.
import moment from 'moment-timezone';
import Scrubbr, { useType } from 'scrubbr';
scrubbr.addPathSerializer('User', (data, state) => {
const path = state.path;
if (path.match(/\.createdAt$/)) {
return moment(data).tz(state.context.timezone).format();
}
return data;
});
const context = {
timezone: 'America/Los_Angeles',
};
const serialized = await scrubbr.serialize(data, 'PostList', context);
Try the example yourself
It's easy to try it yourself with the included example in example/index.ts
. Just clone this repo, install the dependencies (npm install
) and then run the example app with:
npm run example
Advanced Topics
Validation
For the sake of performance and simplicity, scrubber does not perform a schema validation step (it outputs data, not validates). However, under the hood scrubbr converts TypeScript to JSONSchema (via the great ts-json-schema-generator package). So you can easily use ajv to validate the serialized object.
import Ajv from 'ajv';
import Scrubbr from 'scrubbr';
const scrubbr = new Scrubbr('./schema.ts');
async function main() {
const output = await scrubbr.serialize(data, 'UserList');
const jsonSchema = scrubbr.getSchema();
const ajv = new Ajv();
const schemaValidator = ajv.compile(jsonSchema);
const isValid = schemaValidator(output);
if (!isValid) {
console.error(schemaValidator.errors);
}
}
License
MIT