Skip to content
This repository was archived by the owner on Dec 17, 2024. It is now read-only.
This repository was archived by the owner on Dec 17, 2024. It is now read-only.

Swagger schemas are missing the required field #222

@DmitryScaletta

Description

@DmitryScaletta

I use swagger.json for generating typescript definitions:

npx openapi-typescript https://github.com/SevenTV/API/raw/dev/internal/api/rest/v3/docs/swagger.json

And now it generates types where all fields in schemas are optional, because they are missing the required field.

export interface definitions {
  // ...
  "model.ActiveEmoteModel": {
    actor_id?: string;
    data?: definitions["model.EmotePartialModel"];
    flags?: definitions["model.ActiveEmoteFlagModel"];
    id?: string;
    name?: string;
    origin_id?: string;
    timestamp?: number;
  };
  // ...
}

Schema Object Examples with required in the docs: https://swagger.io/specification/v2/#:~:text=Schema%20Object%20Examples
Example how it should look like:

{
  "model.ActiveEmoteModel": {
    "type": "object",
+    "required": [
+      "actor_id",
+      "data",
+      "flags",
+      "id",
+      "name",
+      "origin_id",
+      "timestamp",
+    ],
    "properties": {
      "actor_id": {
        "type": "string",
        "x-nullable": true
      },
      "data": {
        "allOf": [
          {
            "$ref": "#/definitions/model.EmotePartialModel"
          }
        ],
        "x-nullable": true
      },
      "flags": {
        "$ref": "#/definitions/model.ActiveEmoteFlagModel"
      },
      "id": {
        "type": "string"
      },
      "name": {
        "type": "string"
      },
      "origin_id": {
        "type": "string",
        "x-omitempty": true
      },
      "timestamp": {
        "type": "integer"
      }
    }
  },
}
Full generated types with openapi-typescript
/**
 * This file was auto-generated by openapi-typescript.
 * Do not make direct changes to the file.
 */

export interface paths {
  "/emote-sets": {
    /** Search for Emote Sets */
    get: {
      parameters: {
        query: {
          /** search by emote set name / tags */
          query?: string;
        };
      };
      responses: {
        /** OK */
        200: {
          schema: definitions["model.EmoteSetModel"][];
        };
      };
    };
  };
 // ...
}

