commit
						6640276cf7
					
				
					 10 changed files with 500 additions and 0 deletions
				
			
		|  | @ -11,6 +11,7 @@ | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "config": "node ./init.js", |     "config": "node ./init.js", | ||||||
|     "start": "node ./built/index.js", |     "start": "node ./built/index.js", | ||||||
|  |     "swagger": "node ./swagger.js", | ||||||
|     "build": "gulp build", |     "build": "gulp build", | ||||||
|     "rebuild": "gulp rebuild", |     "rebuild": "gulp rebuild", | ||||||
|     "clean": "gulp clean", |     "clean": "gulp clean", | ||||||
|  | @ -124,6 +125,7 @@ | ||||||
|     "sortablejs": "1.5.0-rc1", |     "sortablejs": "1.5.0-rc1", | ||||||
|     "subdomain": "1.2.0", |     "subdomain": "1.2.0", | ||||||
|     "summaly": "1.2.7", |     "summaly": "1.2.7", | ||||||
|  |     "swagger-jsdoc": "^1.8.4", | ||||||
|     "syuilo-password-strength": "0.0.1", |     "syuilo-password-strength": "0.0.1", | ||||||
|     "syuilo-transformify": "0.1.2", |     "syuilo-transformify": "0.1.2", | ||||||
|     "tcp-port-used": "0.1.2", |     "tcp-port-used": "0.1.2", | ||||||
|  |  | ||||||
|  | @ -7,6 +7,59 @@ import rndstr from 'rndstr'; | ||||||
| import App from '../../models/app'; | import App from '../../models/app'; | ||||||
| import serialize from '../../serializers/app'; | import serialize from '../../serializers/app'; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @swagger | ||||||
|  |  * /app/create: | ||||||
|  |  *   post: | ||||||
|  |  *     summary: Create an application | ||||||
|  |  *     parameters: | ||||||
|  |  *       - $ref: "#/parameters/AccessToken" | ||||||
|  |  *       - | ||||||
|  |  *         name: name_id | ||||||
|  |  *         description: Application unique name | ||||||
|  |  *         in: formData | ||||||
|  |  *         required: true | ||||||
|  |  *         type: string | ||||||
|  |  *       - | ||||||
|  |  *         name: name | ||||||
|  |  *         description: Application name | ||||||
|  |  *         in: formData | ||||||
|  |  *         required: true | ||||||
|  |  *         type: string | ||||||
|  |  *       - | ||||||
|  |  *         name: description | ||||||
|  |  *         description: Application description | ||||||
|  |  *         in: formData | ||||||
|  |  *         required: true | ||||||
|  |  *         type: string | ||||||
|  |  *       - | ||||||
|  |  *         name: permission | ||||||
|  |  *         description: Permissions that application has | ||||||
|  |  *         in: formData | ||||||
|  |  *         required: true | ||||||
|  |  *         type: array | ||||||
|  |  *         items: | ||||||
|  |  *           type: string | ||||||
|  |  *           collectionFormat: csv | ||||||
|  |  *       - | ||||||
|  |  *         name: callback_url | ||||||
|  |  *         description: URL called back after authentication | ||||||
|  |  *         in: formData | ||||||
|  |  *         required: false | ||||||
|  |  *         type: string | ||||||
|  |  *        | ||||||
|  |  *     responses: | ||||||
|  |  *       200: | ||||||
|  |  *         description: Created application's information | ||||||
|  |  *         schema: | ||||||
|  |  *           $ref: "#/definitions/Application" | ||||||
|  |  *        | ||||||
|  |  *       default: | ||||||
|  |  *         description: Failed | ||||||
|  |  *         schema: | ||||||
|  |  *           $ref: "#/definitions/Error" | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Create an app |  * Create an app | ||||||
|  * |  * | ||||||
|  |  | ||||||
|  | @ -5,6 +5,35 @@ | ||||||
|  */ |  */ | ||||||
| import App from '../../../models/app'; | import App from '../../../models/app'; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @swagger | ||||||
|  |  * /app/name_id/available: | ||||||
|  |  *   post: | ||||||
|  |  *     summary: Check available name_id on creation an application | ||||||
|  |  *     parameters: | ||||||
|  |  *       - | ||||||
|  |  *         name: name_id | ||||||
|  |  *         description: Application unique name | ||||||
|  |  *         in: formData | ||||||
|  |  *         required: true | ||||||
|  |  *         type: string | ||||||
|  |  *      | ||||||
|  |  *     responses: | ||||||
|  |  *       200: | ||||||
|  |  *         description: Success | ||||||
|  |  *         schema: | ||||||
|  |  *           type: object | ||||||
|  |  *           properties: | ||||||
|  |  *             available: | ||||||
|  |  *               description: Whether name_id is available | ||||||
|  |  *               type: boolean | ||||||
|  |  *          | ||||||
|  |  *       default: | ||||||
|  |  *         description: Failed | ||||||
|  |  *         schema: | ||||||
|  |  *           $ref: "#/definitions/Error" | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Check available name_id of app |  * Check available name_id of app | ||||||
|  * |  * | ||||||
|  |  | ||||||
|  | @ -7,6 +7,36 @@ import * as mongo from 'mongodb'; | ||||||
| import App from '../../models/app'; | import App from '../../models/app'; | ||||||
| import serialize from '../../serializers/app'; | import serialize from '../../serializers/app'; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @swagger | ||||||
|  |  * /app/show: | ||||||
|  |  *   post: | ||||||
|  |  *     summary: Show an application's information | ||||||
|  |  *     description: Require app_id or name_id | ||||||
|  |  *     parameters: | ||||||
|  |  *       - | ||||||
|  |  *         name: app_id | ||||||
|  |  *         description: Application ID | ||||||
|  |  *         in: formData | ||||||
|  |  *         type: string | ||||||
|  |  *       - | ||||||
|  |  *         name: name_id | ||||||
|  |  *         description: Application unique name | ||||||
|  |  *         in: formData | ||||||
|  |  *         type: string | ||||||
|  |  *          | ||||||
|  |  *     responses: | ||||||
|  |  *       200: | ||||||
|  |  *         description: Success | ||||||
|  |  *         schema: | ||||||
|  |  *           $ref: "#/definitions/Application" | ||||||
|  |  *            | ||||||
|  |  *       default: | ||||||
|  |  *         description: Failed | ||||||
|  |  *         schema: | ||||||
|  |  *           $ref: "#/definitions/Error" | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Show an app |  * Show an app | ||||||
|  * |  * | ||||||
|  |  | ||||||
|  | @ -9,6 +9,29 @@ import App from '../../models/app'; | ||||||
| import AuthSess from '../../models/auth-session'; | import AuthSess from '../../models/auth-session'; | ||||||
| import AccessToken from '../../models/access-token'; | import AccessToken from '../../models/access-token'; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @swagger | ||||||
|  |  * /auth/accept: | ||||||
|  |  *   post: | ||||||
|  |  *     summary: Accept a session | ||||||
|  |  *     parameters: | ||||||
|  |  *       - $ref: "#/parameters/NativeToken" | ||||||
|  |  *       -  | ||||||
|  |  *         name: token | ||||||
|  |  *         description: Session Token | ||||||
|  |  *         in: formData | ||||||
|  |  *         required: true | ||||||
|  |  *         type: string | ||||||
|  |  *     responses: | ||||||
|  |  *       204: | ||||||
|  |  *         description: OK | ||||||
|  |  *        | ||||||
|  |  *       default: | ||||||
|  |  *         description: Failed | ||||||
|  |  *         schema: | ||||||
|  |  *           $ref: "#/definitions/Error" | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Accept |  * Accept | ||||||
|  * |  * | ||||||
|  |  | ||||||
|  | @ -7,6 +7,37 @@ import * as uuid from 'uuid'; | ||||||
| import App from '../../../models/app'; | import App from '../../../models/app'; | ||||||
| import AuthSess from '../../../models/auth-session'; | import AuthSess from '../../../models/auth-session'; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @swagger | ||||||
|  |  * /auth/session/generate: | ||||||
|  |  *   post: | ||||||
|  |  *     summary: Generate a session | ||||||
|  |  *     parameters: | ||||||
|  |  *       - | ||||||
|  |  *         name: app_secret | ||||||
|  |  *         description: App Secret | ||||||
|  |  *         in: formData | ||||||
|  |  *         required: true | ||||||
|  |  *         type: string | ||||||
|  |  *          | ||||||
|  |  *     responses: | ||||||
|  |  *       200: | ||||||
|  |  *         description: OK | ||||||
|  |  *         schema: | ||||||
|  |  *           type: object | ||||||
|  |  *           properties: | ||||||
|  |  *             token: | ||||||
|  |  *               type: string | ||||||
|  |  *               description: Session Token | ||||||
|  |  *             url: | ||||||
|  |  *               type: string | ||||||
|  |  *               description: Authentication form's URL | ||||||
|  |  *       default: | ||||||
|  |  *         description: Failed | ||||||
|  |  *         schema: | ||||||
|  |  *           $ref: "#/definitions/Error" | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Generate a session |  * Generate a session | ||||||
|  * |  * | ||||||
|  |  | ||||||
|  | @ -6,6 +6,46 @@ | ||||||
| import AuthSess from '../../../models/auth-session'; | import AuthSess from '../../../models/auth-session'; | ||||||
| import serialize from '../../../serializers/auth-session'; | import serialize from '../../../serializers/auth-session'; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @swagger | ||||||
|  |  * /auth/session/show: | ||||||
|  |  *   post: | ||||||
|  |  *     summary: Show a session information | ||||||
|  |  *     parameters: | ||||||
|  |  *       - | ||||||
|  |  *         name: token | ||||||
|  |  *         description: Session Token | ||||||
|  |  *         in: formData | ||||||
|  |  *         required: true | ||||||
|  |  *         type: string | ||||||
|  |  *          | ||||||
|  |  *     responses: | ||||||
|  |  *       200: | ||||||
|  |  *         description: OK | ||||||
|  |  *         schema:  | ||||||
|  |  *           type: object | ||||||
|  |  *           properties: | ||||||
|  |  *             created_at: | ||||||
|  |  *               type: string | ||||||
|  |  *               format: date-time | ||||||
|  |  *               description: Date and time of the session creation | ||||||
|  |  *             app_id: | ||||||
|  |  *               type: string | ||||||
|  |  *               description: Application ID | ||||||
|  |  *             token: | ||||||
|  |  *               type: string | ||||||
|  |  *               description: Session Token | ||||||
|  |  *             user_id: | ||||||
|  |  *               type: string | ||||||
|  |  *               description: ID of user who create the session | ||||||
|  |  *             app: | ||||||
|  |  *               $ref: "#/definitions/Application" | ||||||
|  |  *       default: | ||||||
|  |  *         description: Failed | ||||||
|  |  *         schema: | ||||||
|  |  *           $ref: "#/definitions/Error" | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Show a session |  * Show a session | ||||||
|  * |  * | ||||||
|  |  | ||||||
|  | @ -8,6 +8,42 @@ import AuthSess from '../../../models/auth-session'; | ||||||
| import AccessToken from '../../../models/access-token'; | import AccessToken from '../../../models/access-token'; | ||||||
| import serialize from '../../../serializers/user'; | import serialize from '../../../serializers/user'; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @swagger | ||||||
|  |  * /auth/session/userkey: | ||||||
|  |  *   post: | ||||||
|  |  *     summary: Get a access token(userkey) | ||||||
|  |  *     parameters: | ||||||
|  |  *       - | ||||||
|  |  *         name: app_secret | ||||||
|  |  *         description: App Secret | ||||||
|  |  *         in: formData | ||||||
|  |  *         required: true | ||||||
|  |  *         type: string | ||||||
|  |  *       - | ||||||
|  |  *         name: token | ||||||
|  |  *         description: Session Token | ||||||
|  |  *         in: formData | ||||||
|  |  *         required: true | ||||||
|  |  *         type: string | ||||||
|  |  *      | ||||||
|  |  *     responses: | ||||||
|  |  *       200: | ||||||
|  |  *         description: OK | ||||||
|  |  *         schema: | ||||||
|  |  *           type: object | ||||||
|  |  *           properties: | ||||||
|  |  *             userkey: | ||||||
|  |  *               type: string | ||||||
|  |  *               description: Access Token | ||||||
|  |  *             user: | ||||||
|  |  *               $ref: "#/definitions/User" | ||||||
|  |  *       default: | ||||||
|  |  *         description: Failed | ||||||
|  |  *         schema: | ||||||
|  |  *           $ref: "#/definitions/Error" | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Generate a session |  * Generate a session | ||||||
|  * |  * | ||||||
|  |  | ||||||
|  | @ -6,6 +6,33 @@ | ||||||
| import prominence from 'prominence'; | import prominence from 'prominence'; | ||||||
| import git from 'git-last-commit'; | import git from 'git-last-commit'; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @swagger | ||||||
|  |  * /meta: | ||||||
|  |  *   post: | ||||||
|  |  *     summary: Show the misskey's information | ||||||
|  |  *     responses: | ||||||
|  |  *       200: | ||||||
|  |  *         description: Success | ||||||
|  |  *         schema: | ||||||
|  |  *           type: object | ||||||
|  |  *           properties: | ||||||
|  |  *             maintainer: | ||||||
|  |  *               description: maintainer's name | ||||||
|  |  *               type: string | ||||||
|  |  *             commit: | ||||||
|  |  *               description: latest commit's hash | ||||||
|  |  *               type: string | ||||||
|  |  *             secure:  | ||||||
|  |  *               description: whether the server supports secure protcols | ||||||
|  |  *               type: boolean | ||||||
|  |  *                | ||||||
|  |  *       default: | ||||||
|  |  *         description: Failed | ||||||
|  |  *         schema: | ||||||
|  |  *           $ref: "#/definitions/Error" | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Show core info |  * Show core info | ||||||
|  * |  * | ||||||
|  |  | ||||||
							
								
								
									
										229
									
								
								swagger.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										229
									
								
								swagger.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,229 @@ | ||||||
