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

TypeScript support for the admin api client #446

Open
dsebastien opened this issue Sep 22, 2022 · 6 comments
Open

TypeScript support for the admin api client #446

dsebastien opened this issue Sep 22, 2022 · 6 comments
Labels
Hacktoberfest Issues suitable for hacktoberfest participants

Comments

@dsebastien
Copy link

dsebastien commented Sep 22, 2022

I saw that there are community-provided types for the content API, but couldn't find the equivalent for the admin API.

It would be great if TypeScript types could be provided for the Admin API client. More and more apps are being developed using TypeScript, as it makes for a much nicer developer experience. Is this something already on the product roadmap?

@ErisDS
Copy link
Member

ErisDS commented Sep 22, 2022

These typings are provided by the community over on the DefinitelyTyped repo, but I'm not aware of anyone actively working on them for admin.

@dsebastien
Copy link
Author

I've just created my own. I'll try to make those available on DefinitelyTyped if I get the time.

Here they are, just I case I don't and someone else cares enough. It's very rough, but it's a start:

declare module "@tryghost/admin-api" {
  import type {AxiosResponse} from "axios";

  export interface GhostAdminAPIOptions {
    /**
     * URL of the Ghost instance
     */
    url: string;
    ghostPath?: string;
    /**
     * The Admin API key
     */
    key: string;
    /**
     * A version string like v3.2, v4.1, v5.8 or boolean value identifying presence of Accept-Version header
     */
    version: string;
    /**
     * Flag controlling if the 'User-Agent' header should be sent with a request
     */
    userAgent?: string | boolean;
    /**
     * Customize the Accept-Version header sent with requests
     */
    acceptVersionHeader?: string;
    /**
     * Replace the function used to send HTTP requests
     */
    makeRequest?: (options: GhostAdminApiMakeRequestOptions) => Promise<unknown>; // TODO refine
    /**
     * Replace the function used to generate tokens
     * @param key the key
     * @param audience the audience of the token
     */
    generateToken?: (key: string, audience: string) => string;
  }

  export interface GhostAdminApiMakeRequestOptions {
    url: string;
    method: string;
    data: unknown;
    params: Record<unknown>;
    headers: Record<unknown>
  }

  export interface GhostAdminApiMediaUploadData {
    /**
     * File path to a media file
     **/
    file: string;
    /**
     * File path to a thumbnail file
     */
    thumbnail?: string;
    /**
     * Purpose of the file
     */
    purpose?: string;
  }

  export type GhostAdminApiImageUploadData = GhostAdminApiMediaUploadData;

  export interface GhostAdminApiFileUploadData {
    /**
     * File path to a file
     **/
    file: string;
    /**
     * Reference field returned in the response
     */
    ref?: string;
  }

  // export interface GhostAdminApiInstance {
  //
  // }

  declare class GhostAdminAPI implements GhostAdminApiInstance {
    constructor(options: GhostAdminAPIOptions);

    posts: {
      read: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      browse: (options: Record<unknown>) => Promise<AxiosResponse<unknown>>;
      add: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      edit: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      del: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
    };

    pages: {
      read: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      browse: (options: Record<unknown>) => Promise<AxiosResponse<unknown>>;
      add: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      edit: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      del: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
    };

    tags: {
      read: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      browse: (options: Record<unknown>) => Promise<AxiosResponse<unknown>>;
      add: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      edit: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      del: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
    };

    members: {
      read: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      browse: (options: Record<unknown>) => Promise<AxiosResponse<unknown>>;
      add: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      edit: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      del: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
    };

    users: {
      read: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      browse: (options: Record<unknown>) => Promise<AxiosResponse<unknown>>;
      add: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      edit: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      del: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
    };

    newsletters: {
      read: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      browse: (options: Record<unknown>) => Promise<AxiosResponse<unknown>>;
      add: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      edit: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      del: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
    };

    webhooks: {
      add: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      edit: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
      del: (data: Record<unknown>, queryParams: Record<unknown> = {}) => Promise<AxiosResponse<unknown>>;
    };

    images: {
      upload: (data: GhostAdminApiImageUploadData | FormData) => Promise<AxiosResponse<unknown>>;
    }

    media: {
      upload: (data: GhostAdminApiMediaUploadData | FormData) => Promise<AxiosResponse<unknown>>;
    }

    files: {
      upload: (data: GhostAdminApiFileUploadData | FormData) => Promise<AxiosResponse<unknown>>;
    }

    config: {
      read: () => Promise<AxiosResponse<unknown>>;
    }

    site: {
      read: () => Promise<AxiosResponse<unknown>>;
    }

    themes: {
      upload: (data) => Promise<AxiosResponse<unknown>>;
      activate: (name: string) => Promise<AxiosResponse<unknown>>;
    }
  }

  export = GhostAdminAPI;
}

@ErisDS ErisDS added the Hacktoberfest Issues suitable for hacktoberfest participants label Sep 27, 2022
@newTomas
Copy link

newTomas commented Jan 4, 2023

Code generated by chat gpt. Needs review:

declare module "@tryghost/admin-api" {
  export interface ClientOptions {
    url: string;
    key: string;
    version?: string;
  }

  export interface Page {
    id: string;
    title: string;
    slug: string;
    html: string;
    markdown: string;
    feature_image: string;
    featured: boolean;
    page: boolean;
    status: string;
    language: string;
    visibility: string;
    meta_title: string;
    meta_description: string;
    author_id: string;
    created_at: string;
    created_by: string;
    updated_at: string;
    updated_by: string;
    published_at: string;
    published_by: string;
  }

