Use type instead of interface for entities

This commit is contained in:
AkiraFukushima 2019-05-30 23:16:11 +09:00
parent e954bcc35c
commit 60dd098c89
33 changed files with 172 additions and 153 deletions

View file

@ -0,0 +1,7 @@
import Mastodon, { Instance } from 'megalodon'
const BASE_URL: string = 'http://mstdn.jp'
Mastodon.get<Instance>('/api/v1/instance', {}, BASE_URL).then(res => {
console.log(res)
})

View file

@ -1,7 +1,7 @@
import Emoji from './emoji'
import Source from './source'
import { Emoji } from './emoji'
import { Source } from './source'
export default interface Account {
export type Account = {
id: string
username: string
acct: string

View file

@ -1,4 +1,4 @@
export default interface Application {
export type Application = {
name: string
website: string | null
}

View file

@ -1,4 +1,4 @@
export default interface Attachment {
export type Attachment = {
id: string
type: 'unknown' | 'image' | 'gifv' | 'video'
url: string

View file

@ -1,4 +1,4 @@
export default interface Card {
export type Card = {
url: string
title: string
description: string

View file

@ -1,6 +1,6 @@
import Status from './status'
import { Status } from './status'
export default interface Context {
export type Context = {
ancestors: Array<Status>
descendants: Array<Status>
}

View file

@ -1,7 +1,7 @@
import Account from './account'
import Status from './status'
import { Account } from './account'
import { Status } from './status'
export default interface Conversation {
export type Conversation = {
id: string
accounts: Array<Account>
last_status: Status | null

View file

@ -1,4 +1,4 @@
export default interface Emoji {
export type Emoji = {
shortcode: string
static_url: string
url: string

View file

@ -1,4 +1,4 @@
export default interface Field {
export type Field = {
name: string
value: string
verified_at: string | null

View file

@ -1,4 +1,4 @@
export default interface Filter {
export type Filter = {
id: string
phrase: string
context: Array<string>

View file

@ -1,4 +1,4 @@
export default interface History {
export type History = {
day: string
uses: number
accounts: number

View file

@ -1,8 +1,8 @@
import Account from './account'
import URLs from './urls'
import Stats from './stats'
import { Account } from './account'
import { URLs } from './urls'
import { Stats } from './stats'
export default interface Instance {
export type Instance = {
uri: string
title: string
description: string

View file

@ -1,4 +1,4 @@
export default interface List {
export type List = {
id: string
title: string
}

View file

@ -1,4 +1,4 @@
export default interface Mention {
export type Mention = {
id: string
username: string
url: string

View file

@ -1,7 +1,7 @@
import Account from './account'
import Status from './status'
import { Account } from './account'
import { Status } from './status'
export default interface Notification {
export type Notification = {
account: Account
created_at: string
id: string

View file

@ -1,4 +1,4 @@
export default interface PushSubscription {
export type PushSubscription = {
id: string
endpoint: string
server_key: string

View file

@ -1,4 +1,4 @@
export default interface Relationship {
export type Relationship = {
id: string
following: boolean
followed_by: boolean

View file

@ -1,8 +1,8 @@
import Account from './account'
import Status from './status'
import Tag from './tag'
import { Account } from './account'
import { Status } from './status'
import { Tag } from './tag'
export default interface Results {
export type Results = {
accounts: Array<Account>
statuses: Array<Status>
hashtags: Array<Tag>

View file

@ -1,6 +1,6 @@
import Attachment from './attachment'
import { Attachment } from './attachment'
export default interface ScheduledStatus {
export type ScheduledStatus = {
id: string
scheduled_at: string
params: object

View file

@ -1,4 +1,4 @@
export default interface Source {
export type Source = {
privacy: string | null
sensitive: boolean | null
language: string | null

View file

@ -1,4 +1,4 @@
export default interface Stats {
export type Stats = {
user_count: number
status_count: number
domain_count: number

View file

@ -1,12 +1,12 @@
import Account from './account'
import Application from './application'
import Mention from './mention'
import Tag from './tag'
import Attachment from './attachment'
import Emoji from './emoji'
import Card from './card'
import { Account } from './account'
import { Application } from './application'
import { Mention } from './mention'
import { Tag } from './tag'
import { Attachment } from './attachment'
import { Emoji } from './emoji'
import { Card } from './card'
export default interface Status {
export type Status = {
id: string
uri: string
url: string

View file

@ -1,4 +1,4 @@
export default interface StatusParams {
export type StatusParams = {
text: string
in_reply_to_id: string | null
media_ids: Array<string> | null

View file

@ -1,6 +1,6 @@
import History from './history'
import { History } from './history'
export default interface Tag {
export type Tag = {
name: string
url: string
history: Array<History> | null

View file

@ -1,4 +1,4 @@
export default interface Token {
export type Token = {
access_token: string
token_type: string
scope: string

View file

@ -1,3 +1,3 @@
export default interface URLs {
export type URLs = {
streaming_api: string
}

View file

@ -6,31 +6,31 @@ import OAuth from './oauth'
/**
* Entities
*/
import Account from './entities/account'
import Application from './entities/application'
import Attachment from './entities/attachment'
import Card from './entities/card'
import Context from './entities/context'
import Conversation from './entities/conversation'
import Emoji from './entities/emoji'
import Field from './entities/field'
import Filter from './entities/filter'
import History from './entities/history'
import Instance from './entities/instance'
import List from './entities/list'
import Mention from './entities/mention'
import Notification from './entities/notification'
import PushSubscription from './entities/push_subscription'
import Relationship from './entities/relationship'
import Results from './entities/results'
import ScheduledStatus from './entities/scheduled_status'
import Source from './entities/source'
import Stats from './entities/stats'
import Status from './entities/status'
import StatusParams from './entities/status_params'
import Tag from './entities/tag'
import Token from './entities/token'
import URLs from './entities/urls'
import { Account } from './entities/account'
import { Application } from './entities/application'
import { Attachment } from './entities/attachment'
import { Card } from './entities/card'
import { Context } from './entities/context'
import { Conversation } from './entities/conversation'
import { Emoji } from './entities/emoji'
import { Field } from './entities/field'
import { Filter } from './entities/filter'
import { History } from './entities/history'
import { Instance } from './entities/instance'
import { List } from './entities/list'
import { Mention } from './entities/mention'
import { Notification } from './entities/notification'
import { PushSubscription } from './entities/push_subscription'
import { Relationship } from './entities/relationship'
import { Results } from './entities/results'
import { ScheduledStatus } from './entities/scheduled_status'
import { Source } from './entities/source'
import { Stats } from './entities/stats'
import { Status } from './entities/status'
import { StatusParams } from './entities/status_params'
import { Tag } from './entities/tag'
import { Token } from './entities/token'
import { URLs } from './entities/urls'
export {
StreamListener,

View file

@ -52,25 +52,28 @@ export default class Mastodon implements MegalodonInstance {
* @param options Form Data, which is sent to /api/v1/apps. and properties should be **snake_case**
* @param baseUrl base URL of the target
*/
public static registerApp(
public static async registerApp(
client_name: string,
options: Partial<{ scopes: string, redirect_uris: string, website: string }> = {
options: Partial<{ scopes: string; redirect_uris: string; website: string }> = {
scopes: DEFAULT_SCOPE,
redirect_uris: NO_REDIRECT
},
baseUrl = DEFAULT_URL
): Promise<OAuth.AppData> {
return this.createApp(client_name, options, baseUrl)
.then(appData => {
return this.generateAuthUrl(appData.client_id, appData.client_secret, {
return this.createApp(client_name, options, baseUrl).then(async appData => {
return this.generateAuthUrl(
appData.client_id,
appData.client_secret,
{
redirect_uri: appData.redirect_uri,
scope: options.scopes
}, baseUrl)
.then(url => {
appData.url = url
return appData
})
},
baseUrl
).then(url => {
appData.url = url
return appData
})
})
}
/**
@ -81,9 +84,9 @@ export default class Mastodon implements MegalodonInstance {
* @param options Form Data
* @param baseUrl target of base URL
*/
public static createApp(
public static async createApp(
client_name: string,
options: Partial<{ redirect_uris: string, scopes: string, website: string }> = {
options: Partial<{ redirect_uris: string; scopes: string; website: string }> = {
redirect_uris: NO_REDIRECT,
scopes: DEFAULT_SCOPE
},
@ -93,9 +96,9 @@ export default class Mastodon implements MegalodonInstance {
const scopes = options.scopes || DEFAULT_SCOPE
const params: {
client_name: string,
redirect_uris: string,
scopes: string,
client_name: string
redirect_uris: string
scopes: string
website?: string
} = {
client_name,
@ -104,8 +107,9 @@ export default class Mastodon implements MegalodonInstance {
}
if (options.website) params.website = options.website
return this._post<OAuth.AppDataFromServer>('/api/v1/apps', params, baseUrl)
.then((res: Response<OAuth.AppDataFromServer>) => OAuth.AppData.from(res.data))
return this._post<OAuth.AppDataFromServer>('/api/v1/apps', params, baseUrl).then((res: Response<OAuth.AppDataFromServer>) =>
OAuth.AppData.from(res.data)
)
}
/**
@ -119,13 +123,13 @@ export default class Mastodon implements MegalodonInstance {
public static generateAuthUrl(
clientId: string,
clientSecret: string,
options: Partial<{ redirect_uri: string, scope: string }> = {
options: Partial<{ redirect_uri: string; scope: string }> = {
redirect_uri: NO_REDIRECT,
scope: DEFAULT_SCOPE
},
baseUrl = DEFAULT_URL
): Promise<string> {
return new Promise((resolve) => {
return new Promise(resolve => {
const oauth = new OAuth2(clientId, clientSecret, baseUrl, undefined, '/oauth/token')
const url = oauth.getAuthorizeUrl({
redirect_uri: options.redirect_uri,
@ -147,20 +151,24 @@ export default class Mastodon implements MegalodonInstance {
* @param baseUrl base URL of the target
* @param redirect_uri must be the same uri as the time when you register your OAuth application
*/
public static fetchAccessToken(
public static async fetchAccessToken(
client_id: string,
client_secret: string,
code: string,
baseUrl = DEFAULT_URL,
redirect_uri = NO_REDIRECT
): Promise<OAuth.TokenData> {
return this._post<OAuth.TokenDataFromServer>('/oauth/token', {
client_id,
client_secret,
code,
redirect_uri,
grant_type: 'authorization_code'
}, baseUrl).then((res: Response<OAuth.TokenDataFromServer>) => OAuth.TokenData.from(res.data))
return this._post<OAuth.TokenDataFromServer>(
'/oauth/token',
{
client_id,
client_secret,
code,
redirect_uri,
grant_type: 'authorization_code'
},
baseUrl
).then((res: Response<OAuth.TokenDataFromServer>) => OAuth.TokenData.from(res.data))
}
/**
@ -172,18 +180,22 @@ export default class Mastodon implements MegalodonInstance {
* @param refresh_token will be get #fetchAccessToken
* @param baseUrl base URL or the target
*/
public static refreshToken(
public static async refreshToken(
client_id: string,
client_secret: string,
refresh_token: string,
baseUrl = DEFAULT_URL
): Promise<OAuth.TokenData> {
return this._post<OAuth.TokenDataFromServer>('/oauth/token', {
client_id,
client_secret,
refresh_token,
grant_type: 'refresh_token'
}, baseUrl).then((res: Response<OAuth.TokenDataFromServer>) => OAuth.TokenData.from(res.data))
return this._post<OAuth.TokenDataFromServer>(
'/oauth/token',
{
client_id,
client_secret,
refresh_token,
grant_type: 'refresh_token'
},
baseUrl
).then((res: Response<OAuth.TokenDataFromServer>) => OAuth.TokenData.from(res.data))
}
/**
@ -192,7 +204,7 @@ export default class Mastodon implements MegalodonInstance {
* @param params Query parameters
* @param baseUrl base URL of the target
*/
public static get<T>(path: string, params = {}, baseUrl = DEFAULT_URL): Promise<Response<T>> {
public static async get<T>(path: string, params = {}, baseUrl = DEFAULT_URL): Promise<Response<T>> {
const apiUrl = baseUrl
return axios
.get<T>(apiUrl + path, {
@ -209,19 +221,17 @@ export default class Mastodon implements MegalodonInstance {
})
}
private static _post<T>(path: string, params = {}, baseUrl = DEFAULT_URL): Promise<Response<T>> {
private static async _post<T>(path: string, params = {}, baseUrl = DEFAULT_URL): Promise<Response<T>> {
const apiUrl = baseUrl
return axios
.post<T>(apiUrl + path, params)
.then((resp: AxiosResponse<T>) => {
const res: Response<T> = {
data: resp.data,
status: resp.status,
statusText: resp.statusText,
headers: resp.headers
}
return res
})
return axios.post<T>(apiUrl + path, params).then((resp: AxiosResponse<T>) => {
const res: Response<T> = {
data: resp.data,
status: resp.status,
statusText: resp.statusText,
headers: resp.headers
}
return res
})
}
/**
@ -229,11 +239,11 @@ export default class Mastodon implements MegalodonInstance {
* @param path relative path from baseUrl
* @param params Query parameters
*/
public get<T>(path: string, params = {}): Promise<Response<T>> {
public async get<T>(path: string, params = {}): Promise<Response<T>> {
return axios
.get<T>(this.baseUrl + path, {
headers: {
'Authorization': `Bearer ${this.accessToken}`
Authorization: `Bearer ${this.accessToken}`
},
params
})
@ -253,11 +263,11 @@ export default class Mastodon implements MegalodonInstance {
* @param path relative path from baseUrl
* @param params Form data. If you want to post file, please use FormData()
*/
public put<T>(path: string, params = {}): Promise<Response<T>> {
public async put<T>(path: string, params = {}): Promise<Response<T>> {
return axios
.put<T>(this.baseUrl + path, params, {
headers: {
'Authorization': `Bearer ${this.accessToken}`
Authorization: `Bearer ${this.accessToken}`
}
})
.then((resp: AxiosResponse<T>) => {
@ -276,11 +286,11 @@ export default class Mastodon implements MegalodonInstance {
* @param path relative path from baseUrl
* @param params Form data. If you want to post file, please use FormData()
*/
public patch<T>(path: string, params = {}): Promise<Response<T>> {
public async patch<T>(path: string, params = {}): Promise<Response<T>> {
return axios
.patch<T>(this.baseUrl + path, params, {
headers: {
'Authorization': `Bearer ${this.accessToken}`
Authorization: `Bearer ${this.accessToken}`
}
})
.then((resp: AxiosResponse<T>) => {
@ -299,11 +309,11 @@ export default class Mastodon implements MegalodonInstance {
* @param path relative path from baseUrl
* @param params Form data
*/
public post<T>(path: string, params = {}): Promise<Response<T>> {
public async post<T>(path: string, params = {}): Promise<Response<T>> {
return axios
.post<T>(this.baseUrl + path, params, {
headers: {
'Authorization': `Bearer ${this.accessToken}`
Authorization: `Bearer ${this.accessToken}`
}
})
.then((resp: AxiosResponse<T>) => {
@ -322,12 +332,12 @@ export default class Mastodon implements MegalodonInstance {
* @param path relative path from baseUrl
* @param params Form data
*/
public del<T>(path: string, params = {}): Promise<Response<T>> {
public async del<T>(path: string, params = {}): Promise<Response<T>> {
return axios
.delete(this.baseUrl + path, {
data: params,
headers: {
'Authorization': `Bearer ${this.accessToken}`
Authorization: `Bearer ${this.accessToken}`
}
})
.then((resp: AxiosResponse) => {
@ -352,8 +362,8 @@ export default class Mastodon implements MegalodonInstance {
public stream(path: string, reconnectInterval = 1000): StreamListener {
const headers = {
'Cache-Control': 'no-cache',
'Accept': 'text/event-stream',
'Authorization': `Bearer ${this.accessToken}`
Accept: 'text/event-stream',
Authorization: `Bearer ${this.accessToken}`
}
const url = this.baseUrl + path
const streaming = new StreamListener(url, headers, reconnectInterval)

View file

@ -3,21 +3,21 @@
* Response data when oauth request.
**/
namespace OAuth {
export interface AppDataFromServer {
id: number,
name: string,
website: string | null,
redirect_uri: string,
client_id: string,
export type AppDataFromServer = {
id: number
name: string
website: string | null
redirect_uri: string
client_id: string
client_secret: string
}
export interface TokenDataFromServer {
access_token: string,
token_type: string,
scope: string,
created_at: number,
expires_in: number | null,
export type TokenDataFromServer = {
access_token: string
token_type: string
scope: string
created_at: number
expires_in: number | null
refresh_token: string | null
}

View file

@ -1,7 +1,7 @@
import { EventEmitter } from 'events'
import Status from './entities/status'
import Notification from './entities/notification'
import Conversation from './entities/conversation'
import { Status } from './entities/status'
import { Notification } from './entities/notification'
import { Conversation } from './entities/conversation'
/**
* Parser

View file

@ -1,6 +1,8 @@
export default interface Response<T = any> {
type Response<T = any> = {
data: T
status: number
statusText: string
headers: any
}
export default Response

View file

@ -1,9 +1,9 @@
import Request from 'request'
import { EventEmitter } from 'events'
import Parser from './parser'
import Status from './entities/status'
import Notification from './entities/notification'
import Conversation from './entities/conversation'
import { Status } from './entities/status'
import { Notification } from './entities/notification'
import { Conversation } from './entities/conversation'
const STATUS_CODES_TO_ABORT_ON: Array<number> = [400, 401, 403, 404, 406, 410, 422]

View file

@ -1,8 +1,8 @@
import { client, connection, IMessage } from 'websocket'
import { EventEmitter } from 'events'
import Status from './entities/status'
import Notification from './entities/notification'
import Conversation from './entities/conversation'
import { Status } from './entities/status'
import { Notification } from './entities/notification'
import { Conversation } from './entities/conversation'
/**
* WebSocket