export interface definitions {
  "model.ActiveEmoteFlagModel": 1 | 65536 | 131072 | 262144;
  "model.ActiveEmoteModel": {
    actor_id?: string;
    data?: definitions["model.EmotePartialModel"];
    flags?: definitions["model.ActiveEmoteFlagModel"];
    id?: string;
    name?: string;
    origin_id?: string;
    timestamp?: number;
  };
  "model.CosmeticBadgeModel": {
    host?: definitions["model.ImageHost"];
    id?: string;
    name?: string;
    tag?: string;
    tooltip?: string;
  };
  "model.CosmeticPaintCanvasRepeat":
    | "no-repeat"
    | "repeat-x"
    | "repeat-y"
    | "revert"
    | "round"
    | "space";
  "model.CosmeticPaintFlair": {
    /** Base64-encoded image or vector data */
    data?: string;
    /** The height of the flair */
    height?: number;
    /** The kind of sprite */
    kind?: definitions["model.CosmeticPaintFlairKind"];
    /** The width of the flair */
    width?: number;
    /** The X offset of the flair (%) */
    x_offset?: number;
    /** The Y offset of the flair (%) */
    y_offset?: number;
  };
  "model.CosmeticPaintFlairKind": "IMAGE" | "VECTOR" | "TEXT";
  "model.CosmeticPaintFunction": "LINEAR_GRADIENT" | "RADIAL_GRADIENT" | "URL";
  "model.CosmeticPaintGradient": {
    /** The degree angle of the gradient (does not apply if function is URL) */
    angle?: number;
    /** Gradient position (X/Y % values) */
    at?: number[];
    /** The repeat mode of the canvas */
    canvas_repeat?: definitions["model.CosmeticPaintCanvasRepeat"];
    /** The canvas size for the paint */
    canvas_size?: number[];
    /** The function used to generate the paint (i.e gradients or an image) */
    function?: definitions["model.CosmeticPaintFunction"];
    /** For a URL-based paint, the URL to an image */
    image_url?: string;
    /** Whether or not the gradient repeats outside its original area */
    repeat?: boolean;
    /** For a radial gradient, the shape of the gradient */
    shape?: string;
    /**
     * A list of gradients. There may be any amount, which can be stacked onto each other
     * Gradient stops, a list of positions and colors
     */
    stops?: definitions["model.CosmeticPaintGradientStop"][];
  };
  "model.CosmeticPaintGradientStop": {
    at?: number;
    /** the center position for the gradient. X/Y % values (for radial gradients only) */
    center_at?: number[];
    color?: number;
  };
  "model.CosmeticPaintModel": {
    /** use `gradients` */
    angle?: number;
    color?: number;
    flairs?: definitions["model.CosmeticPaintFlair"][];
    /** use `gradients` */
    function?: "LINEAR_GRADIENT" | "RADIAL_GRADIENT" | "URL";
    gradients?: definitions["model.CosmeticPaintGradient"][];
    id?: string;
    /** use `gradients` */
    image_url?: string;
    name?: string;
    /** use `gradients` */
    repeat?: boolean;
    /** A list of shadows. There may be any amount, which can be stacked onto each other */
    shadows?: definitions["model.CosmeticPaintShadow"][];
    /** use `gradients` */
    shape?: string;
    /** use `gradients` */
    stops?: definitions["model.CosmeticPaintGradientStop"][];
    text?: definitions["model.CosmeticPaintText"];
  };
  "model.CosmeticPaintShadow": {
    color?: number;
    radius?: number;
    x_offset?: number;
    y_offset?: number;
  };
  "model.CosmeticPaintStroke": {
    /** Stroke color */
    color?: number;
    /** Stroke width */
    width?: number;
  };
  "model.CosmeticPaintText": {
    /** Shadows applied to the text */
    shadows?: definitions["model.CosmeticPaintShadow"][];
    /** Text stroke */
    stroke?: definitions["model.CosmeticPaintStroke"];
    /** Text tranformation */
    transform?: definitions["model.CosmeticPaintTextTransform"];
    /** (css) font variant property. non-standard */
    variant?: string;
    /** Weight multiplier for the text. Defaults to 9x is not specified */
    weight?: number;
  };
  "model.CosmeticPaintTextTransform": "uppercase" | "lowercase";
  "model.EmoteFlagsModel": 1 | 2 | 256 | 65536 | 131072 | 262144 | 16777216;
  "model.EmoteLifecycleModel": -1 | 0 | 1 | 2 | 3 | -2;
  "model.EmoteModel": {
    animated?: boolean;
    flags?: definitions["model.EmoteFlagsModel"];
    host?: definitions["model.ImageHost"];
    id?: string;
    lifecycle?: definitions["model.EmoteLifecycleModel"];
    listed?: boolean;
    name?: string;
    owner?: definitions["model.UserPartialModel"];
    state?: definitions["model.EmoteVersionState"][];
    tags?: string[];
    versions?: definitions["model.EmoteVersionModel"][];
  };
  "model.EmotePartialModel": {
    animated?: boolean;
    flags?: definitions["model.EmoteFlagsModel"];
    host?: definitions["model.ImageHost"];
    id?: string;
    lifecycle?: definitions["model.EmoteLifecycleModel"];
    listed?: boolean;
    name?: string;
    owner?: definitions["model.UserPartialModel"];
    state?: definitions["model.EmoteVersionState"][];
    tags?: string[];
  };
  "model.EmoteSetFlagModel": 1 | 2 | 4 | 8;
  "model.EmoteSetModel": {
    capacity?: number;
    emote_count?: number;
    emotes?: definitions["model.ActiveEmoteModel"][];
    flags?: definitions["model.EmoteSetFlagModel"];
    id?: string;
    immutable?: boolean;
    name?: string;
    origins?: definitions["model.EmoteSetOrigin"][];
    owner?: definitions["model.UserPartialModel"];
    privileged?: boolean;
    tags?: string[];
  };
  "model.EmoteSetOrigin": {
    id?: string;
    slices?: number[];
    weight?: number;
  };
  "model.EmoteSetPartialModel": {
    capacity?: number;
    flags?: definitions["model.EmoteSetFlagModel"];
    id?: string;
    name?: string;
    owner?: definitions["model.UserPartialModel"];
    tags?: string[];
  };
  "model.EmoteVersionModel": {
    animated?: boolean;
    createdAt?: number;
    description?: string;
    host?: definitions["model.ImageHost"];
    id?: string;
    lifecycle?: definitions["model.EmoteLifecycleModel"];
    listed?: boolean;
    name?: string;
    state?: definitions["model.EmoteVersionState"][];
  };
  "model.EmoteVersionState": "LISTED" | "PERSONAL" | "NO_PERSONAL";
  "model.ImageFile": {
    format?: definitions["model.ImageFormat"];
    frame_count?: number;
    height?: number;
    name?: string;
    size?: number;
    /** deprecated */
    static_name?: string;
    width?: number;
  };
  "model.ImageFormat": "AVIF" | "WEBP";
  "model.ImageHost": {
    files?: definitions["model.ImageFile"][];
    url?: string;
  };
  "model.PresenceKind": 0 | 1 | 2;
  "model.PresenceModel": {
    id?: string;
    kind?: definitions["model.PresenceKind"];
    timestamp?: number;
    ttl?: number;
    user_id?: string;
  };
  "model.UserConnectionModel": {
    /** The display name of the user on the platform. */
    display_name?: string;
    /** The maximum size of emote sets that may be bound to this connection. */
    emote_capacity?: number;
    /** The emote set that is linked to this connection */
    emote_set?: definitions["model.EmoteSetModel"];
    /** The ID of the emote set bound to this connection. */
    emote_set_id?: string;
    id?: string;
    /** The time when the user linked this connection */
    linked_at?: number;
    /** The service of the connection. */
    platform?: "TWITCH" | "YOUTUBE" | "DISCORD";
    /** A list of users active in the channel */
    presences?: definitions["model.UserPartialModel"][];
    /** App data for the user */
    user?: definitions["model.UserModel"];
    /** The username of the user on the platform. */
    username?: string;
  };
  "model.UserConnectionPartialModel": {
    /** The display name of the user on the platform. */
    display_name?: string;
    /** The maximum size of emote sets that may be bound to this connection. */
    emote_capacity?: number;
    /** The emote set that is linked to this connection */
    emote_set_id?: string;
    id?: string;
    /** The time when the user linked this connection */
    linked_at?: number;
    /** The service of the connection. */
    platform?: "TWITCH" | "YOUTUBE" | "DISCORD";
    /** The username of the user on the platform. */
    username?: string;
  };
  "model.UserEditorModel": {
    added_at?: number;
    id?: string;
    permissions?: number;
    visible?: boolean;
  };
  "model.UserModel": {
    avatar_url?: string;
    biography?: string;
    connections?: definitions["model.UserConnectionModel"][];
    created_at?: number;
    display_name?: string;
    editors?: definitions["model.UserEditorModel"][];
    emote_sets?: definitions["model.EmoteSetPartialModel"][];
    id?: string;
    roles?: string[];
    style?: definitions["model.UserStyle"];
    type?: "" | "BOT" | "SYSTEM";
    username?: string;
  };
  "model.UserPartialModel": {
    avatar_url?: string;
    connections?: definitions["model.UserConnectionPartialModel"][];
    display_name?: string;
    id?: string;
    roles?: string[];
    style?: definitions["model.UserStyle"];
    type?: "" | "BOT" | "SYSTEM";
    username?: string;
  };
  "model.UserStyle": {
    badge?: definitions["model.CosmeticBadgeModel"];
    badge_id?: string;
    color?: number;
    paint?: definitions["model.CosmeticPaintModel"];
    paint_id?: string;
  };
}

export interface operations {}
Details

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions