• Stars
    star
    496
  • Rank 88,807 (Top 2 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created about 6 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A fluent API to generate JSON schemas

fluent-json-schema

A fluent API to generate JSON schemas (draft-07) for Node.js and browser. Framework agnostic.

view on npm Coverage Status JavaScript Style Guide

Features

  • Fluent schema implements JSON Schema draft-07 standards
  • Faster and shorter way to write a JSON Schema via a fluent API
  • Runtime errors for invalid options or keywords misuse
  • JavaScript constants can be used in the JSON schema (e.g. enum, const, default ) avoiding discrepancies between model and schema
  • TypeScript definitions
  • Coverage 99%

Install

npm i fluent-json-schema

or

yarn add fluent-json-schema

Usage

const S = require('fluent-json-schema')

const ROLES = {
  ADMIN: 'ADMIN',
  USER: 'USER',
}

const schema = S.object()
  .id('http://foo/user')
  .title('My First Fluent JSON Schema')
  .description('A simple user')
  .prop('email', S.string().format(S.FORMATS.EMAIL).required())
  .prop('password', S.string().minLength(8).required())
  .prop('role', S.string().enum(Object.values(ROLES)).default(ROLES.USER))
  .prop(
    'birthday',
    S.raw({ type: 'string', format: 'date', formatMaximum: '2020-01-01' }) // formatMaximum is an AJV custom keywords
  )
  .definition(
    'address',
    S.object()
      .id('#address')
      .prop('line1', S.anyOf([S.string(), S.null()])) // JSON Schema nullable
      .prop('line2', S.string().raw({ nullable: true })) // Open API / Swagger  nullable
      .prop('country', S.string())
      .prop('city', S.string())
      .prop('zipcode', S.string())
      .required(['line1', 'country', 'city', 'zipcode'])
  )
  .prop('address', S.ref('#address'))

console.log(JSON.stringify(schema.valueOf(), undefined, 2))

Schema generated:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "address": {
      "type": "object",
      "$id": "#address",
      "properties": {
        "line1": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ]
        },
        "line2": {
          "type": "string",
          "nullable": true
        },
        "country": {
          "type": "string"
        },
        "city": {
          "type": "string"
        },
        "zipcode": {
          "type": "string"
        }
      },
      "required": ["line1", "country", "city", "zipcode"]
    }
  },
  "type": "object",
  "$id": "http://foo/user",
  "title": "My First Fluent JSON Schema",
  "description": "A simple user",
  "properties": {
    "email": {
      "type": "string",
      "format": "email"
    },
    "password": {
      "type": "string",
      "minLength": 8
    },
    "birthday": {
      "type": "string",
      "format": "date",
      "formatMaximum": "2020-01-01"
    },
    "role": {
      "type": "string",
      "enum": ["ADMIN", "USER"],
      "default": "USER"
    },
    "address": {
      "$ref": "#address"
    }
  },
  "required": ["email", "password"]
}

TypeScript

CommonJS

With "esModuleInterop": true activated in the tsconfig.json:

import S from 'fluent-json-schema'

const schema = S.object()
  .prop('foo', S.string())
  .prop('bar', S.number())
  .valueOf()

With "esModuleInterop": false in the tsconfig.json:

import * as S from 'fluent-json-schema'

const schema = S.object()
  .prop('foo', S.string())
  .prop('bar', S.number())
  .valueOf()

ESM

A named export is also available to work with native ESM modules:

import { S } from 'fluent-json-schema'

const schema = S.object()
  .prop('foo', S.string())
  .prop('bar', S.number())
  .valueOf()

Validation

Fluent schema does not validate a JSON schema. However, many libraries can do that for you. Below a few examples using AJV:

npm i ajv

or

yarn add ajv

Validate an empty model

Snippet:

const ajv = new Ajv({ allErrors: true })
const validate = ajv.compile(schema.valueOf())
let user = {}
let valid = validate(user)
console.log({ valid }) //=> {valid: false}
console.log(validate.errors) //=> {valid: false}

Output:

{valid: false}
errors: [
  {
    keyword: 'required',
    dataPath: '',
    schemaPath: '#/required',
    params: { missingProperty: 'email' },
    message: "should have required property 'email'",
  },
  {
    keyword: 'required',
    dataPath: '',
    schemaPath: '#/required',
    params: { missingProperty: 'password' },
    message: "should have required property 'password'",
  },
]