|  | 'use strict' | ||||||
|  | 
 | ||||||
|  | const swaggerJSDoc = require('swagger-jsdoc'); | ||||||
|  | const fs = require('fs'); | ||||||
|  | const yaml = require('js-yaml'); | ||||||
|  | 
 | ||||||
|  | const apiRoot = './src/api/endpoints'; | ||||||
|  | const files = [ | ||||||
|  |   'meta.js', | ||||||
|  |   //app
 | ||||||
|  |   'app/show.js', | ||||||
|  |   'app/create.js', | ||||||
|  |   'app/name_id/available.js', | ||||||
|  |   //auth
 | ||||||
|  |   'auth/accept.js', | ||||||
|  |   //auth/session
 | ||||||
|  |   'auth/session/generate.js', | ||||||
|  |   'auth/session/show.js', | ||||||
|  |   'auth/session/userkey.js', | ||||||
|  | ]; | ||||||
|  | 
 | ||||||
|  | const defaultSwagger = { | ||||||
|  |   "swagger": "2.0", | ||||||
|  |   "info": { | ||||||
|  |     "title": "Misskey API", | ||||||
|  |     "version": "aoi" | ||||||
|  |   }, | ||||||
|  |   "host": "api.misskey.xyz", | ||||||
|  |   "schemes": [ | ||||||
|  |     "https" | ||||||
|  |   ], | ||||||
|  |   "consumes": [ | ||||||
|  |     "application/x-www-form-urlencoded" | ||||||
|  |   ], | ||||||
|  |   "produces": [ | ||||||
|  |     "application/json" | ||||||
|  |   ], | ||||||
|  | 
 | ||||||
|  |   "parameters": { | ||||||
|  |     "AccessToken": { | ||||||
|  |       "name": "i", | ||||||
|  |       "description": "Access Token", | ||||||
|  |       "in": "formData", | ||||||
|  |       "required": true, | ||||||
|  |       "type": "string" | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     "NativeToken": { | ||||||
|  |       "name": "i", | ||||||
|  |       "description": "Native Access Token", | ||||||
|  |       "in": "formData", | ||||||
|  |       "required": true, | ||||||
|  |       "type": "string", | ||||||
|  |       "pattern": "^\!.+" | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   "definitions": { | ||||||
|  |     "Error": { | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": { | ||||||
|  |         "error": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "Error message" | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "User": { | ||||||
|  |       "type": "object", | ||||||
|  |       "required": [ | ||||||
|  |         "created_at", | ||||||
|  |         "followers_count", | ||||||
|  |         "following_count", | ||||||
|  |         "id", | ||||||
|  |         "liked_count", | ||||||
|  |         "likes_count", | ||||||
|  |         "name", | ||||||
|  |         "posts_count", | ||||||
|  |         "username" | ||||||
|  |       ], | ||||||
|  |       "properties": { | ||||||
|  |         "avatar_id": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "アバターに設定しているドライブのファイルのID" | ||||||
|  |         }, | ||||||
|  |         "avatar_url": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "アバターURL" | ||||||
|  |         }, | ||||||
|  |         "banner_id": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "バナーに設定しているドライブのファイルのID" | ||||||
|  |         }, | ||||||
|  |         "banner_url": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "バナーURL" | ||||||
|  |         }, | ||||||
|  |         "bio": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "プロフィール" | ||||||
|  |         }, | ||||||
|  |         "birthday": { | ||||||
|  |           "type": "string", | ||||||
|  |           "format": "date", | ||||||
|  |           "description": "誕生日" | ||||||
|  |         }, | ||||||
|  |         "created_at": { | ||||||
|  |           "type": "string", | ||||||
|  |           "format": "date-time", | ||||||
|  |           "description": "アカウント作成日時" | ||||||
|  |         }, | ||||||
|  |         "drive_capacity": { | ||||||
|  |           "type": "integer", | ||||||
|  |           "description": "ドライブの最大容量" | ||||||
|  |         }, | ||||||
|  |         "followers_count": { | ||||||
|  |           "type": "integer", | ||||||
|  |           "description": "フォロワー数" | ||||||
|  |         }, | ||||||
|  |         "following_count": { | ||||||
|  |           "type": "integer", | ||||||
|  |           "description": "フォロー数" | ||||||
|  |         }, | ||||||
|  |         "id": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "ユーザーID" | ||||||
|  |         }, | ||||||
|  |         "is_followed": { | ||||||
|  |           "type": "boolean", | ||||||
|  |           "description": "フォローされているか" | ||||||
|  |         }, | ||||||
|  |         "is_following": { | ||||||
|  |           "type": "boolean", | ||||||
|  |           "description": "フォローしているか" | ||||||
|  |         }, | ||||||
|  |         "liked_count": { | ||||||
|  |           "type": "integer", | ||||||
|  |           "description": "投稿にいいねされた数" | ||||||
|  |         }, | ||||||
|  |         "likes_count": { | ||||||
|  |           "type": "integer", | ||||||
|  |           "description": "投稿にいいねした数" | ||||||
|  |         }, | ||||||
|  |         "location": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "場所" | ||||||
|  |         }, | ||||||
|  |         "name": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "ニックネーム" | ||||||
|  |         }, | ||||||
|  |         "posts_count": { | ||||||
|  |           "type": "integer", | ||||||
|  |           "description": "投稿数" | ||||||
|  |         }, | ||||||
|  |         "username": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "ユーザー名" | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "Application": { | ||||||
|  |       "type": "object", | ||||||
|  |       "properties": { | ||||||
|  |         "created_at": { | ||||||
|  |           "type": "string", | ||||||
|  |           "format": "date-time", | ||||||
|  |           "description": "アプリケーションの作成日時" | ||||||
|  |         }, | ||||||
|  |         "user_id": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "アプリケーションを作成したユーザーのID" | ||||||
|  |         }, | ||||||
|  |         "name": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "アプリケーションの名前" | ||||||
|  |         }, | ||||||
|  |         "name_id": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "アプリケーションのユニークな名前" | ||||||
|  |         }, | ||||||
|  |         "description": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "アプリケーションの説明" | ||||||
|  |         }, | ||||||
|  |         "permission": { | ||||||
|  |           "type": "array", | ||||||
|  |           "items": { | ||||||
|  |             "type": "string" | ||||||
|  |           }, | ||||||
|  |           "description": "アプリケーションの持つ権限一覧" | ||||||
|  |         }, | ||||||
|  |         "callback_url": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "コールバックURL" | ||||||
|  |         }, | ||||||
|  |         "id": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "アプリケーションID" | ||||||
|  |         }, | ||||||
|  |         "icon_url": { | ||||||
|  |           "type": "string", | ||||||
|  |           "description": "アプリケーションのアイコンのURL" | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "securityDefinitions": {}, | ||||||
|  |   "tags": [] | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | var options = { | ||||||
|  |   swaggerDefinition: defaultSwagger, | ||||||
|  |   apis: [] | ||||||
|  | }; | ||||||
|  | options.apis = files.map(c => {return `${apiRoot}/${c}`;}); | ||||||
|  | 
 | ||||||
|  | if(fs.existsSync('.config/config.yml')){ | ||||||
|  |   var config = yaml.safeLoad(fs.readFileSync('./.config/config.yml', 'utf8')); | ||||||
|  |   options.swaggerDefinition.host = `api.${config.url.match(/\:\/\/(.+)$/)[1]}`; | ||||||
|  |   options.swaggerDefinition.schemes = config.https.enable ?  | ||||||
|  |                                       ['https'] :  | ||||||
|  |                                       ['http']; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var swaggerSpec = swaggerJSDoc(options); | ||||||
|  | 
 | ||||||
|  | fs.writeFileSync('api-docs.json', JSON.stringify(swaggerSpec)); | ||||||
|  | 
 | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue