Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🚧 refactor(types): replace EmitterEventWebhookPayloadMap #441

Closed
wants to merge 6 commits into from

Conversation

jablko
Copy link
Contributor

@jablko jablko commented Feb 4, 2021

Can we eliminate get-webhook-payload-type-from-event.ts thanks to #435?

  • Replace EmitterEventWebhookPayloadMap[TName] with EventPayloadMap[TWebhookEvent] & { action: TAction }
  • Replace keyof EmitterEventWebhookPayloadMap with typeof emitterEventNames[number]

@G-Rath
Copy link
Member

G-Rath commented Feb 4, 2021

I had originally laid the types out like this (or similar to this), but decided against it in favor of how it is currently as it's easier to predict the behaviour (both in typings and in performance).

EmitterEventWebhookPayloadMap[keyof EmitterEventWebhookPayloadMap],
{ action: string }
EmitterWebhookEvent["payload"],
{ action: any }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{ action: any }
{ action: string }

@G-Rath
Copy link
Member

G-Rath commented Feb 4, 2021

I've not checked out this out locally, but I feel like it's not preserving the mapping of the event + action to the specific type for that action. We're probably not got any tests covering this as there are some subtle differences in the events.

I'll push one up so we can see.

Nope it'll be fine because that's handled by the types for each payload being a union 🤦

src/types.ts Outdated
[K in Exclude<
typeof emitterEventNames[number],
"error"
>]: K extends `${infer TWebhookEvent}.${infer TAction}`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please make this a "type function"? i.e.

type WithAction<...> = K extends ... // etc

src/types.ts Outdated

export type EmitterWebhookEventMap = {
[K in keyof EmitterEventPayloadMap]: BaseWebhookEvent<K>;
[K in Exclude<
typeof emitterEventNames[number],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think let's make this a type alias in the generated type:

export type EmitterEventName = typeof emitterEventNames[number];

Copy link
Member

@G-Rath G-Rath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to get started on a next branch, which'll likely include this change so going to hold off merging it for now.

@G-Rath G-Rath mentioned this pull request Feb 5, 2021
@jablko jablko changed the title refactor: replace EmitterEventWebhookPayloadMap refactor(types): replace EmitterEventWebhookPayloadMap Feb 5, 2021
@G-Rath
Copy link
Member

G-Rath commented Feb 5, 2021

Just FYI, as I mentioned in #444: this change causes massive performance problems in the current version of WebStorm - while TypeScript seems to be able to handle it fine, I don't think there's a huge gain to be had that makes it worth putting such a massive blocker on anyone using that IDE.

I've submitted an issue on YouTrack and pinged the team, so hopefully it'll get fixed promptly (but even once fixed we'd want to wait for the release, which'd be a few months later).

@jablko
Copy link
Contributor Author

jablko commented Feb 5, 2021

I wonder if removing EmitterWebhookEventMap/EmitterEventMap would make a difference? When you get a chance, would you mind seeing whether the latest revision makes a difference in WebStorm, one way or the other?

@G-Rath
Copy link
Member

G-Rath commented Feb 5, 2021

That seems to have fixed both this and the performance problems caused by inferring the impact of transform in #440 🎉

Currently I'm on the fence about shipping this because of the huge impact if I'm wrong, but def going to keep this patch around to apply it at a later date:

patch
Index: src/types.ts
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/types.ts b/src/types.ts
--- a/src/types.ts	(revision 560ff73ef02453fd0a28705e042e8ad3538c43ef)
+++ b/src/types.ts	(date 1612557132345)
@@ -1,25 +1,33 @@
-import type { RequestError } from "@octokit/request-error";
-import type { EmitterEventWebhookPayloadMap } from "./generated/get-webhook-payload-type-from-event";
+import { RequestError } from '@octokit/request-error';
+import type {
+  EventPayloadMap,
+  Schema,
+  WebhookEventName,
+} from "@octokit/webhooks-definitions/schema";
+import type { EmitterEventName } from "./generated/webhook-names";
+
+export { EmitterEventName };
 
-export type EmitterWebhookEventMap = {
-  [K in keyof EmitterEventWebhookPayloadMap]: BaseWebhookEvent<K>;
-};
+type EmitterEventPayloadMap = { "*": Schema } & EventPayloadMap;
 
-export type EmitterWebhookEventName = keyof EmitterWebhookEventMap;
-export type EmitterWebhookEvent = EmitterWebhookEventMap[EmitterWebhookEventName];
+export type EmitterWebhookEventName = EmitterEventName;
 
-type ToWebhookEvent<
-  TEmitterEvent extends string
-> = TEmitterEvent extends `${infer TWebhookEvent}.${string}`
-  ? TWebhookEvent
-  : TEmitterEvent;
+export type EmitterWebhookEvent<
+  TEmitterEvent = WebhookEventName
+> = TEmitterEvent extends `${infer TWebhookEvent}.${infer TAction}`
+  ? BaseWebhookEvent<Extract<TWebhookEvent, keyof EmitterEventPayloadMap>> & {
+      payload: { action: TAction };
+    }
+  : BaseWebhookEvent<Extract<TEmitterEvent, keyof EmitterEventPayloadMap>>;
 
-interface BaseWebhookEvent<
-  TName extends EmitterWebhookEventName = EmitterWebhookEventName
-> {
+type EmitterEvent<TEmitterEvent> = TEmitterEvent extends "error"
+  ? WebhookEventHandlerError
+  : EmitterWebhookEvent<TEmitterEvent>;
+
+interface BaseWebhookEvent<TName extends keyof EmitterEventPayloadMap> {
   id: string;
-  name: ToWebhookEvent<TName>;
-  payload: EmitterEventWebhookPayloadMap[TName];
+  name: TName;
+  payload: EmitterEventPayloadMap[TName];
 }
 
 export interface Options<
@@ -39,15 +47,9 @@
 // type MaybeArray<T> = T | T[];
 
 export type HandlerFunction<
-  TName extends EmitterWebhookEventName | EmitterWebhookEventName[],
+  TName extends EmitterEventName | EmitterEventName[],
   TTransformed
-> = (
-  event: EmitterWebhookEventMap[Extract<
-    EmitterWebhookEventName,
-    EnsureArray<TName>[number]
-  >] &
-    TTransformed
-) => any;
+> = (event: EmitterEvent<EnsureArray<TName>[number]> & TTransformed) => any;
 
 type Hooks = {
   [key: string]: Function[];
Index: test/typescript-validate.ts
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/test/typescript-validate.ts b/test/typescript-validate.ts
--- a/test/typescript-validate.ts	(revision 560ff73ef02453fd0a28705e042e8ad3538c43ef)
+++ b/test/typescript-validate.ts	(date 1612557132359)
@@ -9,7 +9,7 @@
   WebhookError,
 } from "../src/index";
 import { createServer } from "http";
-import { HandlerFunction, EmitterWebhookEventName } from "../src/types";
+import { EmitterEventName, HandlerFunction } from '../src/types';
 
 // ************************************************************
 // THIS CODE IS NOT EXECUTED. IT IS FOR TYPECHECKING ONLY
@@ -23,7 +23,7 @@
   }
 };
 
-declare const on: <E extends EmitterWebhookEventName>(
+declare const on: <E extends EmitterEventName>(
   name: E | E[],
   callback: HandlerFunction<E, unknown>
 ) => void;
Index: src/generated/webhook-names.ts
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/generated/webhook-names.ts b/src/generated/webhook-names.ts
--- a/src/generated/webhook-names.ts	(revision 560ff73ef02453fd0a28705e042e8ad3538c43ef)
+++ b/src/generated/webhook-names.ts	(date 1612556741606)
@@ -206,4 +206,6 @@
   "workflow_run",
   "workflow_run.completed",
   "workflow_run.requested",
-];
+] as const;
+
+export type EmitterEventName = typeof emitterEventNames[number];

In saying that, I think it probably has fixed the issue and I'm just being paranoid 😅
I'll let things sit for a bit so that the WebStorm team has a chance to look into it, and to give myself some time to put the types through their paces a bit more to confirm, but I think this should be fine to ship in the near future! 🎉

(/cc @anstarovoyt, since it might help you pin down where the performance issue is)

@jablko
Copy link
Contributor Author

jablko commented Feb 5, 2021

Awesome, thanks! 👍

@oscard0m
Copy link
Member

oscard0m commented Feb 7, 2021

I've submitted an issue on YouTrack and pinged the team, so hopefully it'll get fixed promptly (but even once fixed we'd want to wait for the release, which'd be a few months later).

Could you link please the issue on YouTrack, please? :) 🙏🏽

@G-Rath G-Rath changed the title refactor(types): replace EmitterEventWebhookPayloadMap 🚧 refactor(types): replace EmitterEventWebhookPayloadMap Feb 7, 2021
@G-Rath
Copy link
Member

G-Rath commented Feb 7, 2021

https://youtrack.jetbrains.com/issue/WEB-49483

@wolfy1339 wolfy1339 added Type: Maintenance Any dependency, housekeeping, and clean up Issue or PR typescript Relevant to TypeScript users only labels Feb 7, 2021
@gr2m gr2m closed this in #444 Feb 8, 2021
@github-actions
Copy link
Contributor

🎉 This issue has been resolved in version 8.0.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Maintenance Any dependency, housekeeping, and clean up Issue or PR typescript Relevant to TypeScript users only
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants