diff --git a/src/client/docs/api/endpoints/view.pug b/src/client/docs/api/endpoints/view.pug index 24fff1b798..e046b3fc33 100644 --- a/src/client/docs/api/endpoints/view.pug +++ b/src/client/docs/api/endpoints/view.pug @@ -30,3 +30,9 @@ block main section h2= i18n('docs.api.endpoints.res') +propTable(res) + + if resDefs + each resDef in resDefs + section(id= resDef.name) + h3= resDef.name + +propTable(resDef.props) diff --git a/src/client/docs/api/entities/user.yaml b/src/client/docs/api/entities/user.yaml index cccf42f221..3328734d2b 100644 --- a/src/client/docs/api/entities/user.yaml +++ b/src/client/docs/api/entities/user.yaml @@ -5,169 +5,173 @@ desc: en: "A user." props: - - name: "id" + id: type: "id" optional: false desc: ja: "ユーザーID" en: "The ID of this user" - - name: "createdAt" + + createdAt: type: "date" optional: false desc: ja: "アカウント作成日時" en: "The registered date of this user" - - name: "username" + + username: type: "string" optional: false desc: ja: "ユーザー名" en: "The username of this user" - - name: "description" + + description: type: "string" optional: false desc: ja: "アカウントの説明(自己紹介)" en: "The description of this user" - - name: "avatarId" + + avatarId: type: "id(DriveFile)" optional: true desc: ja: "アバターのID" en: "The ID of the avatar of this user" - - name: "avatarUrl" + + avatarUrl: type: "string" optional: false desc: ja: "アバターのURL" en: "The URL of the avatar of this user" - - name: "bannerId" + + bannerId: type: "id(DriveFile)" optional: true desc: ja: "バナーのID" en: "The ID of the banner of this user" - - name: "bannerUrl" + + bannerUrl: type: "string" optional: false desc: ja: "バナーのURL" en: "The URL of the banner of this user" - - name: "followersCount" + + followersCount: type: "number" optional: false desc: ja: "フォロワーの数" en: "The number of the followers for this user" - - name: "followingCount" + + followingCount: type: "number" optional: false desc: ja: "フォローしているユーザーの数" en: "The number of the following users for this user" - - name: "isFollowing" + + isFollowing: type: "boolean" optional: true desc: ja: "自分がこのユーザーをフォローしているか" - - name: "isFollowed" + + isFollowed: type: "boolean" optional: true desc: ja: "自分がこのユーザーにフォローされているか" - - name: "isMuted" + + isMuted: type: "boolean" optional: true desc: ja: "自分がこのユーザーをミュートしているか" en: "Whether you muted this user" - - name: "notesCount" + + notesCount: type: "number" optional: false desc: ja: "投稿の数" en: "The number of the notes of this user" - - name: "pinnedNote" + + pinnedNote: type: "entity(Note)" optional: true desc: ja: "ピン留めされた投稿" en: "The pinned note of this user" - - name: "pinnedNoteId" + + pinnedNoteId: type: "id(Note)" optional: true desc: ja: "ピン留めされた投稿のID" en: "The ID of the pinned note of this user" - - name: "driveCapacity" + + driveCapacity: type: "number" optional: false desc: ja: "ドライブの容量(bytes)" en: "The capacity of drive of this user (bytes)" - - name: "host" + + host: type: "string | null" optional: false desc: ja: "ホスト (例: example.com:3000)" en: "Host (e.g. example.com:3000)" - - name: "account" + + twitter: + type: "object" + optional: true + desc: + ja: "連携されているTwitterアカウント情報" + en: "The info of the connected twitter account of this user" + props: + userId: + type: "string" + optional: false + desc: + ja: "ユーザーID" + en: "The user ID" + screenName: + type: "string" + optional: false + desc: + ja: "ユーザー名" + en: "The screen name of this user" + + isBot: + type: "boolean" + optional: true + desc: + ja: "botか否か(自己申告であることに留意)" + en: "Whether is bot or not" + + profile: type: "object" optional: false desc: - ja: "このサーバーにおけるアカウント" - en: "The account of this user on this server" - defName: "account" - def: - - name: "lastUsedAt" - type: "date" - optional: false - desc: - ja: "最終利用日時" - en: "The last used date of this user" - - name: "isBot" - type: "boolean" + ja: "プロフィール" + en: "The profile of this user" + props: + location: + type: "string" optional: true desc: - ja: "botか否か(自己申告であることに留意)" - en: "Whether is bot or not" - - name: "twitter" - type: "object" + ja: "場所" + en: "The location of this user" + birthday: + type: "string" optional: true desc: - ja: "連携されているTwitterアカウント情報" - en: "The info of the connected twitter account of this user" - defName: "twitter" - def: - - name: "userId" - type: "string" - optional: false - desc: - ja: "ユーザーID" - en: "The user ID" - - name: "screenName" - type: "string" - optional: false - desc: - ja: "ユーザー名" - en: "The screen name of this user" - - name: "profile" - type: "object" - optional: false - desc: - ja: "プロフィール" - en: "The profile of this user" - defName: "profile" - def: - - name: "location" - type: "string" - optional: true - desc: - ja: "場所" - en: "The location of this user" - - name: "birthday" - type: "string" - optional: true - desc: - ja: "誕生日 (YYYY-MM-DD)" - en: "The birthday of this user (YYYY-MM-DD)" + ja: "誕生日 (YYYY-MM-DD)" + en: "The birthday of this user (YYYY-MM-DD)" diff --git a/src/client/docs/api/entities/view.pug b/src/client/docs/api/entities/view.pug index a930f71eb6..3f50bfd3bd 100644 --- a/src/client/docs/api/entities/view.pug +++ b/src/client/docs/api/entities/view.pug @@ -17,4 +17,4 @@ block main each propDef in propDefs section(id= propDef.name) h3= propDef.name - +propTable(propDef.params) + +propTable(propDef.props) diff --git a/src/client/docs/api/mixins.pug b/src/client/docs/api/mixins.pug index 79665a61e3..9e03abefeb 100644 --- a/src/client/docs/api/mixins.pug +++ b/src/client/docs/api/mixins.pug @@ -22,9 +22,9 @@ mixin propTable(props) a(href=`/docs/${lang}/api/entities/${kebab(prop.entity)}`)= prop.entity | ) else if prop.kind == 'object' - if prop.def + if prop.hasDef | ( - a(href=`#${prop.defName}`)= prop.defName + a(href=`#${prop.name}`)= prop.name | ) else if prop.kind == 'date' | (Date) diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts index 45fc77503e..c2f128527e 100644 --- a/src/server/api/endpoints/notes/create.ts +++ b/src/server/api/endpoints/notes/create.ts @@ -90,7 +90,7 @@ export const meta = { res: { type: 'object', - object: { + props: { createdNote: { type: 'entity(Note)', desc: { diff --git a/src/server/web/docs.ts b/src/server/web/docs.ts index e670709634..ceba14bd27 100644 --- a/src/server/web/docs.ts +++ b/src/server/web/docs.ts @@ -63,66 +63,64 @@ async function genVars(lang: string): Promise<{ [key: string]: any }> { } // WIP type -const parseEPDefParam = (key: string, param: Context) => { +const parseParamDefinition = (key: string, param: Context) => { return Object.assign({ name: key, type: param.getType() }, param.data); }; -const parseParam = (param: any) => { - const id = param.type.match(/^id\((.+?)\)|^id/); - const entity = param.type.match(/^entity\((.+?)\)/); - const isObject = /^object/.test(param.type); - const isDate = /^date/.test(param.type); - const isArray = /\[\]$/.test(param.type); +const parsePropDefinition = (key: string, prop: any) => { + const id = prop.type.match(/^id\((.+?)\)|^id/); + const entity = prop.type.match(/^entity\((.+?)\)/); + const isObject = /^object/.test(prop.type); + const isDate = /^date/.test(prop.type); + const isArray = /\[\]$/.test(prop.type); if (id) { - param.kind = 'id'; - param.type = 'string'; - param.entity = id[1]; + prop.kind = 'id'; + prop.type = 'string'; + prop.entity = id[1]; if (isArray) { - param.type += '[]'; + prop.type += '[]'; } } if (entity) { - param.kind = 'entity'; - param.type = 'object'; - param.entity = entity[1]; + prop.kind = 'entity'; + prop.type = 'object'; + prop.entity = entity[1]; if (isArray) { - param.type += '[]'; + prop.type += '[]'; } } if (isObject) { - param.kind = 'object'; + prop.kind = 'object'; + if (prop.props) { + prop.hasDef = true; + } } if (isDate) { - param.kind = 'date'; - param.type = 'string'; + prop.kind = 'date'; + prop.type = 'string'; if (isArray) { - param.type += '[]'; + prop.type += '[]'; } } - if (param.optional) { - param.type += '?'; + if (prop.optional) { + prop.type += '?'; } - return param; + prop.name = key; + + return prop; }; const sortParams = (params: Array<{name: string}>) => { - params.sort((a, b) => { - if (a.name < b.name) - return -1; - if (a.name > b.name) - return 1; - return 0; - }); return params; }; // WIP type -const extractEPDefs = (params: Context[]) => { +const extractParamDefRef = (params: Context[]) => { let defs: any[] = []; params.forEach(param => { @@ -130,10 +128,10 @@ const extractEPDefs = (params: Context[]) => { const props = (param as ObjectContext).props; defs.push({ name: param.data.ref, - params: sortParams(Object.keys(props).map(k => parseEPDefParam(k, props[k]))) + params: sortParams(Object.keys(props).map(k => parseParamDefinition(k, props[k]))) }); - const childDefs = extractEPDefs(Object.keys(props).map(k => props[k])); + const childDefs = extractParamDefRef(Object.keys(props).map(k => props[k])); defs = defs.concat(childDefs); } @@ -142,17 +140,17 @@ const extractEPDefs = (params: Context[]) => { return sortParams(defs); }; -const extractDefs = (params: any[]) => { +const extractPropDefRef = (props: any[]) => { let defs: any[] = []; - params.forEach(param => { - if (param.def) { + Object.entries(props).forEach(([k, v]) => { + if (v.props) { defs.push({ - name: param.defName, - params: sortParams(param.def.map((p: any) => parseParam(p))) + name: k, + props: sortParams(Object.entries(v.props).map(([k, v]) => parsePropDefinition(k, v))) }); - const childDefs = extractDefs(param.def); + const childDefs = extractPropDefRef(v.props); defs = defs.concat(childDefs); } @@ -184,8 +182,10 @@ router.get('/*/api/endpoints/*', async ctx => { }, desc: ep.desc, // @ts-ignore - params: sortParams(Object.keys(ep.params).map(k => parseEPDefParam(k, ep.params[k]))), - paramDefs: extractEPDefs(Object.keys(ep.params).map(k => ep.params[k])), + params: sortParams(Object.entries(ep.params).map(([k, v]) => parseParamDefinition(k, v))), + paramDefs: extractParamDefRef(Object.entries(ep.params).map(([k, v]) => v)), + res: ep.res.props ? sortParams(Object.entries(ep.res.props).map(([k, v]) => parsePropDefinition(k, v))) : null, + resDefs: null//extractPropDefRef(Object.entries(ep.res.props).map(([k, v]) => parsePropDefinition(k, v))) }; await ctx.render('../../../../src/client/docs/api/endpoints/view', Object.assign(await genVars(lang), vars)); @@ -200,8 +200,8 @@ router.get('/*/api/entities/*', async ctx => { await ctx.render('../../../../src/client/docs/api/entities/view', Object.assign(await genVars(lang), { name: x.name, desc: x.desc, - props: sortParams(x.props.map((p: any) => parseParam(p))), - propDefs: extractDefs(x.props) + props: sortParams(Object.entries(x.props).map(([k, v]) => parsePropDefinition(k, v))), + propDefs: extractPropDefRef(x.props) })); });