Schema Overview
@feathersjs/schema
provides a way to define data models and to dynamically resolve them. It comes in two main parts:
- Schema - Uses JSON schema to define a data model with TypeScript types and basic validations. This allows us to:
- Ensure data is valid and always in the right format
- Automatically get TypeScript types from schema definitions
- Automatically generate API documentation
- Create database adapter models without duplicating the data format
- Validate query string queries and convert them to the right type
- Resolvers - Resolve schema properties based on a context (usually the hook context). This can be used for many different things like:
- Populating associations
- Securing queries and e.g. limiting requests to a user
- Removing protected properties for external requests
- Ability to add read- and write permissions on the property level
- Hashing passwords and validating dynamic password policies
Here is an example of a user schema definition and resolver:
import { HookContext } from './definitions'
import { schema, resolve, Infer } from '@feathersjs/schema'
export const userSchema = schema({
$id: 'User',
type: 'object',
additionalProperties: false,
required: ['email', 'password'],
properties: {
id: { type: 'number' },
email: { type: 'string' },
password: { type: 'string' }
}
} as const)
export type User = Infer<typeof userSchema>
export const userDataResolver = resolve<User, HookContext>({
properties: {
password: async (value) => {
// Return a hashed version of the password before storing it in the database
return bcrypt(value)
}
}
})
export const userResultResolver = resolve<User, HookContext>({
properties: {
password: async (value, _user, context) => {
// Do not return the password for external requests
if (context.params.provider) {
return undefined
}
return value
}
}
})
import { HookContext } from './definitions'
import { schema, resolve, Infer } from '@feathersjs/schema'
export const userSchema = schema({
$id: 'User',
type: 'object',
additionalProperties: false,
required: ['email', 'password'],
properties: {
id: { type: 'number' },
email: { type: 'string' },
password: { type: 'string' }
}
} as const)
export type User = Infer<typeof userSchema>
export const userDataResolver = resolve<User, HookContext>({
properties: {
password: async (value) => {
// Return a hashed version of the password before storing it in the database
return bcrypt(value)
}
}
})
export const userResultResolver = resolve<User, HookContext>({
properties: {
password: async (value, _user, context) => {
// Do not return the password for external requests
if (context.params.provider) {
return undefined
}
return value
}
}
})
import { HookContext } from './definitions.js'
import { schema, resolve, Infer } from '@feathersjs/schema'
export const userSchema = schema({
$id: 'User',
type: 'object',
additionalProperties: false,
required: ['email', 'password'],
properties: {
id: { type: 'number' },
email: { type: 'string' },
password: { type: 'string' }
}
})
export const userDataResolver = resolve({
properties: {
password: async (value) => {
// Return a hashed version of the password before storing it in the database
return bcrypt(value)
}
}
})
export const userResultResolver = resolve({
properties: {
password: async (value, _user, context) => {
// Do not return the password for external requests
if (context.params.provider) {
return undefined
}
return value
}
}
})
import { HookContext } from './definitions.js'
import { schema, resolve, Infer } from '@feathersjs/schema'
export const userSchema = schema({
$id: 'User',
type: 'object',
additionalProperties: false,
required: ['email', 'password'],
properties: {
id: { type: 'number' },
email: { type: 'string' },
password: { type: 'string' }
}
})
export const userDataResolver = resolve({
properties: {
password: async (value) => {
// Return a hashed version of the password before storing it in the database
return bcrypt(value)
}
}
})
export const userResultResolver = resolve({
properties: {
password: async (value, _user, context) => {
// Do not return the password for external requests
if (context.params.provider) {
return undefined
}
return value
}
}
})