  export interface Post {
    id: string;
    title: string;
    slug: string;
    html: string;
    markdown: string;
    feature_image: string;
    featured: boolean;
    page: boolean;
    status: string;
    language: string;
    visibility: string;
    meta_title: string;
    meta_description: string;
    author_id: string;
    created_at: string;
    created_by: string;
    updated_at: string;
    updated_by: string;
    published_at: string;
    published_by: string;
  }

  export interface Member {
    id: string;
    name: string;
    email: string;
    status: string;
    note: string;
  }

  export interface Tag {
    id: string;
    name: string;
    slug: string;
    description: string;
    feature_image: string;
    visibility: string;
    created_at: string;
    created_by: string;
    updated_at: string;
    updated_by: string;
  }

  export interface Webhook {
    id: string;
    event: string;
    target_url: string;
    created_at: string;
    created_by: string;
    updated_at: string;
    updated_by: string;
  }

  export interface User {
    id: string;
    name: string;
    slug: string;
    profile_image: string;
    cover_image: string;
    bio: string;
    website: string;
    location: string;
    status: string;
    visibility: string;
    meta_title: string;
    meta_description: string;
    last_login: string;
    created_at: string;
    created_by: string;
    updated_at: string;
    updated_by: string;
  }

  export interface Newsletter {
    id: string;
    name: string;
    slug: string;
    status: string;
    created_at: string;
    created_by: string;
    updated_at: string;
    updated_by: string;
  }

  export interface Image {
    id: string;
    title: string;
    slug: string;
    type: string;
    created_at: string;
    created_by: string;
    updated_at: string;
    updated_by: string;
    published_at: string;
    published_by: string;
  }

  export interface Media {
    id: string;
    title: string;
    slug: string;
    type: string;
    created_at: string;
    created_by: string;
    updated_at: string;
    updated_by: string;
    published_at: string;
    published_by: string;
  }

  export interface File {
    id: string;
    title: string;
    slug: string;
    type: string;
    created_at: string;
    created_by: string;
    updated_at: string;
    updated_by: string;
    published_at: string;
    published_by: string;
  }

  export interface Config {
    id: string;
    key: string;
    value: string;
    created_at: string;
    created_by: string;
    updated_at: string;
    updated_by: string;
  }

  export interface Site {
    id: string;
    name: string;
    description: string;
    logo: string;
    icon: string;
    cover_image: string;
    facebook: string;
    twitter: string;
    lang: string;
    timezone: string;
    navigation: string[];
    created_at: string;
    created_by: string;
    updated_at: string;
    updated_by: string;
  }

  export interface Theme {
    id: string;
    name: string;
    package: {
      name: string;
      version: string;
    };
    active: boolean;
    created_at: string;
    created_by: string;
    updated_at: string;
    updated_by: string;
  }

  export default class Client {
    constructor(options: ClientOptions);

    pages: {
      browse(options?: object): Promise<Page[]>;
      read(options: { id: string }): Promise<Page>;
      edit(options: { id: string; data: Page }): Promise<Page>;
      add(options: Partial<Page>): Promise<Page>;
      delete(options: { id: string }): Promise<void>;
    };

    posts: {
      browse(options?: object): Promise<Post[]>;
      read(options: { id: string }): Promise<Post>;
      edit(options: { id: string; data: Post }): Promise<Post>;
      add(options: Partial<Post>): Promise<Post>;
      delete(options: { id: string }): Promise<void>;
    };

    members: {
      browse(options?: object): Promise<Member[]>;
      read(options: { id: string }): Promise<Member>;
      edit(options: { id: string; data: Member }): Promise<Member>;
      add(options: Partial<Member>): Promise<Member>;
      delete(options: { id: string }): Promise<void>;
    };

    tags: {
      browse(options?: object): Promise<Tag[]>;
      read(options: { id: string }): Promise<Tag>;
      edit(options: { id: string; data: Tag }): Promise<Tag>;
      add(options: Partial<Tag>): Promise<Tag>;
      delete(options: { id: string }): Promise<void>;
    };

    webhooks: {
      browse(options?: object): Promise<Webhook[]>;
      read(options: { id: string }): Promise<Webhook>;
      edit(options: { id: string; data: Webhook }): Promise<Webhook>;
      add(options: Partial<Webhook>): Promise<Webhook>;
      delete(options: { id: string }): Promise<void>;
    };

    users: {
      browse(options?: object): Promise<User[]>;
      read(options: { id: string }): Promise<User>;
      edit(options: { id: string; data: User }): Promise<User>;
      add(options: Partial<User>): Promise<User>;
      delete(options: { id: string }): Promise<void>;
    };

    newsletters: {
      browse(options?: object): Promise<Newsletter[]>;
      read(options: { id: string }): Promise<Newsletter>;
      edit(options: { id: string; data: Newsletter }): Promise<Newsletter>;
      add(options: Partial<Newsletter>): Promise<Newsletter>;
      delete(options: { id: string }): Promise<void>;
    };

    images: {
      upload(options: { file: any }): Promise<Image>;
    };

    media: {
      upload(options: { file: any }): Promise<Media>;
    };

    files: {
      upload(options: { file: any }): Promise<File>;
    };

    config: {
      read(options: { id: string }): Promise<Config>;
    };

    site: {
      read(options: { id: string }): Promise<Site>;
    };

    themes: {
      upload(options: { file: any }): Promise<Theme>;
      activate(options: { id: string }): Promise<Theme>;
    };
  }
}

@maccman
Copy link

maccman commented Aug 18, 2023

It's honestly a bit embarrassing that this lib doesn't have typescript support. Is it maintained?

@ivosabev
Copy link

ivosabev commented Oct 6, 2023

Would love to have TypeScript definitions for the Admin API. JSDoc is not a bad way to do it.

@philkunz
Copy link

philkunz commented May 29, 2024

How is non-TypeScript for npm still a thing in 2024?

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

No branches or pull requests

6 participants