diff --git a/src/client/docs/api/endpoints/view.pug b/src/client/docs/api/endpoints/view.pug index 24fff1b7982d64acc6d9374cc901b880238c8c87..e046b3fc3381670b94f92d8b9e58cede13f33f61 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 cccf42f221df4a87cbd1338f29c52ef0dd6ecd9f..3328734d2ba4b173831e971af1b220ac270ac8ba 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: false + optional: true desc: - ja: "ã“ã®ã‚µãƒ¼ãƒãƒ¼ã«ãŠã‘るアカウント" - en: "The account of this user on this server" - defName: "account" - def: - - name: "lastUsedAt" - type: "date" + ja: "連æºã•れã¦ã„ã‚‹Twitterã‚¢ã‚«ã‚¦ãƒ³ãƒˆæƒ…å ±" + en: "The info of the connected twitter account of this user" + props: + userId: + type: "string" optional: false desc: - ja: "最終利用日時" - en: "The last used date of this user" - - name: "isBot" - type: "boolean" - optional: true + ja: "ユーザーID" + en: "The user ID" + screenName: + type: "string" + optional: false desc: - ja: "botã‹å¦ã‹(自己申告ã§ã‚ã‚‹ã“ã¨ã«ç•™æ„)" - en: "Whether is bot or not" - - name: "twitter" - type: "object" + 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 profile of this user" + props: + location: + 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 + ja: "å ´æ‰€" + en: "The location of this user" + birthday: + type: "string" + optional: true 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 a930f71eb66ac03fbbc65817d361fad61ec488e7..3f50bfd3bd3abc6d8e1c30d8afd854ad95a5f161 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 79665a61e3c2f9c0a6ee985a058526e16c45031c..9e03abefebdfea4b0753b0fc9824ec2da83a0609 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 45fc77503e4a4d14f5382bc01d51f99c980a6e71..c2f128527e8558464509514612e49019349c02c3 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 e67070963448eb2d736de5964ece338ab6ac6f67..ceba14bd277211d15b301ba5fdb61caad0c18680 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<any>).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) })); });