From 75ceeb450073756b5010b1a14d120992647d1c13 Mon Sep 17 00:00:00 2001 From: Karl-Philipp Wulfert Date: Tue, 8 Jan 2019 14:44:15 +0100 Subject: [PATCH] refactor: remove route generation Fixes #21 --- src/cli.ts | 83 ------------------------- src/common.ts | 168 -------------------------------------------------- src/types.ts | 66 -------------------- 3 files changed, 317 deletions(-) delete mode 100644 src/cli.ts delete mode 100644 src/common.ts delete mode 100644 src/types.ts diff --git a/src/cli.ts b/src/cli.ts deleted file mode 100644 index a28716c2..00000000 --- a/src/cli.ts +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2018 StApps - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ -import {execSync} from 'child_process'; -import * as commander from 'commander'; -import {existsSync, mkdirSync, readFileSync, writeFileSync} from 'fs'; -import {resolve} from 'path'; -import {ProjectReflection} from 'typedoc'; -import {gatherRouteInformation, generateDocumentationForRoute, logger, rimrafPromisifed} from './common'; -import {NodesWithMetaInformation} from './types'; - -commander.version(JSON.parse(readFileSync(resolve(__dirname, '..', 'package.json')).toString()).version); - -commander - .command('routes ') - .action(async (relativeMdPath) => { - if (!existsSync(resolve('tmp'))) { - // create tmp directory - mkdirSync(resolve('tmp')); - } - - const command = resolve('node_modules', '.bin', 'typedoc'); - const jsonPath = resolve('tmp', 'out.json'); - const mdPath = resolve(relativeMdPath); - - logger.info(`Using Typedoc from ${command}.`); - - const result = execSync(`${command} --includeDeclarations --excludeExternals --mode modules --json ${jsonPath}`); - - result.toString().split('\n').forEach((line) => { - if (line.length > 0) { - logger.info(line); - } - }); - - const jsonContent: ProjectReflection = JSON.parse(readFileSync(jsonPath).toString()); - - const nodes: NodesWithMetaInformation = {}; - - jsonContent.children.forEach((module: any) => { - if (Array.isArray(module.children) && module.children.length > 0) { - module.children.forEach((node: any) => { - nodes[node.name] = { - module: module.name.substring(1, module.name.length - 1), - type: node.kindString, - }; - }); - } - }); - - const routes = await gatherRouteInformation(jsonContent); - - let output: string = '# Routes\n\n'; - - routes.forEach((routeWithMetaInformation) => { - output += generateDocumentationForRoute(routeWithMetaInformation, nodes); - }); - - writeFileSync(mdPath, output); - - logger.ok(`Route documentation written to ${mdPath}.`); - - // remove temporary files - await rimrafPromisifed(resolve('tmp')); - }); - -commander.parse(process.argv); - -if (commander.args.length < 2) { - commander.outputHelp(); - process.exit(1); -} diff --git a/src/common.ts b/src/common.ts deleted file mode 100644 index 363a2817..00000000 --- a/src/common.ts +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2018 StApps - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ -import {Logger} from '@openstapps/logger'; -import {asyncPool} from 'async-pool-native/dist/async-pool'; -import humanizeString = require('humanize-string'); -import * as rimraf from 'rimraf'; -import {ProjectReflection} from 'typedoc'; -import {promisify} from 'util'; -import {NodesWithMetaInformation, NodeWithMetaInformation, RouteWithMetaInformation} from './types'; - -/** - * Initialized logger - */ -export const logger = new Logger(); - -/** - * Promisified rimraf - */ -export const rimrafPromisifed = promisify(rimraf); - -/** - * Gather relevant information of routes - * - * This gathers the information for all routes that implement the abstract class SCAbstractRoute. - * Furthermore it instantiates every route and adds it to the information. - * - * @param reflection Contents of the JSON representation which Typedoc generates - */ -export async function gatherRouteInformation(reflection: ProjectReflection): Promise { - const routes: RouteWithMetaInformation[] = []; - - await asyncPool(2, reflection.children, async (module: any) => { - if (Array.isArray(module.children) && module.children.length > 0) { - await asyncPool(2, module.children, (async (node: any) => { - if (Array.isArray(node.extendedTypes) && node.extendedTypes.length > 0) { - if (node.extendedTypes.some((extendedType: any) => { - return extendedType.name === 'SCAbstractRoute'; - })) { - logger.info(`Found ${node.name} in ${module.originalName}.`); - - const importedModule = await import(module.originalName); - - const route = new importedModule[node.name](); - - routes.push({description: node.comment, name: node.name, route}); - } - } - })); - } - }); - - return routes; -} - -/** - * Get a linked name for a node - * - * @param name Name of the node - * @param node Node itself - * @param humanize Whether to humanize the name or not - */ -export function getLinkedNameForNode(name: string, node: NodeWithMetaInformation, humanize: boolean = false): string { - let printableName = name; - - if (humanize) { - printableName = humanizeString(name.substr(2)); - } - - let link = `[${printableName}]`; - link += `(${getLinkForNode(name, node)})`; - return link; -} - -/** - * Get link for a node - * - * @param name Name of the node - * @param node Node itself - */ -export function getLinkForNode(name: string, node: NodeWithMetaInformation): string { - let link = 'https://openstapps.gitlab.io/core/'; - const module = node.module.toLowerCase().split('/').join('_'); - - if (node.type === 'Type alias') { - link += 'modules/'; - link += `_${module}_`; - link += `.html#${name.toLowerCase()}`; - return link; - } - - let type = 'classes'; - if (node.type !== 'Class') { - type = `${node.type.toLowerCase()}s`; - } - - link += `${type}/`; - link += `_${module}_`; - link += `.${name.toLowerCase()}.html`; - return link; -} - -/** - * Generate documentation snippet for one route - * - * @param routeWithInfo A route instance with its meta information - * @param nodes - */ -export function generateDocumentationForRoute(routeWithInfo: RouteWithMetaInformation, - nodes: NodesWithMetaInformation): string { - let output = ''; - - const route = routeWithInfo.route; - - output += `## \`${route.method} ${route.urlFragment}\``; - output += ` ${getLinkedNameForNode(routeWithInfo.name, nodes[routeWithInfo.name], true)}\n\n`; - - if (typeof routeWithInfo.description.shortText === 'string') { - output += `**${routeWithInfo.description.shortText}**\n\n`; - } - - if (typeof routeWithInfo.description.text === 'string') { - output += `${routeWithInfo.description.text.replace('\n', '
')}\n\n`; - } - - output += `### Definition - -| parameter | value | -| --- | --- | -| request | ${getLinkedNameForNode(route.requestBodyName, nodes[route.requestBodyName])} | -| response | ${getLinkedNameForNode(route.responseBodyName, nodes[route.responseBodyName])} | -| success code | ${route.statusCodeSuccess} | -| errors | ${route.errorNames.map((errorName) => { - return getLinkedNameForNode(errorName, nodes[errorName]); - }).join('
')} | -`; - if (typeof route.obligatoryParameters === 'object' && Object.keys(route.obligatoryParameters).length > 0) { - let parameterTable = ''; - - Object.keys(route.obligatoryParameters).forEach((parameter) => { - let type = route.obligatoryParameters![parameter]; - - if (typeof nodes[type] !== 'undefined') { - type = getLinkedNameForNode(type, nodes[type]); - } - - parameterTable += ``; - }); - - parameterTable += '
parametertype
${parameter}${type}
'; - - output += `| obligatory parameters | ${parameterTable} |`; - } - output += '\n\n'; - - return output; -} diff --git a/src/types.ts b/src/types.ts deleted file mode 100644 index 43ca248a..00000000 --- a/src/types.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2018 StApps - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ -import {SCAbstractRoute} from './core/Route'; - -/** - * A route instance with its relevant meta information - */ -export interface RouteWithMetaInformation { - /** - * Description of the route - */ - description: { - /** - * Short text of the description - title - */ - shortText?: string; - /** - * Text of the description - */ - text?: string; - }; - /** - * Name of the route - */ - name: string; - /** - * Instance of the route - */ - route: SCAbstractRoute; -} - -/** - * A node with its relevant meta information - */ -export interface NodeWithMetaInformation { - /** - * Module the node belongs to - */ - module: string; - /** - * Type of the node - */ - type: string; -} - -/** - * A map of nodes indexed by their name - */ -export interface NodesWithMetaInformation { - /** - * Index signature - */ - [k: string]: NodeWithMetaInformation; -}