Skip to content

Conversation

donny-dont
Copy link

Add WebhookPayload which contains a discriminator to map the different payload types based on the value of event_type.

Add `WebhookPayload` which contains a `discriminator` to map the different payload types based on the value of `event_type`.
Copy link
Contributor

@ahurtado-figma ahurtado-figma left a comment

Choose a reason for hiding this comment

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

LGTM!

@ahurtado-figma ahurtado-figma self-requested a review September 29, 2025 20:33
Copy link
Contributor

@ahurtado-figma ahurtado-figma left a comment

Choose a reason for hiding this comment

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

Took another look and leaving a request for further explanation. At face value, this change makes sense to me -- but how do you see the WebhookPayload being used in this repo? It make sense to me that each webhook endpoint returns a different webhook payload type

@donny-dont
Copy link
Author

donny-dont commented Sep 29, 2025

Took another look and leaving a request for further explanation. At face value, this change makes sense to me -- but how do you see the WebhookPayload being used in this repo? It make sense to me that each webhook endpoint returns a different webhook payload type

👋 thanks for looking at this @ahurtado-figma !

So the point of adding WebhookPayload is to more accurately reflect a class hierarchy within the spec. OpenAPI uses this concept of a discriminator where it specifies a type to map to based on the value of a property. In this case each type defined in the oneOf section of WebhookPayload has a corresponding value of the event_type property that maps to that different type.

So in the case of generated code from the OpenAPI definition for a typed language there can be a WebhookPayload class that has a factory constructor which looks at event_type then creates the correct WebhookPayload class from the JSON data.

Within this repository this functionality is used in a few places. Here's Effect as an example.

Effect:
oneOf:
- $ref: "#/components/schemas/DropShadowEffect"
- $ref: "#/components/schemas/InnerShadowEffect"
- $ref: "#/components/schemas/BlurEffect"
- $ref: "#/components/schemas/TextureEffect"
- $ref: "#/components/schemas/NoiseEffect"
discriminator:
propertyName: type
mapping:
DROP_SHADOW: "#/components/schemas/DropShadowEffect"
INNER_SHADOW: "#/components/schemas/InnerShadowEffect"
LAYER_BLUR: "#/components/schemas/BlurEffect"
BACKGROUND_BLUR: "#/components/schemas/BlurEffect"
TEXTURE: "#/components/schemas/TextureEffect"
NOISE: "#/components/schemas/NoiseEffect"

@donny-dont
Copy link
Author

For some additional context I'm working on a client library in Dart and am converting the JSON values from the Figma API into Dart types. So by the definition having a discriminator I can generate a base class WebhookPayload that has a factory constructor which converts the JSON payload into a type.

abstract class WebhookPayload extends Equatable {
  const WebhookPayload({
    required this.passcode,
    required this.timestamp,
    required this.webhookId,
  });

  factory WebhookPayload.fromJson(Map<String, Object?> json) {
    final discriminator = json['event_type'];
    final construct = switch (discriminator) {
      'PING' => PingPayload.fromJson,
      'FILE_UPDATE' => FileUpdatePayload.fromJson,
      'FILE_DELETE' => FileDeletePayload.fromJson,
      'FILE_VERSION_UPDATE' => FileVersionUpdatePayload.fromJson,
      'LIBRARY_PUBLISH' => LibraryPublishPayload.fromJson,
      'FILE_COMMENT' => FileCommentPayload.fromJson,
      'DEV_MODE_STATUS_UPDATE' => DevModeStatusUpdatePayload.fromJson,
      _ => throw ArgumentError.value(
        discriminator,
        'event_type',
        'unknown event_type',
      ),
    };

    return construct(json);
  }

  /// Discriminator for [WebhookPayload] types.
  WebhookEvent get eventType;
}

You can see from ☝️ that it looks at the value of event_type and then calls the appropriate constructor based on that.

A good chunk of the patches I have locally are adding discriminators so I'd like to know if this change is acceptable before preparing those patches.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants