From 9b41023c43add194d69259e0a8a8c323aa44c778 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Fri, 6 Jul 2018 02:58:29 +0900
Subject: [PATCH] wip

---
 package.json                                  |  2 +-
 src/client/docs/api/gulpfile.ts               | 48 +++++++------
 src/client/docs/gulpfile.ts                   |  4 +-
 src/server/api/endpoints/aggregation/posts.ts |  2 +-
 src/server/api/endpoints/aggregation/users.ts |  2 +-
 .../endpoints/aggregation/users/activity.ts   |  2 +-
 .../endpoints/aggregation/users/followers.ts  |  2 +-
 .../endpoints/aggregation/users/following.ts  |  2 +-
 .../api/endpoints/aggregation/users/post.ts   |  2 +-
 .../endpoints/aggregation/users/reaction.ts   |  2 +-
 src/server/api/endpoints/app/create.ts        |  2 +-
 .../api/endpoints/app/name_id/available.ts    |  2 +-
 src/server/api/endpoints/app/show.ts          |  2 +-
 src/server/api/endpoints/auth/accept.ts       |  2 +-
 .../api/endpoints/auth/session/generate.ts    |  2 +-
 src/server/api/endpoints/auth/session/show.ts |  2 +-
 .../api/endpoints/auth/session/userkey.ts     |  2 +-
 src/server/api/endpoints/drive.ts             |  2 +-
 src/server/api/endpoints/drive/files.ts       |  2 +-
 .../api/endpoints/drive/files/create.ts       |  2 +-
 .../api/endpoints/drive/files/delete.ts       |  2 +-
 src/server/api/endpoints/drive/files/find.ts  |  2 +-
 src/server/api/endpoints/drive/files/show.ts  |  2 +-
 .../api/endpoints/drive/files/update.ts       |  2 +-
 .../endpoints/drive/files/upload_from_url.ts  |  2 +-
 src/server/api/endpoints/drive/folders.ts     |  2 +-
 .../api/endpoints/drive/folders/create.ts     |  2 +-
 .../api/endpoints/drive/folders/find.ts       |  2 +-
 .../api/endpoints/drive/folders/show.ts       |  2 +-
 .../api/endpoints/drive/folders/update.ts     |  2 +-
 src/server/api/endpoints/drive/stream.ts      |  2 +-
 src/server/api/endpoints/following/create.ts  |  2 +-
 src/server/api/endpoints/following/delete.ts  |  2 +-
 .../endpoints/following/requests/accept.ts    |  2 +-
 .../endpoints/following/requests/cancel.ts    |  2 +-
 .../api/endpoints/following/requests/list.ts  |  2 +-
 .../endpoints/following/requests/reject.ts    |  2 +-
 src/server/api/endpoints/following/stalk.ts   |  2 +-
 src/server/api/endpoints/following/unstalk.ts |  2 +-
 src/server/api/endpoints/hashtags/trend.ts    |  2 +-
 src/server/api/endpoints/i.ts                 |  2 +-
 src/server/api/endpoints/i/2fa/done.ts        |  2 +-
 src/server/api/endpoints/i/2fa/register.ts    |  2 +-
 src/server/api/endpoints/i/2fa/unregister.ts  |  2 +-
 src/server/api/endpoints/i/authorized_apps.ts |  2 +-
 src/server/api/endpoints/i/change_password.ts |  2 +-
 src/server/api/endpoints/i/favorites.ts       |  2 +-
 src/server/api/endpoints/i/notifications.ts   |  2 +-
 src/server/api/endpoints/i/pin.ts             |  2 +-
 .../api/endpoints/i/regenerate_token.ts       |  2 +-
 src/server/api/endpoints/i/signin_history.ts  |  2 +-
 src/server/api/endpoints/i/update.ts          |  2 +-
 .../api/endpoints/i/update_client_setting.ts  |  2 +-
 src/server/api/endpoints/i/update_home.ts     |  2 +-
 .../api/endpoints/i/update_mobile_home.ts     |  2 +-
 src/server/api/endpoints/i/update_widget.ts   |  2 +-
 src/server/api/endpoints/messaging/history.ts |  2 +-
 .../api/endpoints/messaging/messages.ts       |  2 +-
 .../endpoints/messaging/messages/create.ts    |  2 +-
 src/server/api/endpoints/meta.ts              |  2 +-
 src/server/api/endpoints/mute/create.ts       |  2 +-
 src/server/api/endpoints/mute/delete.ts       |  2 +-
 src/server/api/endpoints/mute/list.ts         |  2 +-
 src/server/api/endpoints/my/apps.ts           |  2 +-
 src/server/api/endpoints/notes.ts             |  2 +-
 .../api/endpoints/notes/conversation.ts       |  2 +-
 src/server/api/endpoints/notes/create.ts      | 10 ++-
 src/server/api/endpoints/notes/delete.ts      |  2 +-
 .../api/endpoints/notes/favorites/create.ts   |  2 +-
 .../api/endpoints/notes/favorites/delete.ts   |  2 +-
 .../api/endpoints/notes/global-timeline.ts    |  2 +-
 .../api/endpoints/notes/local-timeline.ts     |  2 +-
 src/server/api/endpoints/notes/mentions.ts    |  2 +-
 .../endpoints/notes/polls/recommendation.ts   |  2 +-
 src/server/api/endpoints/notes/polls/vote.ts  |  2 +-
 src/server/api/endpoints/notes/reactions.ts   |  2 +-
 .../api/endpoints/notes/reactions/create.ts   |  2 +-
 .../api/endpoints/notes/reactions/delete.ts   |  2 +-
 src/server/api/endpoints/notes/replies.ts     |  2 +-
 src/server/api/endpoints/notes/reposts.ts     |  2 +-
 src/server/api/endpoints/notes/search.ts      |  2 +-
 .../api/endpoints/notes/search_by_tag.ts      |  2 +-
 src/server/api/endpoints/notes/show.ts        |  2 +-
 src/server/api/endpoints/notes/timeline.ts    |  2 +-
 src/server/api/endpoints/notes/trend.ts       |  2 +-
 .../api/endpoints/notes/user-list-timeline.ts |  2 +-
 .../notifications/mark_as_read_all.ts         |  2 +-
 src/server/api/endpoints/reversi/games.ts     |  2 +-
 .../api/endpoints/reversi/games/show.ts       |  2 +-
 .../api/endpoints/reversi/invitations.ts      |  2 +-
 src/server/api/endpoints/reversi/match.ts     |  2 +-
 .../api/endpoints/reversi/match/cancel.ts     |  2 +-
 src/server/api/endpoints/stats.ts             |  2 +-
 src/server/api/endpoints/sw/register.ts       |  2 +-
 .../api/endpoints/username/available.ts       |  2 +-
 src/server/api/endpoints/users.ts             |  2 +-
 src/server/api/endpoints/users/followers.ts   |  2 +-
 src/server/api/endpoints/users/following.ts   |  2 +-
 .../users/get_frequently_replied_users.ts     |  2 +-
 .../api/endpoints/users/lists/create.ts       |  2 +-
 src/server/api/endpoints/users/lists/list.ts  |  2 +-
 src/server/api/endpoints/users/lists/push.ts  |  2 +-
 src/server/api/endpoints/users/lists/show.ts  |  2 +-
 src/server/api/endpoints/users/notes.ts       |  2 +-
 .../api/endpoints/users/recommendation.ts     |  2 +-
 src/server/api/endpoints/users/search.ts      |  2 +-
 .../api/endpoints/users/search_by_username.ts |  2 +-
 src/server/api/endpoints/users/show.ts        |  2 +-
 src/server/web/docs.ts                        | 70 +++++++++++++++++++
 109 files changed, 212 insertions(+), 130 deletions(-)

diff --git a/package.json b/package.json
index 42b8fdf5e4..3663d42c4b 100644
--- a/package.json
+++ b/package.json
@@ -89,7 +89,7 @@
 		"autwh": "0.1.0",
 		"bcryptjs": "2.4.3",
 		"bootstrap-vue": "2.0.0-rc.11",
-		"cafy": "11.0.0",
+		"cafy": "11.1.0",
 		"chalk": "2.4.1",
 		"crc-32": "1.2.0",
 		"css-loader": "0.28.11",
diff --git a/src/client/docs/api/gulpfile.ts b/src/client/docs/api/gulpfile.ts
index 0eb8b88287..4b38058b5c 100644
--- a/src/client/docs/api/gulpfile.ts
+++ b/src/client/docs/api/gulpfile.ts
@@ -16,12 +16,13 @@ import fa from '../../../build/fa';
 import config from './../../../config';
 
 import generateVars from '../vars';
