MellKam / soundify

🎧 Lightweight integration with the Spotify Web API for modern Javascript runtimes
https://npmjs.com/@soundify/web-api
MIT License
25 stars 3 forks source link

Add the ability to call endpoint functions from the class, instead of separate functions #26

Closed MellKam closed 1 year ago

MellKam commented 1 year ago

The problem is that the endpoints are a bunch of separate functions that need to pass the client as the first argument each time. In code it look like this:

import { SpoitifyClient, getCurrentUserProfile, getUserProfile } from "soundify-web-api";

const client = new SpotifyClient("ACCESS_TOKEN");

const currentUser = await getCurrentUserProfile(client);
const user123 = await getUserProfile(client, "some-user-id-123");

The obvious question would be: why can't we do that?

import { SpotifyClient } from "soundify-web-api";

const client = new SpotifyCleint("ACCESS_TOKEN");

const currentUser = await client.getCurrentUserProfile();
const user123 = await client.getUserProfile("some-user-id-123");

The answer is this. We want to have a treeshake on the client and not import all the functions we don't need. Plus, personally I don't like to write one huge class with hundreds of methods. But for the backend, it's much easier to use this type of composition. It would be great for implementing dependencies and a good developer experience. So what can we do?

MellKam commented 1 year ago

Thanks @Satont and @crashmax-dev for implementing that class. Satont version and CrashMax version. I mostly prefer the Satont version because it easier to use, but if you have any suggestions you can write them here. I will try test it soon.

MellKam commented 1 year ago

I come up with the idea for stucture refactoring. On the paper it looks like this.

First of all, I want to separate only those things that need to be separated to import for a specific platform. Because at the moment client, endpoints and types are common things that are dublicated for both platforms (node and web).

// Node specific things (mostly authentification)
import {} from "@soundify/node";

// Web specific things (also mostly auth)
import {} from "@soundify/web";

// General functions(endpoints), types, and client
import {} from "@soudnify/api";

And I will most likely move the packages to namespace @soundify

After all ts type system and trying to create this class correctly, I'd rather just create this class by hand with all the api calls as in this example.

import * as ENDPOINTS from "./endpoints.ts";
import { SpotifyClient } from "../client.ts";
import { OmitFirst } from "../utils.ts";

type OmitFirstParameter<T extends keyof typeof ENDPOINTS> = OmitFirst<
  Parameters<typeof ENDPOINTS[T]>
>;

export class SpotifyAPIClient extends SpotifyClient {
  async addItemToPlaylist(
    ...args: OmitFirstParameter<"addItemToPlaylist">
  ) {
    return await ENDPOINTS.addItemToPlaylist(this, ...args);
  }
}