feathersjs / feathers

The API and real-time application framework
https://feathersjs.com
MIT License
15.08k stars 752 forks source link

Client should include at least the authentication part #3134

Closed lukvermeulen closed 1 year ago

lukvermeulen commented 1 year ago

Description

The feathers client could include the authentication configuration.

Currently, using the typed client with a fresh v5 app results in the following typescript errors:

Argument of type "authentication" is not assignable to parameter of type "connection" and Property "user" does not exist on type "TransportConnection<ServiceTypes>

in this line (swr file below):

const { user } = await client.get("authentication");

Setup

This is my feathers-client on the web app:

import { createClient } from "api";
import rest from "@feathersjs/rest-client";
import authentication from "@feathersjs/authentication-client";

const apiUrl = process.env["NEXT_PUBLIC_API_URL"];

const fetchConnection =
  typeof window !== "undefined" ? window.fetch.bind(window) : fetch;

const restClient = rest(apiUrl);

const client = createClient(restClient.fetch(fetchConnection));

client.configure(authentication());

export { client };

This is my swr file on the client:

import { client } from './feathers-client'
import useSWR from 'swr'
import { User } from './client'

async function userFetcher() {
  const { user } = await client.get('authentication')
  return user as User
}

export function useUser() {
  const { data, mutate, error } = useSWR('get_authentication', userFetcher)

  const loading = !data && !error

  return {
    loading,
    error,
    user: data,
    mutate
  }
}

Proposed hotfix

@daffl proposed the pass the configuration type to createClient on discord:

Testing this however appears not to fix the issue.

import { createClient } from "api";
import rest from "@feathersjs/rest-client";
import type { AuthenticationResult } from '@feathersjs/authentication'
import authentication from "@feathersjs/authentication-client";

const apiUrl = process.env["NEXT_PUBLIC_API_URL"];

const fetchConnection =
  typeof window !== "undefined" ? window.fetch.bind(window) : fetch;

const restClient = rest(apiUrl);

type Configuration = {
  authentication: Promise<AuthenticationResult>
}

const client = createClient<Configuration>(restClient.fetch(fetchConnection));

client.configure(authentication());

export { client };
daffl commented 1 year ago

The latest version does include the authentication client setup. This is how it currently looks like: https://github.com/feathersjs/feathers-chat/blob/dove/feathers-chat-ts/src/client.ts

The configuration type was intended to be used if you want to use a typed app.get('authentication') on the client. So with an app that has a client.ts like the one linked everything can be initialised like this:

import { createClient } from "api";
import rest from "@feathersjs/rest-client";
import type { AuthenticationResult } from '@feathersjs/authentication'
import authentication from "@feathersjs/authentication-client";

const apiUrl = process.env["NEXT_PUBLIC_API_URL"];

const fetchConnection =
  typeof window !== "undefined" ? window.fetch.bind(window) : fetch;

const restClient = rest(apiUrl);

type Configuration = {
  authentication: Promise<AuthenticationResult>
}

export const client = createClient<Configuration>(restClient.fetch(fetchConnection));
lukvermeulen commented 1 year ago

Hi @daffl , thanks for the example and the response! Sorry for coming back so late to this.

I tried the configuration above, and as it looks promising - it appears to be not working for me with version 5.0.8.

Where is the generic "Configuration" type in export const createClient = <Configuration = any>[...] (line 29) used - so it could have an effect on the returned result? https://github.com/feathersjs/feathers-chat/blob/dove/feathers-chat-ts/src/client.ts

Thanks for any hints I might have missed!

Adding on this:

adding the authentication: Promise<AuthenticationResult directly inside the client.ts allows the client.get("authentication") to work. The AuthenticationResult is however still of type [key: string]: any, thus not that useful. And I believe, that using the generic Configuration is useful, however it looks unused/unimplemented in the linked setup.