feathers
feathers copied to clipboard
[feathers-dove] Client service return type for `find` with MongoDB adapter
Steps to reproduce
feathers generate app
touch src/test.ts
// src/test.js
import io from 'socket.io-client'
import socketio from '@feathersjs/socketio-client'
import authentication from '@feathersjs/authentication-client'
import { createClient } from './client'
const client = createClient(socketio(io('http://localhost:3030')))
client.configure(authentication() as any)
client.authenticate({
strategy: 'local',
email: '[email protected]',
password: 'letmein'
})
const users = client.service('users')
.find()
.then((users) => console.log(users))
Expected behavior
The return type for find is Promise<UsersResult | UsersResult[]>
so it should give
[ { _id: '62eaa29933cef3658cf04fa9', email: '[email protected]' } ]
Actual behavior
Returns
{ total: 1,
limit: 10,
skip: 0,
data: [ { _id: '62eaa29933cef3658cf04fa9', email: '[email protected]' } ] }
System configuration
{
"dependencies": {
"@feathersjs/authentication": "^5.0.0-pre.28",
"@feathersjs/authentication-client": "^5.0.0-pre.28",
"@feathersjs/authentication-local": "^5.0.0-pre.28",
"@feathersjs/authentication-oauth": "^5.0.0-pre.28",
"@feathersjs/configuration": "^5.0.0-pre.28",
"@feathersjs/errors": "^5.0.0-pre.28",
"@feathersjs/feathers": "^5.0.0-pre.28",
"@feathersjs/koa": "^5.0.0-pre.28",
"@feathersjs/mongodb": "^5.0.0-pre.28",
"@feathersjs/schema": "^5.0.0-pre.28",
"@feathersjs/socketio": "^5.0.0-pre.28",
"@feathersjs/socketio-client": "^5.0.0-pre.28",
"@feathersjs/transport-commons": "^5.0.0-pre.28",
"koa-static": "^5.0.0",
"mongodb": "^4.8.1",
"socket.io-client": "^4.5.1",
"winston": "^3.8.1"
},
"devDependencies": {
"@types/koa-static": "^4.0.2",
"@types/mocha": "^9.1.1",
"@types/node": "^18.6.3",
"axios": "^0.27.2",
"cross-env": "^7.0.3",
"mocha": "^10.0.0",
"nodemon": "^2.0.19",
"prettier": "^2.7.1",
"shx": "^0.3.4",
"ts-node": "^10.9.1",
"typescript": "^4.7.4"
}
}
The issue lies with the generated client.js file:
export interface ServiceTypes {
users: Service<UsersResult, UsersData, Params<UsersQuery>>
// A mapping of client side services
}
The UsersService interface differs from the Service interface:
// as per Service interface
interface Service {
find(params?: P): Promise<T | T[]>;
}
// actual
interface UsersService {
find(params?: P): Promise<Paginated<T[]>>;
}
There might be a more obvious solution to this, but I employed a ClientService type which uses the methods actually implemented by a particular service:
// declarations.js
export type ServiceMethod = 'find' | 'get' | 'create' | 'update' | 'patch' | 'remove'
export type ClientService<S extends ServiceInterface> = {
[M in ServiceMethod & keyof S]: S[M]
}
and use it like this
// client.js
import { ClientService } from './declarations'
import UsersService from './services/users/users.class'
export interface ServiceTypes {
users: ClientService<UsersService>
}
Does this make sense?
Totally. I noticed that issue and then forgot about adding it in the PR. I think we need an adapter service interface in core.
This will be closed in the next prerelease via https://github.com/feathersjs/feathers/pull/2750