feathers
                                
                                 feathers copied to clipboard
                                
                                    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