octokit / octokit.js

The all-batteries-included GitHub SDK for Browsers, Node.js, and Deno.
MIT License
6.94k stars 1.02k forks source link

Separate types from code and make types composable/extendable #2127

Open gr2m opened 3 years ago

gr2m commented 3 years ago

Currently all JS Octokit modules depend on @ocotkit/types. @octokit/types include definitions for all 600+ REST API endpoints for api.github.com and primitives such as types for Requests and responses that are not extendable.

Problems

  1. All endpoint types are for api.github.com. They cannot be replaced for GHAE or a specific GHES version. They cannot be imported selectively.
  2. The types cannot be extended by plugins. Plugins often time introduce new Octokit options such as throttle, extend request options and/or responses. Authentication strategies are a special kind of plugins that provide custom auth options, but they cannot define the options in a way that would provide IntelliSense to users of the authentication strategy. Plugins also hook into the request life cycle and amend requests/responses, but the types for requests/responses provided by @octokit/types cannot be extended at this point.

Solution

Take advantage of declaration merging and global augmentation to make it possible for imported code to amend the global Octokit Types.

For the endpoint types, I see two approaches:

  1. Create entirely separate types for api.github.com, GHES-3.0, GHES-3.1
  2. Use types for api.github.com as the starting point, then create types for the GHES/GHAE versions as an extension of that. Endpoints that do not (yet) exist in the target version can be set to never with an explanation. If the endpoint exists in both environments but differs in its request parameters or response, create a union of both types. We could introduce a new option such as request.version which defaults to "api.github.com" but which can be set to whatever version of the REST API endpoint types were loaded. So when it's set to "ghes-3.1" then the types from that version are used explicitly, instead of the union between the types of api.github.com and ghes-3.1.

I'd prefer the 2nd approach as I'd expect it to be a better developer experience.

For developers who write code that is meant to run against both api.github.com and a minimal version of GHES, we could create virtual versions such as ghes-3.0-compatible, which will either only include types that are covered by both environments, or make clear which endpoints/properties do not exist in either.

Benefits

Steps

@octokit-next/* packages

Implement changes in Octokit

Backlog

gr2m commented 3 years ago

This will unlock https://github.com/octokit/core.js/issues/323

gr2m commented 3 years ago

For the curious ones, here's what this is all about

https://user-images.githubusercontent.com/39992/129640719-48be7f8c-2fce-4e74-9556-3794a73e291b.mp4

gr2m commented 2 years ago

Another update, in 4 parts, because

  1. There is more to show
  2. I'm giving TypeScript a hard time

Part I: upcoming @octokit/core without any REST API types and with types for github.com

https://user-images.githubusercontent.com/39992/133866362-2b758476-ee5f-4c4b-b81c-d3f545126154.mp4

Part II: types for GitHub Enterprise Server (GHES)

https://user-images.githubusercontent.com/39992/133866363-e6ce9da9-f9c8-436a-ab4e-7c394eb14130.mov

Part III: set API version on new Octokit() constructor

https://user-images.githubusercontent.com/39992/133866368-f7256212-32ee-413a-82b7-b9c4779636b9.mp4

Part IV: types for GHES-compatible versions

https://user-images.githubusercontent.com/39992/133866371-a4e636ef-a6d9-4684-9159-a8eb1b9fe1ab.mp4