0.10.1 • Published 3 years ago

@japan-d2/schema v0.10.1

Weekly downloads
31
License
MIT
Repository
github
Last release
3 years ago

schema

A library designed to implement both TypeScript Interface and json-schema.

install

npm install @japan-d2/schema

or

yarn add @japan-d2/schema

Usage

Schema definition

Construct JSON Schema and TypeScript types simultaneously in the method chain for defineSchema(). The following methods are provided for schema definition:

  • string (name, options?)
  • number (name, options?)
  • integer (name, options?)
  • boolean (name, options?)
  • null (name, options?):
  • const (name, value, options?)
  • enum (name, type, values, options?)
  • array (name, type, itemOptions?, arrayOptions?)
  • object (name, options, objectOptions?)

For example:

import { defineSchema } from '@japan-d2/schema'

const exampleUserSchema = defineSchema()
  .string('name', {
    maxLength: 32,
    minLength: 1
  })
  .integer('age', {
    minimum: 0
  })

Extend other schema

schema.extend (otherSchema) -> schema

import { defineSchema } from '@japan-d2/schema'

const withAdmin = defineSchema()
  .const('admin', true)

const exampleUserSchemaWithAdmin = exampleUserSchema
  .extend(withAdmin)

Direct object definition

defineObjectSchema() -> schema

import { defineObjectSchema, field } from '@japan-d2/schema'

const user = defineObjectSchema({
  // required fields
  name: field.string(),
  type: field.enum('string', ['creator', 'observer']),
}, {
  // optional fields
  channels: field.array('object', {
    name: field.string(),
    category: field.enum('string', ['music', 'nature', 'game'])
  })
})

Omit specific key

schema.omit (...keys) -> schema

import { defineSchema } from '@japan-d2/schema'

const exampleUserSchemaWithoutPrivateInfo = exampleUserSchema
  .omit(
    'age',
    'name',
    'phoneNumber'
  )

Pick specific key

schema.pick (...keys) -> schema

import { defineSchema } from '@japan-d2/schema'

const exampleUserSchemaOnlyPublicInfo = exampleUserSchema
  .pick(
    'id',
    'email',
    'nickName'
  )

Combine

combineSchema.oneOf ([schema1, schema2, ...]) -> schema

import { defineSchema, combineSchema } from '@japan-d2/schema'

const contactSchema = combineschema.oneOf([
  phoneNumberContactSchema,
  emailContactSchema,
])

Runtime conversion to JSON Schema

call instance method toJSONSchema() of schema.

const jsonSchema = exampleUserSchema.toJSONSchema()
console.log(jsonSchema)

The return value is a standard JSON Schema object (supports Draft 7).

{
  type: 'object',
  properties: {
    name: { type: 'string', maxLength: 32, minLength: 1 },
    age: { type: 'integer', minimum: 0 }
  },
  required: [ 'name', 'age' ]
}

Validation

Assume the following "dirty" data for validation.

const dirtyUser = {
  name: 'roa',
  age: Math.random() < 0.5 ? 13 : '13'
}

dirtyUser.age // number | string

Validation with User-Defined Type Guard

validate (instance, schema) -> boolean

Returns true or false using validate function in jsonschema package with options { throwError: false }. When used inside an if conditional expression, type guard is enabled.

import { validate } from '@japan-d2/schema'

if (validate(dirtyUser, exampleUserSchema)) {
  dirtyUser.age // number
}
dirtyUser.age // number | string

Validation with Assertion Function

assertValid (instance, schema) -> void

Throws ValidationError if instance are invalid, and does nothing if valid. Internally it uses validate function in jsonschema package with options { throwError: true }. This function is an Assertion Function that uses the new features of TS3.7 and this fixes the type in a scope where no error occurred.

import { validate } from '@japan-d2/schema'

// throw validation error if age is not a number
assertValid(dirtyUser, exampleUserSchema)

dirtyUser.age // number

Type utilities

Pure

Provides a purified schema type. Same as guarded by validate orassertValid.

import { Pure } from '@japan-d2/schema'
type UserType = Pure<typeof exampleUserSchema>

const user: UserType = {
  name: 'roa',
  age: 13,
}

Dirty

Provides an explicitly tainted schema type. It can be used to indicate an external value as input value for validate orassertValid.

import { Dirty, assertValid } from '@japan-d2/schema'
type DirtyUserType = Dirty<typeof exampleUserSchema>

app.post('/users', (req) => {
  const user: DirtyUserType = req.body

  user.name // unknown
  user.age // unknown

  assertValid(user)

  user.name // string
  user.age // number
})

License

MIT

0.10.1

3 years ago

0.10.0

3 years ago

0.8.5

3 years ago

0.8.6

3 years ago

0.9.1

3 years ago

0.8.4

3 years ago

0.8.3

3 years ago

0.8.2

3 years ago

0.8.1

3 years ago

0.8.0

3 years ago

0.7.0

4 years ago

0.6.0

4 years ago

0.5.0

4 years ago

0.5.1

4 years ago

0.4.1

4 years ago

0.3.0

4 years ago

0.2.0

4 years ago

0.3.1

4 years ago

0.0.19

4 years ago

0.0.18

4 years ago

0.0.17

4 years ago

0.0.15

4 years ago

0.0.16

4 years ago

0.0.14

4 years ago

0.0.13

4 years ago

0.0.12

4 years ago

0.0.11

4 years ago

0.0.5

4 years ago

0.0.6

4 years ago

0.0.4

4 years ago

0.0.3

4 years ago

0.0.2

4 years ago

0.0.1

4 years ago