+import { Context } from 'cafy';
+import ObjectContext from 'cafy/built/types/object';
 
 const langs = Object.keys(locales);
 
 const kebab = (string: string) => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase();
 
-// WIP type
 const parseParam = (param: any) => {
 	const id = param.type.match(/^id\((.+?)\)|^id/);
 	const entity = param.type.match(/^entity\((.+?)\)/);
@@ -58,6 +59,14 @@ const parseParam = (param: any) => {
 	return param;
 };
 
+// WIP type
+const parseEPDefParam = (key: string, param: Context) => {
+	return Object.assign({
+		name: key,
+		type: param.getType()
+	}, param.data);
+};
+
 const sortParams = (params: Array<{name: string}>) => {
 	params.sort((a, b) => {
 		if (a.name < b.name)
@@ -70,17 +79,18 @@ const sortParams = (params: Array<{name: string}>) => {
 };
 
 // WIP type
-const extractDefs = (params: any[]) => {
+const extractDefs = (params: Context[]) => {
 	let defs: any[] = [];
 
 	params.forEach(param => {
-		if (param.def) {
+		if (param.data && param.data.ref) {
+			const props = (param as ObjectContext<any>).props;
 			defs.push({
-				name: param.defName,
-				params: sortParams(param.def.map((p: any) => parseParam(p)))
+				name: param.data.ref,
+				params: sortParams(Object.keys(props).map(k => parseEPDefParam(k, props[k])))
 			});
 
-			const childDefs = extractDefs(param.def);
+			const childDefs = extractDefs(Object.keys(props).map(k => props[k]));
 
 			defs = defs.concat(childDefs);
 		}
@@ -94,35 +104,33 @@ gulp.task('doc:api', [
 	'doc:api:entities'
 ]);
 
-gulp.task('doc:api:endpoints', async () => {
+gulp.task('doc:api:endpoints', ['build:ts'], async () => {
 	const commonVars = await generateVars();
-	glob('./src/client/docs/api/endpoints/**/*.yaml', (globErr, files) => {
+	glob('./built/server/api/endpoints/**/*.js', (globErr, files) => {
 		if (globErr) {
 			console.error(globErr);
 			return;
 		}
-		//console.log(files);
-		files.forEach(file => {
-			const ep: any = yaml.safeLoad(fs.readFileSync(file, 'utf-8'));
+		console.log(files.map(file => require('../../../../' + file)));
+
+		files.map(file => require('../../../../' + file)).filter(x => x.meta).map(x => x.meta).forEach(ep => {
+			console.log(ep);
 			const vars = {
-				endpoint: ep.endpoint,
+				endpoint: ep.name,
 				url: {
 					host: config.api_url,
-					path: ep.endpoint
+					path: ep.name
 				},
 				desc: ep.desc,
 				// @ts-ignore
-				params: sortParams(ep.params.map(p => parseParam(p))),
+				params: sortParams(ep.params.map(p => parseEPDefParam(p))),
 				paramDefs: extractDefs(ep.params),
-				// @ts-ignore
-				res: ep.res ? sortParams(ep.res.map(p => parseParam(p))) : null,
-				resDefs: ep.res ? extractDefs(ep.res) : null,
 			};
 			langs.forEach(lang => {
 				pug.renderFile('./src/client/docs/api/endpoints/view.pug', Object.assign({}, vars, {
 					lang,
-					title: ep.endpoint,
-					src: `https://github.com/syuilo/misskey/tree/master/src/client/docs/api/endpoints/${ep.endpoint}.yaml`,
+					title: ep.name,
+					src: `https://github.com/syuilo/misskey/tree/master/src/client/docs/api/endpoints/${ep.name}.yaml`,
 					kebab,
 					common: commonVars
 				}), (renderErr, html) => {
@@ -133,7 +141,7 @@ gulp.task('doc:api:endpoints', async () => {
 					const i18n = new I18nReplacer(lang);
 					html = html.replace(i18n.pattern, i18n.replacement);
 					html = fa(html);
-					const htmlPath = `./built/client/docs/${lang}/api/endpoints/${ep.endpoint}.html`;
+					const htmlPath = `./built/client/docs/${lang}/api/endpoints/${ep.name}.html`;
 					mkdirp(path.dirname(htmlPath), (mkdirErr) => {
 						if (mkdirErr) {
 							console.error(mkdirErr);
diff --git a/src/client/docs/gulpfile.ts b/src/client/docs/gulpfile.ts
index 4683a04659..5ef87315fb 100644
--- a/src/client/docs/gulpfile.ts
+++ b/src/client/docs/gulpfile.ts
@@ -15,11 +15,11 @@ import I18nReplacer from '../../build/i18n';
 import fa from '../../build/fa';
 import generateVars from './vars';
 
-require('./api/gulpfile.ts');
+//require('./api/gulpfile.ts');
 
 gulp.task('doc', [
 	'doc:docs',
-	'doc:api',
+	//'doc:api',
 	'doc:styles'
 ]);
 
diff --git a/src/server/api/endpoints/aggregation/posts.ts b/src/server/api/endpoints/aggregation/posts.ts
index 5de5789954..629bb19108 100644
--- a/src/server/api/endpoints/aggregation/posts.ts
+++ b/src/server/api/endpoints/aggregation/posts.ts
@@ -4,7 +4,7 @@ import Note from '../../../../models/note';
 /**
  * Aggregate notes
  */
-module.exports = (params: any) => new Promise(async (res, rej) => {
+export default (params: any) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 365, limitErr] = $.num.optional.range(1, 365).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/aggregation/users.ts b/src/server/api/endpoints/aggregation/users.ts
index 3ab96b66d4..f1e41cf170 100644
--- a/src/server/api/endpoints/aggregation/users.ts
+++ b/src/server/api/endpoints/aggregation/users.ts
@@ -4,7 +4,7 @@ import User from '../../../../models/user';
 /**
  * Aggregate users
  */
-module.exports = (params: any) => new Promise(async (res, rej) => {
+export default (params: any) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 365, limitErr] = $.num.optional.range(1, 365).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/aggregation/users/activity.ts b/src/server/api/endpoints/aggregation/users/activity.ts
index 98c7d3a1dc..4afa6d1203 100644
--- a/src/server/api/endpoints/aggregation/users/activity.ts
+++ b/src/server/api/endpoints/aggregation/users/activity.ts
@@ -7,7 +7,7 @@ import Note from '../../../../../models/note';
 /**
  * Aggregate activity of a user
  */
-module.exports = (params: any) => new Promise(async (res, rej) => {
+export default (params: any) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 365, limitErr] = $.num.optional.range(1, 365).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/aggregation/users/followers.ts b/src/server/api/endpoints/aggregation/users/followers.ts
index 847f376079..484c58ad3d 100644
--- a/src/server/api/endpoints/aggregation/users/followers.ts
+++ b/src/server/api/endpoints/aggregation/users/followers.ts
@@ -8,7 +8,7 @@ import FollowedLog from '../../../../../models/followed-log';
 /**
  * Aggregate followers of a user
  */
-module.exports = (params: any) => new Promise(async (res, rej) => {
+export default (params: any) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [userId, userIdErr] = $.type(ID).get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/aggregation/users/following.ts b/src/server/api/endpoints/aggregation/users/following.ts
index 6c52752f98..16812a9f09 100644
--- a/src/server/api/endpoints/aggregation/users/following.ts
+++ b/src/server/api/endpoints/aggregation/users/following.ts
@@ -8,7 +8,7 @@ import FollowingLog from '../../../../../models/following-log';
 /**
  * Aggregate following of a user
  */
-module.exports = (params: any) => new Promise(async (res, rej) => {
+export default (params: any) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [userId, userIdErr] = $.type(ID).get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/aggregation/users/post.ts b/src/server/api/endpoints/aggregation/users/post.ts
index 28ba1482bf..4965d3c7ac 100644
--- a/src/server/api/endpoints/aggregation/users/post.ts
+++ b/src/server/api/endpoints/aggregation/users/post.ts
@@ -5,7 +5,7 @@ import Note from '../../../../../models/note';
 /**
  * Aggregate note of a user
  */
-module.exports = (params: any) => new Promise(async (res, rej) => {
+export default (params: any) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [userId, userIdErr] = $.type(ID).get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/aggregation/users/reaction.ts b/src/server/api/endpoints/aggregation/users/reaction.ts
index adb5acfb4e..20b5e93d54 100644
--- a/src/server/api/endpoints/aggregation/users/reaction.ts
+++ b/src/server/api/endpoints/aggregation/users/reaction.ts
@@ -5,7 +5,7 @@ import Reaction from '../../../../../models/note-reaction';
 /**
  * Aggregate reaction of a user
  */
-module.exports = (params: any) => new Promise(async (res, rej) => {
+export default (params: any) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [userId, userIdErr] = $.type(ID).get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/app/create.ts b/src/server/api/endpoints/app/create.ts
index 5da87e5a3a..3b3eafa699 100644
--- a/src/server/api/endpoints/app/create.ts
+++ b/src/server/api/endpoints/app/create.ts
@@ -59,7 +59,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Create an app
  */
-module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'nameId' parameter
 	const [nameId, nameIdErr] = $.str.pipe(isValidNameId).get(params.nameId);
 	if (nameIdErr) return rej('invalid nameId param');
diff --git a/src/server/api/endpoints/app/name_id/available.ts b/src/server/api/endpoints/app/name_id/available.ts
index 58101a7e6a..9f6e8dc34e 100644
--- a/src/server/api/endpoints/app/name_id/available.ts
+++ b/src/server/api/endpoints/app/name_id/available.ts
@@ -40,7 +40,7 @@ import { isValidNameId } from '../../../../../models/app';
  * @param {any} params
  * @return {Promise<any>}
  */
-module.exports = async (params: any) => new Promise(async (res, rej) => {
+export default async (params: any) => new Promise(async (res, rej) => {
 	// Get 'nameId' parameter
 	const [nameId, nameIdErr] = $.str.pipe(isValidNameId).get(params.nameId);
 	if (nameIdErr) return rej('invalid nameId param');
diff --git a/src/server/api/endpoints/app/show.ts b/src/server/api/endpoints/app/show.ts
index 982c87c4ec..2b8a929543 100644
--- a/src/server/api/endpoints/app/show.ts
+++ b/src/server/api/endpoints/app/show.ts
@@ -35,7 +35,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Show an app
  */
-module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
 	const isSecure = user != null && app == null;
 
 	// Get 'appId' parameter
diff --git a/src/server/api/endpoints/auth/accept.ts b/src/server/api/endpoints/auth/accept.ts
index fc6cbc473d..d14c853415 100644
--- a/src/server/api/endpoints/auth/accept.ts
+++ b/src/server/api/endpoints/auth/accept.ts
@@ -32,7 +32,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Accept
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'token' parameter
 	const [token, tokenErr] = $.str.get(params.token);
 	if (tokenErr) return rej('invalid token param');
diff --git a/src/server/api/endpoints/auth/session/generate.ts b/src/server/api/endpoints/auth/session/generate.ts
index 5a4d99ff3b..f70495fa4f 100644
--- a/src/server/api/endpoints/auth/session/generate.ts
+++ b/src/server/api/endpoints/auth/session/generate.ts
@@ -44,7 +44,7 @@ import config from '../../../../../config';
  * @param {any} params
  * @return {Promise<any>}
  */
-module.exports = (params: any) => new Promise(async (res, rej) => {
+export default (params: any) => new Promise(async (res, rej) => {
 	// Get 'appSecret' parameter
 	const [appSecret, appSecretErr] = $.str.get(params.appSecret);
 	if (appSecretErr) return rej('invalid appSecret param');
diff --git a/src/server/api/endpoints/auth/session/show.ts b/src/server/api/endpoints/auth/session/show.ts
index 3d3b6bbf61..3716b49c5a 100644
--- a/src/server/api/endpoints/auth/session/show.ts
+++ b/src/server/api/endpoints/auth/session/show.ts
@@ -45,7 +45,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Show a session
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'token' parameter
 	const [token, tokenErr] = $.str.get(params.token);
 	if (tokenErr) return rej('invalid token param');
diff --git a/src/server/api/endpoints/auth/session/userkey.ts b/src/server/api/endpoints/auth/session/userkey.ts
index 3ea48fbe34..8d67c2bdad 100644
--- a/src/server/api/endpoints/auth/session/userkey.ts
+++ b/src/server/api/endpoints/auth/session/userkey.ts
@@ -49,7 +49,7 @@ import { pack } from '../../../../../models/user';
  * @param {any} params
  * @return {Promise<any>}
  */
-module.exports = (params: any) => new Promise(async (res, rej) => {
+export default (params: any) => new Promise(async (res, rej) => {
 	// Get 'appSecret' parameter
 	const [appSecret, appSecretErr] = $.str.get(params.appSecret);
 	if (appSecretErr) return rej('invalid appSecret param');
diff --git a/src/server/api/endpoints/drive.ts b/src/server/api/endpoints/drive.ts
index 9caad273c8..66ac30c4cf 100644
--- a/src/server/api/endpoints/drive.ts
+++ b/src/server/api/endpoints/drive.ts
@@ -4,7 +4,7 @@ import { ILocalUser } from '../../../models/user';
 /**
  * Get drive information
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Calculate drive usage
 	const usage = await DriveFile
 		.aggregate([{
diff --git a/src/server/api/endpoints/drive/files.ts b/src/server/api/endpoints/drive/files.ts
index fa99c4a51b..c0b6c3b069 100644
--- a/src/server/api/endpoints/drive/files.ts
+++ b/src/server/api/endpoints/drive/files.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Get drive files
  */
-module.exports = async (params: any, user: ILocalUser) => {
+export default async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
diff --git a/src/server/api/endpoints/drive/files/create.ts b/src/server/api/endpoints/drive/files/create.ts
index 4c348c1302..5a2bef38ce 100644
--- a/src/server/api/endpoints/drive/files/create.ts
+++ b/src/server/api/endpoints/drive/files/create.ts
@@ -7,7 +7,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Create a file
  */
-module.exports = async (file: any, params: any, user: ILocalUser): Promise<any> => {
+export default async (file: any, params: any, user: ILocalUser): Promise<any> => {
 	if (file == null) {
 		throw 'file is required';
 	}
diff --git a/src/server/api/endpoints/drive/files/delete.ts b/src/server/api/endpoints/drive/files/delete.ts
index 17eb0eb4b9..992f0286f1 100644
--- a/src/server/api/endpoints/drive/files/delete.ts
+++ b/src/server/api/endpoints/drive/files/delete.ts
@@ -7,7 +7,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Delete a file
  */
-module.exports = async (params: any, user: ILocalUser) => {
+export default async (params: any, user: ILocalUser) => {
 	// Get 'fileId' parameter
 	const [fileId, fileIdErr] = $.type(ID).get(params.fileId);
 	if (fileIdErr) throw 'invalid fileId param';
diff --git a/src/server/api/endpoints/drive/files/find.ts b/src/server/api/endpoints/drive/files/find.ts
index dfca4e0395..ed76749739 100644
--- a/src/server/api/endpoints/drive/files/find.ts
+++ b/src/server/api/endpoints/drive/files/find.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Find a file(s)
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'name' parameter
 	const [name, nameErr] = $.str.get(params.name);
 	if (nameErr) return rej('invalid name param');
diff --git a/src/server/api/endpoints/drive/files/show.ts b/src/server/api/endpoints/drive/files/show.ts
index e7dca486c5..2e4ac06bf6 100644
--- a/src/server/api/endpoints/drive/files/show.ts
+++ b/src/server/api/endpoints/drive/files/show.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Show a file
  */
-module.exports = async (params: any, user: ILocalUser) => {
+export default async (params: any, user: ILocalUser) => {
 	// Get 'fileId' parameter
 	const [fileId, fileIdErr] = $.type(ID).get(params.fileId);
 	if (fileIdErr) throw 'invalid fileId param';
diff --git a/src/server/api/endpoints/drive/files/update.ts b/src/server/api/endpoints/drive/files/update.ts
index 76656beaa0..73a193a56b 100644
--- a/src/server/api/endpoints/drive/files/update.ts
+++ b/src/server/api/endpoints/drive/files/update.ts
@@ -7,7 +7,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Update a file
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'fileId' parameter
 	const [fileId, fileIdErr] = $.type(ID).get(params.fileId);
 	if (fileIdErr) return rej('invalid fileId param');
diff --git a/src/server/api/endpoints/drive/files/upload_from_url.ts b/src/server/api/endpoints/drive/files/upload_from_url.ts
index 442a0d3940..7218b345b0 100644
--- a/src/server/api/endpoints/drive/files/upload_from_url.ts
+++ b/src/server/api/endpoints/drive/files/upload_from_url.ts
@@ -9,7 +9,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Create a file from a URL
  */
-module.exports = async (params: any, user: ILocalUser): Promise<any> => {
+export default async (params: any, user: ILocalUser): Promise<any> => {
 	// Get 'url' parameter
 	// TODO: Validate this url
 	const [url, urlErr] = $.str.get(params.url);
diff --git a/src/server/api/endpoints/drive/folders.ts b/src/server/api/endpoints/drive/folders.ts
index 878c747a42..70f581f424 100644
--- a/src/server/api/endpoints/drive/folders.ts
+++ b/src/server/api/endpoints/drive/folders.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Get drive folders
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/drive/folders/create.ts b/src/server/api/endpoints/drive/folders/create.ts
index c06a40ded3..60c7383895 100644
--- a/src/server/api/endpoints/drive/folders/create.ts
+++ b/src/server/api/endpoints/drive/folders/create.ts
@@ -6,7 +6,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Create drive folder
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'name' parameter
 	const [name = '無題のフォルダー', nameErr] = $.str.optional.pipe(isValidFolderName).get(params.name);
 	if (nameErr) return rej('invalid name param');
diff --git a/src/server/api/endpoints/drive/folders/find.ts b/src/server/api/endpoints/drive/folders/find.ts
index 414202ccd6..2e4a09b80d 100644
--- a/src/server/api/endpoints/drive/folders/find.ts
+++ b/src/server/api/endpoints/drive/folders/find.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Find a folder(s)
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'name' parameter
 	const [name, nameErr] = $.str.get(params.name);
 	if (nameErr) return rej('invalid name param');
diff --git a/src/server/api/endpoints/drive/folders/show.ts b/src/server/api/endpoints/drive/folders/show.ts
index c9b4930a76..edc8cb6f1c 100644
--- a/src/server/api/endpoints/drive/folders/show.ts
+++ b/src/server/api/endpoints/drive/folders/show.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Show a folder
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'folderId' parameter
 	const [folderId, folderIdErr] = $.type(ID).get(params.folderId);
 	if (folderIdErr) return rej('invalid folderId param');
diff --git a/src/server/api/endpoints/drive/folders/update.ts b/src/server/api/endpoints/drive/folders/update.ts
index 20675771fe..744d8fcb12 100644
--- a/src/server/api/endpoints/drive/folders/update.ts
+++ b/src/server/api/endpoints/drive/folders/update.ts
@@ -6,7 +6,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Update a folder
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'folderId' parameter
 	const [folderId, folderIdErr] = $.type(ID).get(params.folderId);
 	if (folderIdErr) return rej('invalid folderId param');
diff --git a/src/server/api/endpoints/drive/stream.ts b/src/server/api/endpoints/drive/stream.ts
index 612d922c6b..a7aef926f0 100644
--- a/src/server/api/endpoints/drive/stream.ts
+++ b/src/server/api/endpoints/drive/stream.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Get drive stream
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/following/create.ts b/src/server/api/endpoints/following/create.ts
index 3e45b8da53..ffd399d446 100644
--- a/src/server/api/endpoints/following/create.ts
+++ b/src/server/api/endpoints/following/create.ts
@@ -6,7 +6,7 @@ import create from '../../../../services/following/create';
 /**
  * Follow a user
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	const follower = user;
 
 	// Get 'userId' parameter
diff --git a/src/server/api/endpoints/following/delete.ts b/src/server/api/endpoints/following/delete.ts
index 0af8813cf9..46fe13b2a9 100644
--- a/src/server/api/endpoints/following/delete.ts
+++ b/src/server/api/endpoints/following/delete.ts
@@ -6,7 +6,7 @@ import deleteFollowing from '../../../../services/following/delete';
 /**
  * Unfollow a user
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	const follower = user;
 
 	// Get 'userId' parameter
diff --git a/src/server/api/endpoints/following/requests/accept.ts b/src/server/api/endpoints/following/requests/accept.ts
index a09e32e4d9..722fdac607 100644
--- a/src/server/api/endpoints/following/requests/accept.ts
+++ b/src/server/api/endpoints/following/requests/accept.ts
@@ -5,7 +5,7 @@ import User, { ILocalUser } from '../../../../../models/user';
 /**
  * Accept a follow request
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [followerId, followerIdErr] = $.type(ID).get(params.userId);
 	if (followerIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/following/requests/cancel.ts b/src/server/api/endpoints/following/requests/cancel.ts
index f2a40854c2..88c1b57f43 100644
--- a/src/server/api/endpoints/following/requests/cancel.ts
+++ b/src/server/api/endpoints/following/requests/cancel.ts
@@ -5,7 +5,7 @@ import User, { pack, ILocalUser } from '../../../../../models/user';
 /**
  * Cancel a follow request
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [followeeId, followeeIdErr] = $.type(ID).get(params.userId);
 	if (followeeIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/following/requests/list.ts b/src/server/api/endpoints/following/requests/list.ts
index 287c5a8e46..dfe9858f3a 100644
--- a/src/server/api/endpoints/following/requests/list.ts
+++ b/src/server/api/endpoints/following/requests/list.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Get all pending received follow requests
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	const reqs = await FollowRequest.find({
 		followeeId: user._id
 	});
diff --git a/src/server/api/endpoints/following/requests/reject.ts b/src/server/api/endpoints/following/requests/reject.ts
index 69dddf1355..7b7db2909d 100644
--- a/src/server/api/endpoints/following/requests/reject.ts
+++ b/src/server/api/endpoints/following/requests/reject.ts
@@ -5,7 +5,7 @@ import User, { ILocalUser } from '../../../../../models/user';
 /**
  * Reject a follow request
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [followerId, followerIdErr] = $.type(ID).get(params.userId);
 	if (followerIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/following/stalk.ts b/src/server/api/endpoints/following/stalk.ts
index b9d19d57b4..19c71cfd5a 100644
--- a/src/server/api/endpoints/following/stalk.ts
+++ b/src/server/api/endpoints/following/stalk.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Stalk a user
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	const follower = user;
 
 	// Get 'userId' parameter
diff --git a/src/server/api/endpoints/following/unstalk.ts b/src/server/api/endpoints/following/unstalk.ts
index 255f22ca1f..03ee107835 100644
--- a/src/server/api/endpoints/following/unstalk.ts
+++ b/src/server/api/endpoints/following/unstalk.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Unstalk a user
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	const follower = user;
 
 	// Get 'userId' parameter
diff --git a/src/server/api/endpoints/hashtags/trend.ts b/src/server/api/endpoints/hashtags/trend.ts
index 17af9d6a9a..01dfccc71c 100644
--- a/src/server/api/endpoints/hashtags/trend.ts
+++ b/src/server/api/endpoints/hashtags/trend.ts
@@ -15,7 +15,7 @@ const max = 5;
 /**
  * Get trends of hashtags
  */
-module.exports = () => new Promise(async (res, rej) => {
+export default () => new Promise(async (res, rej) => {
 	//#region 1. 直近Aの内に投稿されたハッシュタグ(とユーザーのペア)を集計
 	const data = await Note.aggregate([{
 		$match: {
diff --git a/src/server/api/endpoints/i.ts b/src/server/api/endpoints/i.ts
index 5c769a02fd..150ab34a0f 100644
--- a/src/server/api/endpoints/i.ts
+++ b/src/server/api/endpoints/i.ts
@@ -4,7 +4,7 @@ import { IApp } from '../../../models/app';
 /**
  * Show myself
  */
-module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
 	const isSecure = user != null && app == null;
 
 	// Serialize
diff --git a/src/server/api/endpoints/i/2fa/done.ts b/src/server/api/endpoints/i/2fa/done.ts
index 61f13c4c61..fef045948a 100644
--- a/src/server/api/endpoints/i/2fa/done.ts
+++ b/src/server/api/endpoints/i/2fa/done.ts
@@ -2,7 +2,7 @@ import $ from 'cafy';
 import * as speakeasy from 'speakeasy';
 import User, { ILocalUser } from '../../../../../models/user';
 
-module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'token' parameter
 	const [token, tokenErr] = $.str.get(params.token);
 	if (tokenErr) return rej('invalid token param');
diff --git a/src/server/api/endpoints/i/2fa/register.ts b/src/server/api/endpoints/i/2fa/register.ts
index d05892c84b..ac703f5b0a 100644
--- a/src/server/api/endpoints/i/2fa/register.ts
+++ b/src/server/api/endpoints/i/2fa/register.ts
@@ -5,7 +5,7 @@ import * as QRCode from 'qrcode';
 import User, { ILocalUser } from '../../../../../models/user';
 import config from '../../../../../config';
 
-module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'password' parameter
 	const [password, passwordErr] = $.str.get(params.password);
 	if (passwordErr) return rej('invalid password param');
diff --git a/src/server/api/endpoints/i/2fa/unregister.ts b/src/server/api/endpoints/i/2fa/unregister.ts
index fc197cb1e4..7d99ee397d 100644
--- a/src/server/api/endpoints/i/2fa/unregister.ts
+++ b/src/server/api/endpoints/i/2fa/unregister.ts
@@ -2,7 +2,7 @@ import $ from 'cafy';
 import * as bcrypt from 'bcryptjs';
 import User, { ILocalUser } from '../../../../../models/user';
 
-module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'password' parameter
 	const [password, passwordErr] = $.str.get(params.password);
 	if (passwordErr) return rej('invalid password param');
diff --git a/src/server/api/endpoints/i/authorized_apps.ts b/src/server/api/endpoints/i/authorized_apps.ts
index 9c518b3c84..24c4b58f7f 100644
--- a/src/server/api/endpoints/i/authorized_apps.ts
+++ b/src/server/api/endpoints/i/authorized_apps.ts
@@ -6,7 +6,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Get authorized apps of my account
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/i/change_password.ts b/src/server/api/endpoints/i/change_password.ts
index 9851fa895a..698db5a6e4 100644
--- a/src/server/api/endpoints/i/change_password.ts
+++ b/src/server/api/endpoints/i/change_password.ts
@@ -5,7 +5,7 @@ import User, { ILocalUser } from '../../../../models/user';
 /**
  * Change password
  */
-module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'currentPasword' parameter
 	const [currentPassword, currentPasswordErr] = $.str.get(params.currentPasword);
 	if (currentPasswordErr) return rej('invalid currentPasword param');
diff --git a/src/server/api/endpoints/i/favorites.ts b/src/server/api/endpoints/i/favorites.ts
index 1ed42a98b1..75b456ca58 100644
--- a/src/server/api/endpoints/i/favorites.ts
+++ b/src/server/api/endpoints/i/favorites.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Get favorited notes
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts
index 93c5abf4d5..1073b0369f 100644
--- a/src/server/api/endpoints/i/notifications.ts
+++ b/src/server/api/endpoints/i/notifications.ts
@@ -9,7 +9,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Get notifications
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'following' parameter
 	const [following = false, followingError] =
 		$.bool.optional.get(params.following);
diff --git a/src/server/api/endpoints/i/pin.ts b/src/server/api/endpoints/i/pin.ts
index 7f4a45e1f5..1edc571737 100644
--- a/src/server/api/endpoints/i/pin.ts
+++ b/src/server/api/endpoints/i/pin.ts
@@ -6,7 +6,7 @@ import { pack } from '../../../../models/user';
 /**
  * Pin note
  */
-module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/i/regenerate_token.ts b/src/server/api/endpoints/i/regenerate_token.ts
index 3ffab5428e..1f68e3abd7 100644
--- a/src/server/api/endpoints/i/regenerate_token.ts
+++ b/src/server/api/endpoints/i/regenerate_token.ts
@@ -7,7 +7,7 @@ import generateUserToken from '../../common/generate-native-user-token';
 /**
  * Regenerate native token
  */
-module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'password' parameter
 	const [password, passwordErr] = $.str.get(params.password);
 	if (passwordErr) return rej('invalid password param');
diff --git a/src/server/api/endpoints/i/signin_history.ts b/src/server/api/endpoints/i/signin_history.ts
index e58f48f72d..1315a2cfb6 100644
--- a/src/server/api/endpoints/i/signin_history.ts
+++ b/src/server/api/endpoints/i/signin_history.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Get signin history of my account
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts
index fc23d9fc82..08d17fa854 100644
--- a/src/server/api/endpoints/i/update.ts
+++ b/src/server/api/endpoints/i/update.ts
@@ -8,7 +8,7 @@ import { IApp } from '../../../../models/app';
 /**
  * Update myself
  */
-module.exports = async (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
+export default async (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
 	const isSecure = user != null && app == null;
 
 	const updates = {} as any;
diff --git a/src/server/api/endpoints/i/update_client_setting.ts b/src/server/api/endpoints/i/update_client_setting.ts
index 9eca66cfcc..edcd3e7423 100644
--- a/src/server/api/endpoints/i/update_client_setting.ts
+++ b/src/server/api/endpoints/i/update_client_setting.ts
@@ -5,7 +5,7 @@ import event from '../../../../publishers/stream';
 /**
  * Update myself
  */
-module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'name' parameter
 	const [name, nameErr] = $.str.get(params.name);
 	if (nameErr) return rej('invalid name param');
diff --git a/src/server/api/endpoints/i/update_home.ts b/src/server/api/endpoints/i/update_home.ts
index 511a647d88..03795ae8d9 100644
--- a/src/server/api/endpoints/i/update_home.ts
+++ b/src/server/api/endpoints/i/update_home.ts
@@ -2,7 +2,7 @@ import $ from 'cafy';
 import User, { ILocalUser } from '../../../../models/user';
 import event from '../../../../publishers/stream';
 
-module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'home' parameter
 	const [home, homeErr] = $.arr(
 		$.obj.strict()
diff --git a/src/server/api/endpoints/i/update_mobile_home.ts b/src/server/api/endpoints/i/update_mobile_home.ts
index b1f25624fd..a2e2a13465 100644
--- a/src/server/api/endpoints/i/update_mobile_home.ts
+++ b/src/server/api/endpoints/i/update_mobile_home.ts
@@ -2,7 +2,7 @@ import $ from 'cafy';
 import User, { ILocalUser } from '../../../../models/user';
 import event from '../../../../publishers/stream';
 
-module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'home' parameter
 	const [home, homeErr] = $.arr(
 		$.obj.strict()
diff --git a/src/server/api/endpoints/i/update_widget.ts b/src/server/api/endpoints/i/update_widget.ts
index 82bb04d1f4..006916c9fe 100644
--- a/src/server/api/endpoints/i/update_widget.ts
+++ b/src/server/api/endpoints/i/update_widget.ts
@@ -2,7 +2,7 @@ import $ from 'cafy';
 import User, { ILocalUser } from '../../../../models/user';
 import event from '../../../../publishers/stream';
 
-module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'id' parameter
 	const [id, idErr] = $.str.get(params.id);
 	if (idErr) return rej('invalid id param');
diff --git a/src/server/api/endpoints/messaging/history.ts b/src/server/api/endpoints/messaging/history.ts
index d76aa78230..a1bd015864 100644
--- a/src/server/api/endpoints/messaging/history.ts
+++ b/src/server/api/endpoints/messaging/history.ts
@@ -7,7 +7,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Show messaging history
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/messaging/messages.ts b/src/server/api/endpoints/messaging/messages.ts
index 16236136d3..6ac1cc980a 100644
--- a/src/server/api/endpoints/messaging/messages.ts
+++ b/src/server/api/endpoints/messaging/messages.ts
@@ -7,7 +7,7 @@ import read from '../../common/read-messaging-message';
 /**
  * Get messages
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [recipientId, recipientIdErr] = $.type(ID).get(params.userId);
 	if (recipientIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/messaging/messages/create.ts b/src/server/api/endpoints/messaging/messages/create.ts
index d4f16d0dce..bcbbd9a1f4 100644
--- a/src/server/api/endpoints/messaging/messages/create.ts
+++ b/src/server/api/endpoints/messaging/messages/create.ts
@@ -14,7 +14,7 @@ import config from '../../../../../config';
 /**
  * Create a message
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [recipientId, recipientIdErr] = $.type(ID).get(params.userId);
 	if (recipientIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts
index ce460d0b8b..836123a3ae 100644
--- a/src/server/api/endpoints/meta.ts
+++ b/src/server/api/endpoints/meta.ts
@@ -38,7 +38,7 @@ const client = require('../../../../built/client/meta.json');
 /**
  * Show core info
  */
-module.exports = (params: any) => new Promise(async (res, rej) => {
+export default (params: any) => new Promise(async (res, rej) => {
 	const meta: any = (await Meta.findOne()) || {};
 
 	res({
diff --git a/src/server/api/endpoints/mute/create.ts b/src/server/api/endpoints/mute/create.ts
index 415745e2c3..0f8d8fb09d 100644
--- a/src/server/api/endpoints/mute/create.ts
+++ b/src/server/api/endpoints/mute/create.ts
@@ -5,7 +5,7 @@ import Mute from '../../../../models/mute';
 /**
  * Mute a user
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	const muter = user;
 
 	// Get 'userId' parameter
diff --git a/src/server/api/endpoints/mute/delete.ts b/src/server/api/endpoints/mute/delete.ts
index 2d1d286585..bc3160c157 100644
--- a/src/server/api/endpoints/mute/delete.ts
+++ b/src/server/api/endpoints/mute/delete.ts
@@ -5,7 +5,7 @@ import Mute from '../../../../models/mute';
 /**
  * Unmute a user
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	const muter = user;
 
 	// Get 'userId' parameter
diff --git a/src/server/api/endpoints/mute/list.ts b/src/server/api/endpoints/mute/list.ts
index b632b1a1a9..89287c50a0 100644
--- a/src/server/api/endpoints/mute/list.ts
+++ b/src/server/api/endpoints/mute/list.ts
@@ -6,7 +6,7 @@ import { getFriendIds } from '../../common/get-friends';
 /**
  * Get muted users of a user
  */
-module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'iknow' parameter
 	const [iknow = false, iknowErr] = $.bool.optional.get(params.iknow);
 	if (iknowErr) return rej('invalid iknow param');
diff --git a/src/server/api/endpoints/my/apps.ts b/src/server/api/endpoints/my/apps.ts
index 8f67af8854..8e946c9466 100644
--- a/src/server/api/endpoints/my/apps.ts
+++ b/src/server/api/endpoints/my/apps.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Get my apps
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/notes.ts b/src/server/api/endpoints/notes.ts
index 8b0c4177fc..dd8d09dcc4 100644
--- a/src/server/api/endpoints/notes.ts
+++ b/src/server/api/endpoints/notes.ts
@@ -7,7 +7,7 @@ import Note, { pack } from '../../../models/note';
 /**
  * Get all notes
  */
-module.exports = (params: any) => new Promise(async (res, rej) => {
+export default (params: any) => new Promise(async (res, rej) => {
 	// Get 'local' parameter
 	const [local, localErr] = $.bool.optional.get(params.local);
 	if (localErr) return rej('invalid local param');
diff --git a/src/server/api/endpoints/notes/conversation.ts b/src/server/api/endpoints/notes/conversation.ts
index a8e8c4eeb7..e47b977279 100644
--- a/src/server/api/endpoints/notes/conversation.ts
+++ b/src/server/api/endpoints/notes/conversation.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Show conversation of a note
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts
index 62eafa5340..45fc77503e 100644
--- a/src/server/api/endpoints/notes/create.ts
+++ b/src/server/api/endpoints/notes/create.ts
@@ -7,6 +7,8 @@ import { IApp } from '../../../../models/app';
 import getParams from '../../get-params';
 
 export const meta = {
+	name: 'notes/create',
+
 	desc: {
 		ja: '投稿します。'
 	},
@@ -57,7 +59,8 @@ export const meta = {
 		}).optional.nullable.strict().note({
 			desc: {
 				ja: '位置情報'
-			}
+			},
+			ref: 'geo'
 		}),
 
 		mediaIds: $.arr($.type(ID)).optional.unique().range(1, 4).note({
@@ -80,7 +83,8 @@ export const meta = {
 		}).optional.strict().note({
 			desc: {
 				ja: 'アンケート'
-			}
+			},
+			ref: 'poll'
 		})
 	},
 
@@ -100,7 +104,7 @@ export const meta = {
 /**
  * Create a note
  */
-module.exports = (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
 	const [ps, psErr] = getParams(meta, params);
 	if (psErr) return rej(psErr);
 
diff --git a/src/server/api/endpoints/notes/delete.ts b/src/server/api/endpoints/notes/delete.ts
index 70bcdbaab9..49907e4449 100644
--- a/src/server/api/endpoints/notes/delete.ts
+++ b/src/server/api/endpoints/notes/delete.ts
@@ -6,7 +6,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Delete a note
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/favorites/create.ts b/src/server/api/endpoints/notes/favorites/create.ts
index 23f7ac5f8d..9ec75dbba6 100644
--- a/src/server/api/endpoints/notes/favorites/create.ts
+++ b/src/server/api/endpoints/notes/favorites/create.ts
@@ -6,7 +6,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Favorite a note
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/favorites/delete.ts b/src/server/api/endpoints/notes/favorites/delete.ts
index 7d2d2b4cb5..f9916905bf 100644
--- a/src/server/api/endpoints/notes/favorites/delete.ts
+++ b/src/server/api/endpoints/notes/favorites/delete.ts
@@ -6,7 +6,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Unfavorite a note
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts
index d032aa1a62..6de83ddad0 100644
--- a/src/server/api/endpoints/notes/global-timeline.ts
+++ b/src/server/api/endpoints/notes/global-timeline.ts
@@ -7,7 +7,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Get timeline of global
  */
-module.exports = async (params: any, user: ILocalUser) => {
+export default async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts
index 74462ce4e4..3e96877c74 100644
--- a/src/server/api/endpoints/notes/local-timeline.ts
+++ b/src/server/api/endpoints/notes/local-timeline.ts
@@ -7,7 +7,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Get timeline of local
  */
-module.exports = async (params: any, user: ILocalUser) => {
+export default async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts
index 06ddc258b0..82e3371ffa 100644
--- a/src/server/api/endpoints/notes/mentions.ts
+++ b/src/server/api/endpoints/notes/mentions.ts
@@ -7,7 +7,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Get mentions of myself
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'following' parameter
 	const [following = false, followingError] =
 		$.bool.optional.get(params.following);
diff --git a/src/server/api/endpoints/notes/polls/recommendation.ts b/src/server/api/endpoints/notes/polls/recommendation.ts
index fb1ee6dda8..f448bb66fc 100644
--- a/src/server/api/endpoints/notes/polls/recommendation.ts
+++ b/src/server/api/endpoints/notes/polls/recommendation.ts
@@ -6,7 +6,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Get recommended polls
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/notes/polls/vote.ts b/src/server/api/endpoints/notes/polls/vote.ts
index 72ac6bb202..b86d319b37 100644
--- a/src/server/api/endpoints/notes/polls/vote.ts
+++ b/src/server/api/endpoints/notes/polls/vote.ts
@@ -10,7 +10,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Vote poll of a note
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/reactions.ts b/src/server/api/endpoints/notes/reactions.ts
index cf88f3860a..5e15ed3ec6 100644
--- a/src/server/api/endpoints/notes/reactions.ts
+++ b/src/server/api/endpoints/notes/reactions.ts
@@ -6,7 +6,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Show reactions of a note
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/reactions/create.ts b/src/server/api/endpoints/notes/reactions/create.ts
index 33e457e308..709b47ab5d 100644
--- a/src/server/api/endpoints/notes/reactions/create.ts
+++ b/src/server/api/endpoints/notes/reactions/create.ts
@@ -7,7 +7,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * React to a note
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/reactions/delete.ts b/src/server/api/endpoints/notes/reactions/delete.ts
index 1f2d662511..81671751a0 100644
--- a/src/server/api/endpoints/notes/reactions/delete.ts
+++ b/src/server/api/endpoints/notes/reactions/delete.ts
@@ -6,7 +6,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Unreact to a note
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/replies.ts b/src/server/api/endpoints/notes/replies.ts
index 3b209b3176..baefde3159 100644
--- a/src/server/api/endpoints/notes/replies.ts
+++ b/src/server/api/endpoints/notes/replies.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Get replies of a note
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/reposts.ts b/src/server/api/endpoints/notes/reposts.ts
index 043a653e83..118e684a87 100644
--- a/src/server/api/endpoints/notes/reposts.ts
+++ b/src/server/api/endpoints/notes/reposts.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Show a renotes of a note
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/search.ts b/src/server/api/endpoints/notes/search.ts
index 3dbf407dff..badaa7afc0 100644
--- a/src/server/api/endpoints/notes/search.ts
+++ b/src/server/api/endpoints/notes/search.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../models/user';
 import { pack } from '../../../../models/note';
 import es from '../../../../db/elasticsearch';
 
-module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'query' parameter
 	const [query, queryError] = $.str.get(params.query);
 	if (queryError) return rej('invalid query param');
diff --git a/src/server/api/endpoints/notes/search_by_tag.ts b/src/server/api/endpoints/notes/search_by_tag.ts
index 78487e2c03..a6fcae5932 100644
--- a/src/server/api/endpoints/notes/search_by_tag.ts
+++ b/src/server/api/endpoints/notes/search_by_tag.ts
@@ -8,7 +8,7 @@ import { pack } from '../../../../models/note';
 /**
  * Search notes by tag
  */
-module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'tag' parameter
 	const [tag, tagError] = $.str.get(params.tag);
 	if (tagError) return rej('invalid tag param');
diff --git a/src/server/api/endpoints/notes/show.ts b/src/server/api/endpoints/notes/show.ts
index 1ba7145996..0a27494962 100644
--- a/src/server/api/endpoints/notes/show.ts
+++ b/src/server/api/endpoints/notes/show.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Show a note
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'noteId' parameter
 	const [noteId, noteIdErr] = $.type(ID).get(params.noteId);
 	if (noteIdErr) return rej('invalid noteId param');
diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts
index 9a5306be61..9144c6625c 100644
--- a/src/server/api/endpoints/notes/timeline.ts
+++ b/src/server/api/endpoints/notes/timeline.ts
@@ -8,7 +8,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Get timeline of myself
  */
-module.exports = async (params: any, user: ILocalUser) => {
+export default async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
diff --git a/src/server/api/endpoints/notes/trend.ts b/src/server/api/endpoints/notes/trend.ts
index b4acd7c5f4..ae66234c0b 100644
--- a/src/server/api/endpoints/notes/trend.ts
+++ b/src/server/api/endpoints/notes/trend.ts
@@ -6,7 +6,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Get trend notes
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/notes/user-list-timeline.ts b/src/server/api/endpoints/notes/user-list-timeline.ts
index f14a869c7f..8a59857392 100644
--- a/src/server/api/endpoints/notes/user-list-timeline.ts
+++ b/src/server/api/endpoints/notes/user-list-timeline.ts
@@ -8,7 +8,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * Get timeline of a user list
  */
-module.exports = async (params: any, user: ILocalUser) => {
+export default async (params: any, user: ILocalUser) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) throw 'invalid limit param';
diff --git a/src/server/api/endpoints/notifications/mark_as_read_all.ts b/src/server/api/endpoints/notifications/mark_as_read_all.ts
index faaaf65a2d..6e2b13fa8c 100644
--- a/src/server/api/endpoints/notifications/mark_as_read_all.ts
+++ b/src/server/api/endpoints/notifications/mark_as_read_all.ts
@@ -5,7 +5,7 @@ import User, { ILocalUser } from '../../../../models/user';
 /**
  * Mark as read all notifications
  */
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Update documents
 	await Notification.update({
 		notifieeId: user._id,
diff --git a/src/server/api/endpoints/reversi/games.ts b/src/server/api/endpoints/reversi/games.ts
index e68f57c6d4..11da7b3c0c 100644
--- a/src/server/api/endpoints/reversi/games.ts
+++ b/src/server/api/endpoints/reversi/games.ts
@@ -2,7 +2,7 @@ import $ from 'cafy'; import ID from '../../../../cafy-id';
 import ReversiGame, { pack } from '../../../../models/reversi-game';
 import { ILocalUser } from '../../../../models/user';
 
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'my' parameter
 	const [my = false, myErr] = $.bool.optional.get(params.my);
 	if (myErr) return rej('invalid my param');
diff --git a/src/server/api/endpoints/reversi/games/show.ts b/src/server/api/endpoints/reversi/games/show.ts
index d70ee547a2..ba52066040 100644
--- a/src/server/api/endpoints/reversi/games/show.ts
+++ b/src/server/api/endpoints/reversi/games/show.ts
@@ -3,7 +3,7 @@ import ReversiGame, { pack } from '../../../../../models/reversi-game';
 import Reversi from '../../../../../reversi/core';
 import { ILocalUser } from '../../../../../models/user';
 
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'gameId' parameter
 	const [gameId, gameIdErr] = $.type(ID).get(params.gameId);
 	if (gameIdErr) return rej('invalid gameId param');
diff --git a/src/server/api/endpoints/reversi/invitations.ts b/src/server/api/endpoints/reversi/invitations.ts
index d7727071ae..179abe8cd9 100644
--- a/src/server/api/endpoints/reversi/invitations.ts
+++ b/src/server/api/endpoints/reversi/invitations.ts
@@ -1,7 +1,7 @@
 import Matching, { pack as packMatching } from '../../../../models/reversi-matching';
 import { ILocalUser } from '../../../../models/user';
 
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Find session
 	const invitations = await Matching.find({
 		childId: user._id
diff --git a/src/server/api/endpoints/reversi/match.ts b/src/server/api/endpoints/reversi/match.ts
index 907df7cf43..20473d9a4b 100644
--- a/src/server/api/endpoints/reversi/match.ts
+++ b/src/server/api/endpoints/reversi/match.ts
@@ -5,7 +5,7 @@ import User, { ILocalUser } from '../../../../models/user';
 import publishUserStream, { publishReversiStream } from '../../../../publishers/stream';
 import { eighteight } from '../../../../reversi/maps';
 
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [childId, childIdErr] = $.type(ID).get(params.userId);
 	if (childIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/reversi/match/cancel.ts b/src/server/api/endpoints/reversi/match/cancel.ts
index 1c9c799dbe..470d848b53 100644
--- a/src/server/api/endpoints/reversi/match/cancel.ts
+++ b/src/server/api/endpoints/reversi/match/cancel.ts
@@ -1,7 +1,7 @@
 import Matching from '../../../../../models/reversi-matching';
 import { ILocalUser } from '../../../../../models/user';
 
-module.exports = (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	await Matching.remove({
 		parentId: user._id
 	});
diff --git a/src/server/api/endpoints/stats.ts b/src/server/api/endpoints/stats.ts
index 74ab6ba945..ca11f67012 100644
--- a/src/server/api/endpoints/stats.ts
+++ b/src/server/api/endpoints/stats.ts
@@ -3,7 +3,7 @@ import Meta from '../../../models/meta';
 /**
  * Get the misskey's statistics
  */
-module.exports = () => new Promise(async (res, rej) => {
+export default () => new Promise(async (res, rej) => {
 	const meta = await Meta.findOne();
 
 	res(meta.stats);
diff --git a/src/server/api/endpoints/sw/register.ts b/src/server/api/endpoints/sw/register.ts
index f04a77fa4d..c7bf1bfbe5 100644
--- a/src/server/api/endpoints/sw/register.ts
+++ b/src/server/api/endpoints/sw/register.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../models/user';
 /**
  * subscribe service worker
  */
-module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'endpoint' parameter
 	const [endpoint, endpointErr] = $.str.get(params.endpoint);
 	if (endpointErr) return rej('invalid endpoint param');
diff --git a/src/server/api/endpoints/username/available.ts b/src/server/api/endpoints/username/available.ts
index aad3adc514..ff12b797ed 100644
--- a/src/server/api/endpoints/username/available.ts
+++ b/src/server/api/endpoints/username/available.ts
@@ -5,7 +5,7 @@ import { validateUsername } from '../../../../models/user';
 /**
  * Check available username
  */
-module.exports = async (params: any) => new Promise(async (res, rej) => {
+export default async (params: any) => new Promise(async (res, rej) => {
 	// Get 'username' parameter
 	const [username, usernameError] = $.str.pipe(validateUsername).get(params.username);
 	if (usernameError) return rej('invalid username param');
diff --git a/src/server/api/endpoints/users.ts b/src/server/api/endpoints/users.ts
index 0756ddc918..d7e85d3cbe 100644
--- a/src/server/api/endpoints/users.ts
+++ b/src/server/api/endpoints/users.ts
@@ -4,7 +4,7 @@ import User, { pack, ILocalUser } from '../../../models/user';
 /**
  * Lists all users
  */
-module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/users/followers.ts b/src/server/api/endpoints/users/followers.ts
index ef36a0df46..f726976774 100644
--- a/src/server/api/endpoints/users/followers.ts
+++ b/src/server/api/endpoints/users/followers.ts
@@ -7,7 +7,7 @@ import { getFriendIds } from '../../common/get-friends';
 /**
  * Get followers of a user
  */
-module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [userId, userIdErr] = $.type(ID).get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/users/following.ts b/src/server/api/endpoints/users/following.ts
index 2c38fe4f87..1b2eb9c878 100644
--- a/src/server/api/endpoints/users/following.ts
+++ b/src/server/api/endpoints/users/following.ts
@@ -7,7 +7,7 @@ import { getFriendIds } from '../../common/get-friends';
 /**
  * Get following users of a user
  */
-module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [userId, userIdErr] = $.type(ID).get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/users/get_frequently_replied_users.ts b/src/server/api/endpoints/users/get_frequently_replied_users.ts
index 6077420908..98d662d29c 100644
--- a/src/server/api/endpoints/users/get_frequently_replied_users.ts
+++ b/src/server/api/endpoints/users/get_frequently_replied_users.ts
@@ -2,7 +2,7 @@ import $ from 'cafy'; import ID from '../../../../cafy-id';
 import Note from '../../../../models/note';
 import User, { pack, ILocalUser } from '../../../../models/user';
 
-module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [userId, userIdErr] = $.type(ID).get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/users/lists/create.ts b/src/server/api/endpoints/users/lists/create.ts
index cdd1a0d813..f3776afee0 100644
--- a/src/server/api/endpoints/users/lists/create.ts
+++ b/src/server/api/endpoints/users/lists/create.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Create a user list
  */
-module.exports = async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
+export default async (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'title' parameter
 	const [title, titleErr] = $.str.range(1, 100).get(params.title);
 	if (titleErr) return rej('invalid title param');
diff --git a/src/server/api/endpoints/users/lists/list.ts b/src/server/api/endpoints/users/lists/list.ts
index bf8391d863..88fa75a111 100644
--- a/src/server/api/endpoints/users/lists/list.ts
+++ b/src/server/api/endpoints/users/lists/list.ts
@@ -4,7 +4,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Add a user to a user list
  */
-module.exports = async (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
+export default async (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Fetch lists
 	const userLists = await UserList.find({
 		userId: me._id,
diff --git a/src/server/api/endpoints/users/lists/push.ts b/src/server/api/endpoints/users/lists/push.ts
index d8a3b3c9aa..0e7caea064 100644
--- a/src/server/api/endpoints/users/lists/push.ts
+++ b/src/server/api/endpoints/users/lists/push.ts
@@ -9,7 +9,7 @@ import { deliver } from '../../../../../queue';
 /**
  * Add a user to a user list
  */
-module.exports = async (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
+export default async (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'listId' parameter
 	const [listId, listIdErr] = $.type(ID).get(params.listId);
 	if (listIdErr) return rej('invalid listId param');
diff --git a/src/server/api/endpoints/users/lists/show.ts b/src/server/api/endpoints/users/lists/show.ts
index e4ae239613..4716dd8211 100644
--- a/src/server/api/endpoints/users/lists/show.ts
+++ b/src/server/api/endpoints/users/lists/show.ts
@@ -5,7 +5,7 @@ import { ILocalUser } from '../../../../../models/user';
 /**
  * Show a user list
  */
-module.exports = async (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
+export default async (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'listId' parameter
 	const [listId, listIdErr] = $.type(ID).get(params.listId);
 	if (listIdErr) return rej('invalid listId param');
diff --git a/src/server/api/endpoints/users/notes.ts b/src/server/api/endpoints/users/notes.ts
index ac4e17946a..6d8d85ff5c 100644
--- a/src/server/api/endpoints/users/notes.ts
+++ b/src/server/api/endpoints/users/notes.ts
@@ -6,7 +6,7 @@ import User, { ILocalUser } from '../../../../models/user';
 /**
  * Get notes of a user
  */
-module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'userId' parameter
 	const [userId, userIdErr] = $.type(ID).optional.get(params.userId);
 	if (userIdErr) return rej('invalid userId param');
diff --git a/src/server/api/endpoints/users/recommendation.ts b/src/server/api/endpoints/users/recommendation.ts
index 6221d751b4..b7402b7fb1 100644
--- a/src/server/api/endpoints/users/recommendation.ts
+++ b/src/server/api/endpoints/users/recommendation.ts
@@ -7,7 +7,7 @@ import Mute from '../../../../models/mute';
 /**
  * Get recommended users
  */
-module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'limit' parameter
 	const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
 	if (limitErr) return rej('invalid limit param');
diff --git a/src/server/api/endpoints/users/search.ts b/src/server/api/endpoints/users/search.ts
index 36a708d21e..d443d35b47 100644
--- a/src/server/api/endpoints/users/search.ts
+++ b/src/server/api/endpoints/users/search.ts
@@ -5,7 +5,7 @@ const escapeRegexp = require('escape-regexp');
 /**
  * Search a user
  */
-module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'query' parameter
 	const [query, queryError] = $.str.pipe(x => x != '').get(params.query);
 	if (queryError) return rej('invalid query param');
diff --git a/src/server/api/endpoints/users/search_by_username.ts b/src/server/api/endpoints/users/search_by_username.ts
index 1c0f09449c..56030a000d 100644
--- a/src/server/api/endpoints/users/search_by_username.ts
+++ b/src/server/api/endpoints/users/search_by_username.ts
@@ -4,7 +4,7 @@ import User, { pack, ILocalUser } from '../../../../models/user';
 /**
  * Search a user by username
  */
-module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	// Get 'query' parameter
 	const [query, queryError] = $.str.get(params.query);
 	if (queryError) return rej('invalid query param');
diff --git a/src/server/api/endpoints/users/show.ts b/src/server/api/endpoints/users/show.ts
index 5cbd83f649..276e7c325b 100644
--- a/src/server/api/endpoints/users/show.ts
+++ b/src/server/api/endpoints/users/show.ts
@@ -7,7 +7,7 @@ const cursorOption = { fields: { data: false } };
 /**
  * Show user(s)
  */
-module.exports = (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
+export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
 	let user;
 
 	// Get 'userId' parameter
diff --git a/src/server/web/docs.ts b/src/server/web/docs.ts
index e65cc87b12..849194388c 100644
--- a/src/server/web/docs.ts
+++ b/src/server/web/docs.ts
@@ -5,9 +5,53 @@
 import ms = require('ms');
 import * as Router from 'koa-router';
 import * as send from 'koa-send';
+import { Context } from 'cafy';
+import ObjectContext from 'cafy/built/types/object';
+import config from '../../config';
+import generateVars from '../../client/docs/vars';
 
 const docs = `${__dirname}/../../client/docs/`;
 
+// WIP type
+const parseEPDefParam = (key: string, param: Context) => {
+	return Object.assign({
+		name: key,
+		type: param.getType()
+	}, param.data);
+};
+
+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 extractDefs = (params: Context[]) => {
+	let defs: any[] = [];
+
+	params.forEach(param => {
+		if (param.data && param.data.ref) {
+			const props = (param as ObjectContext<any>).props;
+			defs.push({
+				name: param.data.ref,
+				params: sortParams(Object.keys(props).map(k => parseEPDefParam(k, props[k])))
+			});
+
+			const childDefs = extractDefs(Object.keys(props).map(k => props[k]));
+
+			defs = defs.concat(childDefs);
+		}
+	});
+
+	return sortParams(defs);
+};
+
 const router = new Router();
 
 router.get('/assets/*', async ctx => {
@@ -18,6 +62,32 @@ router.get('/assets/*', async ctx => {
 	});
 });
 
+router.get('/*/api/endpoints/*', async ctx => {
+	const ep = require('../../../built/server/api/endpoints/' + ctx.params[1]).meta;
+
+	const vars = {
+		endpoint: ep.name,
+		url: {
+			host: config.api_url,
+			path: ep.name
+		},
+		desc: ep.desc,
+		// @ts-ignore
+		params: sortParams(Object.keys(ep.params).map(k => parseEPDefParam(k, ep.params[k]))),
+		paramDefs: extractDefs(Object.keys(ep.params).map(k => ep.params[k])),
+	};
+	console.log(vars);
+
+	const commonVars = await generateVars();
+
+	await ctx.render('../../../../src/client/docs/api/endpoints/view', Object.assign({}, vars, {
+		lang: 'ja',
+		title: ep.name,
+		kebab: (string: string) => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase(),
+		common: commonVars
+	}));
+});
+
 router.get('*', async ctx => {
 	await send(ctx, `${ctx.params[0]}.html`, {
 		root: docs
-- 
GitLab