Validate a partially filled model

Snippet:

user = { email: 'test', password: 'password' }
valid = validate(user)
console.log({ valid })
console.log(validate.errors)

Output:

{valid: false}
errors:
[ { keyword: 'format',
    dataPath: '.email',
    schemaPath: '#/properties/email/format',
    params: { format: 'email' },
    message: 'should match format "email"' } ]

Validate a model with a wrong format attribute

Snippet:

user = { email: '[email protected]', password: 'password' }
valid = validate(user)
console.log({ valid })
console.log('errors:', validate.errors)

Output:

{valid: false}
errors: [ { keyword: 'required',
    dataPath: '.address',
    schemaPath: '#definitions/address/required',
    params: { missingProperty: 'country' },
    message: 'should have required property \'country\'' },
  { keyword: 'required',
    dataPath: '.address',
    schemaPath: '#definitions/address/required',
    params: { missingProperty: 'city' },
    message: 'should have required property \'city\'' },
  { keyword: 'required',
    dataPath: '.address',
    schemaPath: '#definitions/address/required',
    params: { missingProperty: 'zipcoce' },
    message: 'should have required property \'zipcode\'' } ]

Valid model

Snippet:

user = { email: '[email protected]', password: 'password' }
valid = validate(user)
console.log({ valid })

Output:

{valid: true}

Extend schema

Normally inheritance with JSON Schema is achieved with allOf. However when .additionalProperties(false) is used the validator won't understand which properties come from the base schema. S.extend creates a schema merging the base into the new one so that the validator knows all the properties because it is evaluating only a single schema. For example, in a CRUD API POST /users could use the userBaseSchema rather than GET /users or PATCH /users use the userSchema which contains the id, createdAt and updatedAt generated server side.

const S = require('fluent-json-schema')
const userBaseSchema = S.object()
  .additionalProperties(false)
  .prop('username', S.string())
  .prop('password', S.string())

const userSchema = S.object()
  .prop('id', S.string().format('uuid'))
  .prop('createdAt', S.string().format('time'))
  .prop('updatedAt', S.string().format('time'))
  .extend(userBaseSchema)

console.log(userSchema)

Selecting certain properties of your schema

In addition to extending schemas, it is also possible to reduce them into smaller schemas. This comes in handy when you have a large Fluent Schema, and would like to re-use some of its properties.

Select only properties you want to keep.

const S = require('fluent-json-schema')
const userSchema = S.object()
  .prop('username', S.string())
  .prop('password', S.string())
  .prop('id', S.string().format('uuid'))
  .prop('createdAt', S.string().format('time'))
  .prop('updatedAt', S.string().format('time'))

const loginSchema = userSchema.only(['username', 'password'])

Or remove properties you dont want to keep.

const S = require('fluent-json-schema')
const personSchema = S.object()
  .prop('name', S.string())
  .prop('age', S.number())
  .prop('id', S.string().format('uuid'))
  .prop('createdAt', S.string().format('time'))
  .prop('updatedAt', S.string().format('time'))

const bodySchema = personSchema.without(['createdAt', 'updatedAt'])

Detect Fluent Schema objects

Every Fluent Schema object contains a boolean isFluentSchema. In this way, you can write your own utilities that understands the Fluent Schema API and improve the user experience of your tool.

const S = require('fluent-json-schema')
const schema = S.object().prop('foo', S.string()).prop('bar', S.number())
console.log(schema.isFluentSchema) // true

Documentation

Acknowledgments

Thanks to Matteo Collina for pushing me to implement this utility! 🙏

Related projects

Licence

Licensed under MIT.

More Repositories

1

fastify

Fast and low overhead web framework, for Node.js
JavaScript
31,474
star
2

fast-json-stringify

2x faster than JSON.stringify()
JavaScript
3,463
star
3

fastify-dx

Archived
JavaScript
901
star
4

fastify-vite

Fastify plugin for Vite integration
JavaScript
882
star
5

fastify-cli

Run a Fastify application with one command!
JavaScript
644
star
6

fastify-swagger

Swagger documentation generator for Fastify
JavaScript
643
star
7

benchmarks

