Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

jet-schema

Package Overview
Dependencies
Maintainers
0
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jet-schema - npm Package Compare versions

Comparing version 1.0.3 to 1.0.4

2

package.json
{
"name": "jet-schema",
"version": "1.0.3",
"version": "1.0.4",
"description": "Simple, typescript-first schema validation tool",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -1,22 +0,32 @@

# Jet-Schema ✈️ 📝
# Jet-Schema ✈️
> Simple, zero-dependency, typescript-first schema validation tool, that lets you use your own validation functions (inferring types included!).
<br/>
## Introduction 🚀
Most schema validation libraries have fancy functions for validating object properties (i.e. `zod.string().email()`) but problem is I already had a lot of my own custom validation logic specific to my application (i.e. functions to check primitive-types, regexes for validating strings etc). The only thing that was making me use schema-validation libraries was trying to validate object properties. So I thought, why not figure out a way to integrate my all the functions I had already written with something that can validate them against object properties? Well **jet-schema** does just that :)
## Table of contents
- [Introduction](#introduction)
- [Quick Glance](#quick-glance)
- [Guide](#guide)
- [Getting Started](#getting-started)
- [Making schemas optional/nullable](#making-schemas-opt-null)
- [Transforming values with transform()](#transforming-values-with-transform)
- [Using Partial Schemas](#using-partial-schemas)
- [Bonus Features](#bonus-features)
## Introduction <a name="introduction"></a>
Most schema validation libraries have fancy functions for validating objects and their properties, but the problem is I usually already have a lot of my own custom validation logic specific for each of my applications (i.e. functions to check primitive-types, regexes for validating strings etc). The only thing that was making me use schema-validation libraries was trying to validate object properties. So I thought, why not figure out a way to integrate my all the functions I had already written with something that can validate them against object properties? Well **jet-schema** does just that :)
<br/>
If you want a library that includes all kinds of special functions for validating things other than objects **jet-schema** is probably not for you. However, the vast majority of projects I've worked on have involved implementing lots of type checking functions specific to the needs of that project. For example, maybe the email format that's built into the library is different that the one your application needs. Instead of of having to dig into the library's features to validate using your custom method, with **jet-schema** you can just pass your method.
If you want a library that includes all kinds of special functions for validating things other than objects, **jet-schema** is probably not for you. However, the vast majority of projects I've worked on have involved implementing lots of type-checking functions specific to the needs of that project. For example, maybe the email format that's built into the library is different than the one your application needs. Instead of of having to dig into the library's features to validate using your custom method, with **jet-schema** you can just pass your method.
<br/>
Reasons to use Jet-Schema
Reasons to use Jet-Schema 😎
- TypeScript first!
- Quick, terse, simple, easy-to-use (there are only 3 function exports and 2 type exports).
- Much smaller and less complex than most schema-validation libraries.
- Typesafety works both ways, you can either force a schema-type when the `schema` function is called OR you can infer a type from a schema.
- Set a default value for any validation-function you may wanna reuse.
- Typesafety works both ways, you can either force a schema structure using a pre-defined type OR you can infer a type from a schema.
- `new` and `test` functions provided automatically on every new schema.
- Provides a `transform` wrapper function to modify values after before validating them.
- `new` and `test` functions provided automatically on every new `schema`.
- Works client-side or server-side.
- Enums can be used for validation.
- Doesn't require a compilation step (so still works with `ts-node`, unlike `typia`).

@@ -26,5 +36,4 @@ <br/>

## Preview 👀
## Quick Glance <a name="quick-glance"></a>
```typescript
// An example using "zod", a popular schema validation library

@@ -35,3 +44,3 @@ const User: z.ZodType<IUser> = z.object({

email: z.string().email().or(z.literal('')).default('a@a.com'),
age: z.preprocess((arg => Number(arg)), z.number()),
age: z.preprocess(Number, z.number()),
created: z.preprocess((arg => arg === undefined ? new Date() : arg), z.coerce.date()),

@@ -45,4 +54,4 @@ address: z.object({

// Equivalent using "jet-schema" (other than "schema/transform",
// the other are application custom-functions)
// Equivalent using "jet-schema" (other than "schema/transform", the other functions
// are defined elsewhere in the application)
const User = schema<IUser>({

@@ -64,15 +73,20 @@ id: isRelKey,

## Guide 📜
## Guide <a name="guide"></a>
### Getting Started 🚦
First you need to initialize the `schema` function by importing the `jet-logger` function.
- `jetSchema` accepts two optional arguments:
- an array-map of which default-value should be used for which validator-function: you should use this option for frequently used validator-function/default-value combinations where you don't want to set a default value every time.
### Getting Started <a name="getting-started"></a>
> npm install -s jet-schema
After installation, you need to configure the `schema` function by importing and calling the `jetSchema()` function.
<br/>
`jetSchema()` accepts two optional arguments:
- An array-map of which default-value should be used for which validator-function: you should use this option for frequently used validator-function/default-value combinations where you don't want to set a default value every time.
- The second is a custom clone function if you don't want to use the built-in function which uses `structuredClone` (I like to use `lodash.cloneDeep`).
<br/>
When setting up **jet-schema** for the first time, usually what I do is create two files under my `util/` folder: `schema.ts` and `validators.ts`. In `schema.ts` I'll import and call the `jet-schema` function and apply any frequently used validator-function/default-value I have. If you don't want to go through this step you can import the `schema` function directly from `jet-schema`.
> When setting up **jet-schema** for the first time, usually what I do is create two files under my `util/` folder: `schema.ts` and `validators.ts`. In `schema.ts` I'll import and call the `jet-schema` function then apply any frequently used validator-function/default-value combinations I have and a clone-function. If you don't want to go through this step, you can import the `schema` function directly from `jet-schema`.
```typescript
// "util/type-checks.ts"
// IMPORTANT: you should use type-predicates when writing validator functions.
// "util/validators.ts"

@@ -90,8 +104,10 @@ export function isNum(param: unknown): param is number {

}
```
> ⚠️ **IMPORTANT:** &nbsp; You need to use type-predicates when writing validator functions. If a value can be null/undefined, your validator-function's type-predicate needs account for this (`i.e. (arg: unknown): arg is string | undefined => ... `).
```typescript
// "util/schema.ts"
import jetSchema from 'jet-schema';
import { isNum, isStr } from './type-checks';
// import { schema } from 'jet-schema'; // No options
import { isNum, isStr } from './validators';

@@ -101,7 +117,11 @@ export default jetSchema([

[isStr, ''],
], '...pass a custom clone function here if you want to...');
], '...pass a custom clone-function here if you want to...');
```
<br/>
Now that we have our schema function let's make a schema: there are two ways to go about this. I usually like to create an interface first cause I feel like they are great way to document your data types BUT some people would rather setup their schemas first and infer their types from that. I'll show you some examples doing both.
Now that we have our schema function setup, let's make a schema: there are two ways to go about this, enforcing a schema from a type or infering a type from a schema. I'll show you some examples doing it both ways.
<br/>
> Personally, I like to create an interface first cause I feel like they are great way to document your data-types, but I know some people prefer to setup their schemas first and infer their types from that.
```typescript

@@ -125,6 +145,4 @@ // "models/User.ts"

name: isStr,
// You can pass your defaults/validators in an array instead.
email: ['', ((arg: str) => EMAIL_RGX.test(arg))]
// NOTE: we don't have to pass this option since its optional
nickName: isOptionalStr,
email: ['', EMAIL_RGX.test] // You can pass your defaults/validators in an array instead.
nickName: isOptionalStr, // NOTE: we don't have to pass this option since its optional
})

@@ -136,2 +154,3 @@

name: isStr,
email: ['', EMAIL_RGX.test]
nickName: isOptionalStr,

@@ -141,32 +160,54 @@ })

```
<br/>
**IMPORTANT:** Upon initialization, the validator-functions will check their defaults. If a value is not optional and you do not supply default value, then an error will be thrown when `schema` is called.
> ⚠️ **IMPORTANT:** &nbsp; Upon initialization, the validator-functions will check their defaults. If a value is not optional and you do not supply default value, then an error will be thrown when `schema()` is called.
<br/>
Once you have you schema setup, you can call the `new`, `test`, and `pick` functions. Here is an overview of what each one does:
Once you have your schema setup, you can call the `new`, `test`, and `pick` functions. Here is an overview of what each one does:
- `new` Allows you to create new instances of your type using partials. If the value is absent, `new` will using the default supplied. If no default is supplied then the value will be skipped.
- `test` accepts any unknown value, returns a type-predicate and will test it against the `schema`.
- `pick` allows you to select property and returns an object with the `test` and `default` functions. If a value is nullable, then you need to use optional guard when calling it: `pick?.()`
- If an object property is a mapped-type then it must be initialized with the schema function. Just like with the parent schemas, you can also call `new`, `test`, `pick`, in addition to `default`. The value returned from `default` could be different from `new` if the schema is optional/nullable and the default
> If an object property is a mapped-type then it must be initialized with the schema function. Just like with the parent schemas, you can also call `new`, `test`, `pick`, in addition to `default`. The value returned from `default` could be different from `new` if the schema is optional/nullable and the default value is `null` or `undefined`.
### Make schemas optional/nullable ❔
In additiona to a schema-object the `schema()` function accepts 3 additional parameters `isOptional`, `isNullable`, and `default`. These are type-checked against the type supplied to schema `schema<...Your Type...>()`, so you must supply the correct parameters. So for example, if the schema-type is nullable or optional, then you must enter `true` for the second and third parameters.<br/>
The third option `default` defines the behavior for nested schemas when initialized from a parent. The value can be a `boolean` or `null`. If `false` or `undefined` the value will not be initialized with the parent, if `null` (schema must be nullable) value will be `null`, and if `true` then a full schema object will be created.
### Making schemas optional/nullable <a name="making-schemas-opt-null"></a>
In addition to a schema-object, the `schema()` function accepts 3 additional parameters `isOptional`, `isNullable`, and `default`. These are type-checked against the type supplied to schema `schema<...Your Type...>()`, so you must supply the correct parameters. So for example, if the schema-type is nullable and optional, then you must enter `true` for the second and third parameters.<br/>
The third option `default` defines the behavior for nested schemas when initialized from a parent. The value can be a `boolean` or `null`. If `false` the value will not be initialized with the parent, if `null` (the schema must be nullable to do this) value will be `null`, and if `true` or `undefined` then a full schema object will be created when a parent object is created.
### Transforming values with `transform()` 🤖
If you want to modify a value before it passes through a validator function, you can import the `transform` function and wrap your validator function with it. `transform` calls the validator function and fires a callback with the modified value if the callback was provided. When calling `new` or `test`, `transform` will modify the object being used as an argument in. I've found `transform` can be useful for other parts of my application where I need to modify a value before validating it and returning the transformed value. The function firing the callback still returns a type-predicate.
```typescript
interface IUser {
id: number;
name: string;
address?: { street: string, zip: number } | null;
}
const User = schema<IUser>({
id: isNumber,
name: isString,
address: schema({
street: isString,
zip: isNumber,
}, true /*(isOptional)*/, true /*(isNullable)*/, /*default*/) // You MUST pass true for "isOptional" and "isNullable" here.
})
```
### Transforming values with `transform()` <a name="transforming-values-with-transform"></a>
If you want to modify a value before it passes through a validator function, you can import the `transform` function and wrap your validator function with it. `transform` calls the validator function and fires a callback with the modified value if the callback was provided. When calling `new` or `test`, `transform` will modify the original object.
<br/>
I've found `transform` can be useful for other parts of my application where I need to modify a value before validating it and return the transformed value. The function firing the callback still returns the validator's type-predicate:
```typescript
import { transform } from 'jet-schema';
const customTest = transform(JSON.parse, isNumberArray);
console.log(customTest('[1,2,3,5]', transVal => console.log(transVal)));
let val = '[1,2,3,5]';
console.log(customTest(val, transVal => val = transVal)); // => true
console.log(val); // => [1,2,3,5] this is number array not a string
```
### Using Partial Schemas
For whatever reason, your schema may end up existing in multiple places. If you want to declare a partial schema, you can import the `TJetSchema` type and use it to setup a partial type, the merge that type with your full schema later.
### Using Partial Schemas <a name="using-partial-schemas"></a>
For whatever reason, your schema may end up existing in multiple places. If you want to declare a partial schema, you can import the `TJetSchema` type and use it to setup one, then merge it with your full schema later.

@@ -190,4 +231,4 @@ ```typescript

### Misc
- When passing the `Date` constructor, automatically converts all valid date values to a `Date` object.
- You can also use an enum as a validator. The default value will be the first value in the enum object.
### Bonus Features <a name="bonus-features"></a>
- When passing the `Date` constructor, `jet-schema` automatically converts all valid date values (i.e. string/number ) to a `Date` object. The default value will be a current datetime `Date` object.
- You can also use an enum as a validator. The default value will be the first value in the enum object and the validation will make sure the value is a value in the enum.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc