diff --git a/docs/api/schema/resolvers.md b/docs/api/schema/resolvers.md index f107c087db..651a7cc39c 100644 --- a/docs/api/schema/resolvers.md +++ b/docs/api/schema/resolvers.md @@ -52,13 +52,11 @@ class MyContext { } const messageResolver = resolve({ - properties: { - likes: async (value, message, context) => { - return context.getLikes(message.id) - }, - user: async (value, message, context) => { - return context.getUser(message.userId) - } + likes: async (value, message, context) => { + return context.getLikes(message.id) + }, + user: async (value, message, context) => { + return context.getUser(message.userId) } }) @@ -72,16 +70,9 @@ const resolvedMessage = await messageResolver.resolve( ) ``` -## Options - -A resolver takes the following options: - -- `properties`: An object of property names and their [resolver functions](#property-resolvers) -- `converter` (optional): A `async (data, context) => {}` function that can return a completely new representation of the data. A `converter` runs before `properties` resolvers. - ## Property resolvers -A resolver function is an `async` function that resolves a property on a data object. If it returns `undefined` the property will not be included. It gets passed the following parameters: +Property resolvers are a map of property names to resolver functions. A resolver function is an `async` function that resolves a property on a data object. If it returns `undefined` the property will not be included. It gets passed the following parameters: - `value` - The current value which can also be `undefined` - `data` - The initial data object @@ -90,15 +81,13 @@ A resolver function is an `async` function that resolves a property on a data ob ```ts const userResolver = resolve({ - properties: { - isDrinkingAge: async (value, user, context) => { - const drinkingAge = await context.getDrinkingAge(user.country) + isDrinkingAge: async (value, user, context) => { + const drinkingAge = await context.getDrinkingAge(user.country) - return user.age >= drinkingAge - }, - fullName: async (value, user, context) => { - return `${user.firstName} ${user.lastName}` - } + return user.age >= drinkingAge + }, + fullName: async (value, user, context) => { + return `${user.firstName} ${user.lastName}` } }) ``` @@ -109,6 +98,36 @@ Property resolver functions should only return a value and not have side effects +## Options + +A resolver takes the following options as the second parameter: + +- `converter` (optional): A `async (data, context) => {}` function that can return a completely new representation of the data. A `converter` runs before `properties` resolvers. + +```ts +const userResolver = resolve( + { + isDrinkingAge: async (value, user, context) => { + const drinkingAge = await context.getDrinkingAge(user.country) + + return user.age >= drinkingAge + }, + fullName: async (value, user, context) => { + return `${user.firstName} ${user.lastName}` + } + }, + { + // Convert the raw data into a new structure before running property resolvers + converter: async (rawData, context) => { + return { + firstName: rawData.data.first_name, + lastName: rawData.data.last_name + } + } + } +) +``` + ## Hooks In a Feathers application, resolvers are used through [hooks](../hooks.md) to convert service method query, data and responses. The context for these resolvers is always the [hook context](../hooks.md#hook-context). diff --git a/docs/guides/basics/schemas.md b/docs/guides/basics/schemas.md index cd3a26f60f..d4243aaf96 100644 --- a/docs/guides/basics/schemas.md +++ b/docs/guides/basics/schemas.md @@ -47,7 +47,7 @@ First we need to update the `src/services/users/users.schema.js` file with the s -```ts{1,16-17,36,47-57,70-74} +```ts{1,16-17,32,42-52,56,63-67} import crypto from 'crypto' import { resolve } from '@feathersjs/schema' import { Type, getDataValidator, getValidator, querySyntax } from '@feathersjs/typebox' @@ -69,15 +69,11 @@ export const userSchema = Type.Object( { $id: 'User', additionalProperties: false } ) export type User = Static -export const userResolver = resolve({ - properties: {} -}) +export const userResolver = resolve({}) export const userExternalResolver = resolve({ - properties: { - // The password should never be visible externally - password: async () => undefined - } + // The password should never be visible externally + password: async () => undefined }) // Schema for the basic data model (e.g. creating new entries) @@ -92,19 +88,17 @@ export const userDataSchema = Type.Pick( export type UserData = Static export const userDataValidator = getDataValidator(userDataSchema, dataValidator) export const userDataResolver = resolve({ - properties: { - password: passwordHash({ strategy: 'local' }), - avatar: async (value, user) => { - // If the user passed an avatar image, use it - if (value !== undefined) { - return value - } - - // Gravatar uses MD5 hashes from an email address to get the image - const hash = crypto.createHash('md5').update(user.email.toLowerCase()).digest('hex') - // Return the full avatar URL - return `https://s.gravatar.com/avatar/${hash}?s=60` + password: passwordHash({ strategy: 'local' }), + avatar: async (value, user) => { + // If the user passed an avatar image, use it + if (value !== undefined) { + return value } + + // Gravatar uses MD5 hashes from an email address to get the image + const hash = crypto.createHash('md5').update(user.email.toLowerCase()).digest('hex') + // Return the full avatar URL + return `https://s.gravatar.com/avatar/${hash}?s=60` } }) @@ -114,17 +108,15 @@ export const userQuerySchema = querySyntax(userQueryProperties) export type UserQuery = Static export const userQueryValidator = getValidator(userQuerySchema, queryValidator) export const userQueryResolver = resolve({ - properties: { - // If there is a user (e.g. with authentication), they are only allowed to see their own data - id: async (value, user, context) => { - // We want to be able to get a list of all users but - // only let a user modify their own data otherwise - if (context.params.user && context.method !== 'find') { - return context.params.user.id - } - - return value + // If there is a user (e.g. with authentication), they are only allowed to see their own data + id: async (value, user, context) => { + // We want to be able to get a list of all users but + // only let a user modify their own data otherwise + if (context.params.user && context.method !== 'find') { + return context.params.user.id } + + return value } }) ``` @@ -133,7 +125,7 @@ export const userQueryResolver = resolve({ -```ts{1,16-17,36,47-57,70-74} +```ts{1,16-17,32,42-52,56,63-67} import crypto from 'crypto' import { resolve } from '@feathersjs/schema' import { Type, getDataValidator, getValidator, querySyntax } from '@feathersjs/typebox' @@ -155,15 +147,11 @@ export const userSchema = Type.Object( { $id: 'User', additionalProperties: false } ) export type User = Static -export const userResolver = resolve({ - properties: {} -}) +export const userResolver = resolve({}) export const userExternalResolver = resolve({ - properties: { - // The password should never be visible externally - password: async () => undefined - } + // The password should never be visible externally + password: async () => undefined }) // Schema for the basic data model (e.g. creating new entries) @@ -174,19 +162,17 @@ export const userDataSchema = Type.Pick(userSchema, ['email', 'password', 'githu export type UserData = Static export const userDataValidator = getDataValidator(userDataSchema, dataValidator) export const userDataResolver = resolve({ - properties: { - password: passwordHash({ strategy: 'local' }), - avatar: async (value, user) => { - // If the user passed an avatar image, use it - if (value !== undefined) { - return value - } - - // Gravatar uses MD5 hashes from an email address to get the image - const hash = crypto.createHash('md5').update(user.email.toLowerCase()).digest('hex') - // Return the full avatar URL - return `https://s.gravatar.com/avatar/${hash}?s=60` + password: passwordHash({ strategy: 'local' }), + avatar: async (value, user) => { + // If the user passed an avatar image, use it + if (value !== undefined) { + return value } + + // Gravatar uses MD5 hashes from an email address to get the image + const hash = crypto.createHash('md5').update(user.email.toLowerCase()).digest('hex') + // Return the full avatar URL + return `https://s.gravatar.com/avatar/${hash}?s=60` } }) @@ -196,17 +182,15 @@ export const userQuerySchema = querySyntax(userQueryProperties) export type UserQuery = Static export const userQueryValidator = getValidator(userQuerySchema, queryValidator) export const userQueryResolver = resolve({ - properties: { - // If there is a user (e.g. with authentication), they are only allowed to see their own data - _id: async (value, user, context) => { - // We want to be able to get a list of all users but - // only let a user modify their own data otherwise - if (context.params.user && context.method !== 'find') { - return context.params.user._id - } - - return value + // If there is a user (e.g. with authentication), they are only allowed to see their own data + _id: async (value, user, context) => { + // We want to be able to get a list of all users but + // only let a user modify their own data otherwise + if (context.params.user && context.method !== 'find') { + return context.params.user._id } + + return value } }) ``` @@ -230,7 +214,7 @@ Update the `src/services/messages/messages.schema.js` file like this: -```ts{7,14-16,23-26,43-49,56,66-74} +```ts{7,14-16,22-25,38-44,50,60-64} import { resolve } from '@feathersjs/schema' import { Type, getDataValidator, getValidator, querySyntax } from '@feathersjs/typebox' import type { Static } from '@feathersjs/typebox' @@ -252,17 +236,13 @@ export const messageSchema = Type.Object( ) export type Message = Static export const messageResolver = resolve({ - properties: { - user: async (_value, message, context) => { - // Associate the user that sent the message - return context.app.service('users').get(message.userId) - } + user: async (_value, message, context) => { + // Associate the user that sent the message + return context.app.service('users').get(message.userId) } }) -export const messageExternalResolver = resolve({ - properties: {} -}) +export const messageExternalResolver = resolve({}) // Schema for creating new entries export const messageDataSchema = Type.Pick(messageSchema, ['text'], { @@ -272,14 +252,12 @@ export const messageDataSchema = Type.Pick(messageSchema, ['text'], { export type MessageData = Static export const messageDataValidator = getDataValidator(messageDataSchema, dataValidator) export const messageDataResolver = resolve({ - properties: { - userId: async (_value, _message, context) => { - // Associate the record with the id of the authenticated user - return context.params.user.id - }, - createdAt: async () => { - return Date.now() - } + userId: async (_value, _message, context) => { + // Associate the record with the id of the authenticated user + return context.params.user.id + }, + createdAt: async () => { + return Date.now() } }) @@ -295,16 +273,14 @@ export const messageQuerySchema = querySyntax(messageQueryProperties) export type MessageQuery = Static export const messageQueryValidator = getValidator(messageQuerySchema, queryValidator) export const messageQueryResolver = resolve({ - properties: { - userId: async (value, user, context) => { - // We want to be able to get a list of all messages but - // only let a user access their own messages otherwise - if (context.params.user && context.method !== 'find') { - return context.params.user.id - } - - return value + userId: async (value, user, context) => { + // We want to be able to get a list of all messages but + // only let a user access their own messages otherwise + if (context.params.user && context.method !== 'find') { + return context.params.user.id } + + return value } }) ``` @@ -313,7 +289,7 @@ export const messageQueryResolver = resolve({ -```ts{7,14-16,23-26,43-49,56,66-74} +```ts{7,14-16,22-25,38-44,50,60-64} import { resolve } from '@feathersjs/schema' import { Type, getDataValidator, getValidator, querySyntax } from '@feathersjs/typebox' import type { Static } from '@feathersjs/typebox' @@ -335,17 +311,13 @@ export const messageSchema = Type.Object( ) export type Message = Static export const messageResolver = resolve({ - properties: { - user: async (_value, message, context) => { - // Associate the user that sent the message - return context.app.service('users').get(message.userId) - } + user: async (_value, message, context) => { + // Associate the user that sent the message + return context.app.service('users').get(message.userId) } }) -export const messageExternalResolver = resolve({ - properties: {} -}) +export const messageExternalResolver = resolve({}) // Schema for creating new entries export const messageDataSchema = Type.Pick(messageSchema, ['text'], { @@ -355,14 +327,12 @@ export const messageDataSchema = Type.Pick(messageSchema, ['text'], { export type MessageData = Static export const messageDataValidator = getDataValidator(messageDataSchema, dataValidator) export const messageDataResolver = resolve({ - properties: { - userId: async (_value, _message, context) => { - // Associate the record with the id of the authenticated user - return context.params.user._id - }, - createdAt: async () => { - return Date.now() - } + userId: async (_value, _message, context) => { + // Associate the record with the id of the authenticated user + return context.params.user._id + }, + createdAt: async () => { + return Date.now() } }) @@ -374,16 +344,14 @@ export const messageQuerySchema = querySyntax(messageQueryProperties) export type MessageQuery = Static export const messageQueryValidator = getValidator(messageQuerySchema, queryValidator) export const messageQueryResolver = resolve({ - properties: { - userId: async (value, user, context) => { - // We want to be able to get a list of all messages but - // only let a user access their own messages otherwise - if (context.params.user && context.method !== 'find') { - return context.params.user._id - } - - return value + userId: async (value, user, context) => { + // We want to be able to get a list of all messages but + // only let a user access their own messages otherwise + if (context.params.user && context.method !== 'find') { + return context.params.user._id } + + return value } }) ``` diff --git a/packages/cli/src/authentication/templates/schema.json.tpl.ts b/packages/cli/src/authentication/templates/schema.json.tpl.ts index a92ceb62da..8b68acb73e 100644 --- a/packages/cli/src/authentication/templates/schema.json.tpl.ts +++ b/packages/cli/src/authentication/templates/schema.json.tpl.ts @@ -36,9 +36,7 @@ export const ${camelName}Schema = { } } as const export type ${upperName} = FromSchema -export const ${camelName}Resolver = resolve<${upperName}, HookContext>({ - properties: {} -}) +export const ${camelName}Resolver = resolve<${upperName}, HookContext>({}) // Schema for the basic data model (e.g. creating new entries) export const ${camelName}DataSchema = { @@ -53,16 +51,12 @@ export const ${camelName}DataSchema = { export type ${upperName}Data = FromSchema export const ${camelName}DataValidator = getDataValidator(${camelName}DataSchema, dataValidator) export const ${camelName}DataResolver = resolve<${upperName}Data, HookContext>({ - properties: { - ${localTemplate(authStrategies, `password: passwordHash({ strategy: 'local' })`)} - } + ${localTemplate(authStrategies, `password: passwordHash({ strategy: 'local' })`)} }) export const ${camelName}ExternalResolver = resolve<${upperName}, HookContext>({ - properties: { - // The password should never be visible externally - password: async () => undefined - } + // The password should never be visible externally + password: async () => undefined }) // Schema for allowed query properties @@ -77,15 +71,13 @@ export const ${camelName}QuerySchema = { export type ${upperName}Query = FromSchema export const ${camelName}QueryValidator = getValidator(${camelName}QuerySchema, queryValidator) export const ${camelName}QueryResolver = resolve<${upperName}Query, HookContext>({ - properties: { - // If there is a user (e.g. with authentication), they are only allowed to see their own data - ${type === 'mongodb' ? '_id' : 'id'}: async (value, user, context) => { - if (context.params.user) { - return context.params.user.${type === 'mongodb' ? '_id' : 'id'} - } - - return value + // If there is a user (e.g. with authentication), they are only allowed to see their own data + ${type === 'mongodb' ? '_id' : 'id'}: async (value, user, context) => { + if (context.params.user) { + return context.params.user.${type === 'mongodb' ? '_id' : 'id'} } + + return value } }) ` diff --git a/packages/cli/src/authentication/templates/schema.typebox.tpl.ts b/packages/cli/src/authentication/templates/schema.typebox.tpl.ts index e8ffa8ca59..cc90a835b1 100644 --- a/packages/cli/src/authentication/templates/schema.typebox.tpl.ts +++ b/packages/cli/src/authentication/templates/schema.typebox.tpl.ts @@ -29,15 +29,11 @@ export const ${camelName}Schema = Type.Object({ .join(',\n')} },{ $id: '${upperName}', additionalProperties: false }) export type ${upperName} = Static -export const ${camelName}Resolver = resolve<${upperName}, HookContext>({ - properties: {} -}) +export const ${camelName}Resolver = resolve<${upperName}, HookContext>({}) export const ${camelName}ExternalResolver = resolve<${upperName}, HookContext>({ - properties: { - // The password should never be visible externally - password: async () => undefined - } + // The password should never be visible externally + password: async () => undefined }) // Schema for the basic data model (e.g. creating new entries) @@ -49,9 +45,7 @@ export const ${camelName}DataSchema = Type.Pick(${camelName}Schema, [ export type ${upperName}Data = Static export const ${camelName}DataValidator = getDataValidator(${camelName}DataSchema, dataValidator) export const ${camelName}DataResolver = resolve<${upperName}, HookContext>({ - properties: { - ${localTemplate(authStrategies, `password: passwordHash({ strategy: 'local' })`)} - } + ${localTemplate(authStrategies, `password: passwordHash({ strategy: 'local' })`)} }) // Schema for allowed query properties @@ -63,15 +57,13 @@ export const ${camelName}QuerySchema = querySyntax(${camelName}QueryProperties) export type ${upperName}Query = Static export const ${camelName}QueryValidator = getValidator(${camelName}QuerySchema, queryValidator) export const ${camelName}QueryResolver = resolve<${upperName}Query, HookContext>({ - properties: { - // If there is a user (e.g. with authentication), they are only allowed to see their own data - ${type === 'mongodb' ? '_id' : 'id'}: async (value, user, context) => { - if (context.params.user) { - return context.params.user.${type === 'mongodb' ? '_id' : 'id'} - } - - return value + // If there is a user (e.g. with authentication), they are only allowed to see their own data + ${type === 'mongodb' ? '_id' : 'id'}: async (value, user, context) => { + if (context.params.user) { + return context.params.user.${type === 'mongodb' ? '_id' : 'id'} } + + return value } }) ` diff --git a/packages/cli/src/service/templates/schema.json.tpl.ts b/packages/cli/src/service/templates/schema.json.tpl.ts index f713559151..290d80bdb2 100644 --- a/packages/cli/src/service/templates/schema.json.tpl.ts +++ b/packages/cli/src/service/templates/schema.json.tpl.ts @@ -29,12 +29,8 @@ export const ${camelName}Schema = { } } as const export type ${upperName} = FromSchema -export const ${camelName}Resolver = resolve<${upperName}, HookContext>({ - properties: {} -}) -export const ${camelName}ExternalResolver = resolve<${upperName}, HookContext>({ - properties: {} -}) +export const ${camelName}Resolver = resolve<${upperName}, HookContext>({}) +export const ${camelName}ExternalResolver = resolve<${upperName}, HookContext>({}) // Schema for creating new data export const ${camelName}DataSchema = { @@ -50,9 +46,7 @@ export const ${camelName}DataSchema = { } as const export type ${upperName}Data = FromSchema export const ${camelName}DataValidator = getDataValidator(${camelName}DataSchema, dataValidator) -export const ${camelName}DataResolver = resolve<${upperName}Data, HookContext>({ - properties: {} -}) +export const ${camelName}DataResolver = resolve<${upperName}Data, HookContext>({}) // Schema for allowed query properties export const ${camelName}QuerySchema = { @@ -65,9 +59,7 @@ export const ${camelName}QuerySchema = { } as const export type ${upperName}Query = FromSchema export const ${camelName}QueryValidator = getValidator(${camelName}QuerySchema, queryValidator) -export const ${camelName}QueryResolver = resolve<${upperName}Query, HookContext>({ - properties: {} -}) +export const ${camelName}QueryResolver = resolve<${upperName}Query, HookContext>({}) ` export const generate = (ctx: ServiceGeneratorContext) => diff --git a/packages/cli/src/service/templates/schema.typebox.tpl.ts b/packages/cli/src/service/templates/schema.typebox.tpl.ts index 761472a105..4e2e68f660 100644 --- a/packages/cli/src/service/templates/schema.typebox.tpl.ts +++ b/packages/cli/src/service/templates/schema.typebox.tpl.ts @@ -20,13 +20,9 @@ export const ${camelName}Schema = Type.Object({ text: Type.String() }, { $id: '${upperName}', additionalProperties: false }) export type ${upperName} = Static -export const ${camelName}Resolver = resolve<${upperName}, HookContext>({ - properties: {} -}) +export const ${camelName}Resolver = resolve<${upperName}, HookContext>({}) -export const ${camelName}ExternalResolver = resolve<${upperName}, HookContext>({ - properties: {} -}) +export const ${camelName}ExternalResolver = resolve<${upperName}, HookContext>({}) // Schema for creating new entries export const ${camelName}DataSchema = Type.Pick(${camelName}Schema, ['text'], { @@ -34,9 +30,7 @@ export const ${camelName}DataSchema = Type.Pick(${camelName}Schema, ['text'], { }) export type ${upperName}Data = Static export const ${camelName}DataValidator = getDataValidator(${camelName}DataSchema, dataValidator) -export const ${camelName}DataResolver = resolve<${upperName}, HookContext>({ - properties: {} -}) +export const ${camelName}DataResolver = resolve<${upperName}, HookContext>({}) // Schema for allowed query properties export const ${camelName}QueryProperties = Type.Pick(${camelName}Schema, [ @@ -45,9 +39,7 @@ export const ${camelName}QueryProperties = Type.Pick(${camelName}Schema, [ export const ${camelName}QuerySchema = querySyntax(${camelName}QueryProperties) export type ${upperName}Query = Static export const ${camelName}QueryValidator = getValidator(${camelName}QuerySchema, queryValidator) -export const ${camelName}QueryResolver = resolve<${upperName}Query, HookContext>({ - properties: {} -}) +export const ${camelName}QueryResolver = resolve<${upperName}Query, HookContext>({}) ` export const generate = (ctx: ServiceGeneratorContext) => diff --git a/packages/cli/src/service/type/custom.tpl.ts b/packages/cli/src/service/type/custom.tpl.ts index 1c244601c9..365c96aee2 100644 --- a/packages/cli/src/service/type/custom.tpl.ts +++ b/packages/cli/src/service/type/custom.tpl.ts @@ -3,7 +3,7 @@ import { renderSource } from '../../commons' import { ServiceGeneratorContext } from '../index' export const template = ({ className, upperName, schema, fileName, relative }: ServiceGeneratorContext) => ` -import type { Id, NullableId, Params } from '@feathersjs/feathers' +import type { Id, NullableId, Params, ServiceInterface } from '@feathersjs/feathers' import type { Application } from '${relative}/declarations' ${ @@ -30,7 +30,7 @@ export interface ${upperName}Params extends Params<${upperName}Query> { } // This is a skeleton for a custom service class. Remove or add the methods you need here -export class ${className} { +export class ${className} implements ServiceInterface<${upperName}, ${upperName}Data, ${upperName}Params> { constructor (public options: ${className}Options) { } diff --git a/packages/schema/src/resolver.ts b/packages/schema/src/resolver.ts index de78fc8ab1..a480b72e3a 100644 --- a/packages/schema/src/resolver.ts +++ b/packages/schema/src/resolver.ts @@ -18,8 +18,16 @@ export type ResolverConverter = ( status: ResolverStatus ) => Promise -export interface ResolverConfig { +export interface ResolverOptions { schema?: Schema + /** + * A converter function that is run before property resolvers + * to transform the initial data into a different format. + */ + converter?: ResolverConverter +} + +export interface ResolverConfig extends ResolverOptions { /** * @deprecated Use the `validateData` and `validateQuery` hooks explicitly instead */ @@ -28,11 +36,6 @@ export interface ResolverConfig { * The properties to resolve */ properties: PropertyResolverMap - /** - * A converter function that is run before property resolvers - * to transform the initial data into a different format. - */ - converter?: ResolverConverter } export interface ResolverStatus { @@ -155,6 +158,18 @@ export class Resolver { * @param options The configuration for the returned resolver * @returns A new resolver instance */ -export function resolve(options: ResolverConfig) { - return new Resolver(options) +export function resolve( + properties: PropertyResolverMap, + options?: ResolverOptions +): Resolver +export function resolve(options: ResolverConfig): Resolver +export function resolve( + properties: PropertyResolverMap | ResolverConfig, + options?: ResolverOptions +) { + const settings = ( + (properties as ResolverConfig).properties ? properties : { properties, ...options } + ) as ResolverConfig + + return new Resolver(settings) } diff --git a/packages/schema/test/fixture.ts b/packages/schema/test/fixture.ts index 6155672ad9..6855bb7aeb 100644 --- a/packages/schema/test/fixture.ts +++ b/packages/schema/test/fixture.ts @@ -74,15 +74,13 @@ export const userResolver = resolve>({ export const userExternalResolver = resolve>({ properties: { - password: async () => undefined, + password: async (): Promise => undefined, email: async () => '[redacted]' } }) export const secondUserResolver = resolve>({ - properties: { - name: async (value, user) => `${value} (${user.email})` - } + name: async (value, user) => `${value} (${user.email})` }) export const messageDataSchema = { @@ -152,14 +150,12 @@ export type MessageQuery = FromSchema export const messageQueryValidator = getValidator(messageQuerySchema, fixtureAjv) export const messageQueryResolver = resolve>({ - properties: { - userId: async (value, _query, context) => { - if (context.params?.user) { - return context.params.user.id - } - - return value + userId: async (value, _query, context) => { + if (context.params?.user) { + return context.params.user.id } + + return value } }) diff --git a/packages/schema/test/resolver.test.ts b/packages/schema/test/resolver.test.ts index c5101ecd58..3015208906 100644 --- a/packages/schema/test/resolver.test.ts +++ b/packages/schema/test/resolver.test.ts @@ -26,7 +26,7 @@ describe('@feathersjs/schema/resolver', () => { it('simple resolver', async () => { const userResolver = resolve({ properties: { - password: async () => undefined, + password: async (): Promise => undefined, name: async (_name, user, ctx, status) => { assert.deepStrictEqual(ctx, context) @@ -82,7 +82,7 @@ describe('@feathersjs/schema/resolver', () => { schema: userFeathersSchema, validate: 'after', properties: { - firstName: async () => undefined + firstName: async (): Promise => undefined } })