Fast and low overhead web framework fastify benchmarks.
JavaScript
502
star
8

aws-lambda-fastify

Insipired by aws-serverless-express to work with Fastify with inject functionality.
JavaScript
497
star
9

fastify-nextjs

React server side rendering support for Fastify with Next
JavaScript
450
star
10

fastify-sensible

Defaults for Fastify that everyone can agree on
JavaScript
448
star
11

fastify-static

Plugin for serving static files as fast as possible
JavaScript
420
star
12

avvio

Asynchronous bootstrapping of Node applications
JavaScript
407
star
13

fastify-multipart

Multipart support for Fastify
JavaScript
343
star
14

fastify-jwt

JWT utils for Fastify
JavaScript
340
star
15

fastify-rate-limit

A low overhead rate limiter for your routes
JavaScript
335
star
16

fastify-http-proxy

Proxy your http requests to another server, with hooks.
JavaScript
332
star
17

fastify-helmet

Important security headers for Fastify
JavaScript
305
star
18

fastify-websocket

basic websocket support for fastify
JavaScript
290
star
19

fastify-cors

Fastify CORS
JavaScript
276
star
20

point-of-view

Template rendering plugin for Fastify
JavaScript
272
star
21

fastify-example-twitter

Fastify example - clone twitter
JavaScript
270
star
22

fastify-auth

Run multiple auth functions in Fastify
JavaScript
268
star
23

docs-chinese

Fastify 中文文档
259
star
24

fastify-passport

Use passport strategies for authentication within a fastify application
TypeScript
248
star
25

fastify-cookie

A Fastify plugin to add cookies support
JavaScript
243
star
26

light-my-request

Fake HTTP injection library
JavaScript
243
star
27

fastify-oauth2

Enable to perform login using oauth2 protocol
JavaScript
243
star
28

fastify-autoload

Require all plugins in a directory
JavaScript
242
star
29

under-pressure

Measure process load with automatic handling of "Service Unavailable" plugin for Fastify.
JavaScript
234
star
30

middie

Middleware engine for Fastify.
JavaScript
206
star
31

fastify-mongodb

Fastify MongoDB connection plugin
JavaScript
200
star
32

fastify-env

Fastify plugin to check environment variables
JavaScript
194
star
33

fastify-express

Express compatibility layer for Fastify
JavaScript
190
star
34

fastify-caching

A Fastify plugin to facilitate working with cache headers
JavaScript
181
star
35

secure-json-parse

JSON.parse() drop-in replacement with prototype poisoning protection
JavaScript
176
star
36

fast-proxy

Node.js framework agnostic library that enables you to forward an http request to another HTTP server. Supported protocols: HTTP, HTTPS, HTTP2
JavaScript
162
star
37

fastify-plugin

Plugin helper for Fastify
JavaScript
159
star
38

fastify-compress

Fastify compression utils
JavaScript
157
star
39

env-schema

Validate your env variable using Ajv and dotenv
JavaScript
154
star
40

github-action-merge-dependabot

This action automatically approves and merges dependabot PRs.
JavaScript
152
star
41

fastify-type-provider-typebox

A Type Provider for Typebox
TypeScript
151
star
42

fastify-redis

Plugin to share a common Redis connection across Fastify.
JavaScript
151
star
43

fastify-reply-from

fastify plugin to forward the current http request to another server
JavaScript
149
star
44

fastify-bearer-auth

A Fastify plugin to require bearer Authorization headers
JavaScript
148
star
45

fastify-request-context

Request-scoped storage support, based on Asynchronous Local Storage (with fallback to cls-hooked)
JavaScript
146
star
46

fastify-secure-session

Create a secure stateless cookie session for Fastify
JavaScript
145
star
47

fastify-postgres

Fastify PostgreSQL connection plugin
JavaScript
145
star
48

csrf-protection

A fastify csrf plugin.
JavaScript
144
star
49

fastify-swagger-ui

Serve Swagger-UI for Fastify
JavaScript
129
star
50

fastify-formbody

A Fastify plugin to parse x-www-form-urlencoded bodies
JavaScript
127
star
51

fastify-circuit-breaker

A low overhead circuit breaker for your routes
JavaScript
113
star
52

session

Session plugin for fastify
JavaScript
104
star
53

create-fastify

Rapidly generate a Fastify project
JavaScript
98
star
54

example

Runnable examples of Fastify
JavaScript
96
star
55

fastify-routes

Decorates fastify instance with a map of routes
JavaScript
91
star
56

fastify-awilix

Dependency injection support for fastify
JavaScript
90
star
57

fastify-schedule

Fastify plugin for scheduling periodic jobs.
JavaScript
88
star
58

restartable

Restart Fastify without losing a request
JavaScript
86
star
59

busboy

A streaming parser for HTML form data for node.js
JavaScript
76
star
60

fastify-error

JavaScript
74
star
61

fastify-funky

Make fastify functional! Plugin, adding support for fastify routes returning functional structures, such as Either, Task or plain parameterless function.
JavaScript
74
star
62

fast-uri

Dependency free RFC 3986 URI toolbox
JavaScript
74
star
63

fastify-hotwire

Use the Hotwire pattern with Fastify
JavaScript
74
star
64

website-metalsmith

This project is used to build the website for fastify web framework and publish it online.
HTML
73
star
65

fastify-etag

Automatically generate etags for HTTP responses, for Fastify
JavaScript
69
star
66

fastify-accepts

Add accepts parser to fastify
JavaScript
67
star
67

fastify-mysql

JavaScript
66
star
68

fastify-example-todo

A Simple Fastify REST API Example
JavaScript
64
star
69

help

Need help with Fastify? File an Issue here.
61
star
70

fastify-basic-auth

Fastify basic auth plugin
JavaScript
59
star
71

fastify-url-data

A plugin to provide access to the raw URL components
JavaScript
57
star
72

releasify

A tool to release in a simpler way your module
JavaScript
55
star
73

fastify-kafka

Fastify plugin to interact with Apache Kafka.
JavaScript
52
star
74

fastify-routes-stats

provide stats for routes using perf_hooks, for fastify
JavaScript
45
star
75

fastify-elasticsearch

Fastify plugin for Elasticsearch
JavaScript
41
star
76

deepmerge

Merges the enumerable properties of two or more objects deeply. Fastest implementation of deepmerge
JavaScript
39
star
77

fastify-response-validation

A simple plugin that enables response validation for Fastify.
JavaScript
36
star
78

fastify-type-provider-json-schema-to-ts

A Type Provider for json-schema-to-ts
TypeScript
36
star
79

skeleton

Template repository to create standardized Fastify plugins.
35
star
80

fastify-accepts-serializer

Serializer according to the accept header
JavaScript
25
star
81

website

JavaScript
24
star
82

fastify-flash

Flash message plugin for Fastify
TypeScript
24
star
83

tsconfig

Shared TypeScript configuration for fastify projects
22
star
84

fastify-leveldb

Plugin to share a common LevelDB connection across Fastify.
JavaScript
21
star
85

docs-korean

19
star
86

process-warning

A small utility for creating warnings and emitting them.
JavaScript
19
star
87

fastify-diagnostics-channel

Plugin to deal with diagnostics_channel on Fastify
JavaScript
19
star
88

one-line-logger

JavaScript
18
star
89

ajv-compiler

Build and manage the AJV instances for the fastify framework
JavaScript
17
star
90

fastify-early-hints

Draft plugin of the HTTP 103 implementation
JavaScript
17
star
91

vite-plugin-blueprint

Vite plugin for shadowing files from a blueprint folder.
JavaScript
17
star
92

fastify-throttle

Throttle the download speed of a request
JavaScript
15
star
93

fastify-bankai

Bankai assets compiler for Fastify
JavaScript
15
star
94

csrf

CSRF utilities for fastify
JavaScript
13
star
95

.github

Default community health files
13
star
96

any-schema-you-like

Save multiple schemas and decide which one to use to serialize the payload
JavaScript
13
star
97

docs-portuguese

Portuguese docs for Fastify
11
star
98

fastify-typescript-extended-sample

This project is supposed to be a large, fake Fastify & TypeScript app. It is meant to be a reference as well as a pseudo-sandbox for Fastify TypeScript changes.
TypeScript
11
star
99

fastify-soap-client

Fastify plugin for a SOAP client
JavaScript
10
star
100

workflows

Reusable workflows for use in the Fastify organization
9
star