mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-09 10:12:47 +00:00
185 lines
4.8 KiB
TypeScript
185 lines
4.8 KiB
TypeScript
/*
|
|
* Copyright (C) 2018-2019 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 <https://www.gnu.org/licenses/>.
|
|
*/
|
|
import {Logger} from '@openstapps/logger';
|
|
import {existsSync, mkdir, PathLike, readFile, unlink, writeFile} from 'fs';
|
|
import * as glob from 'glob';
|
|
import {Schema as JSONSchema, ValidationError} from 'jsonschema';
|
|
import {platform} from 'os';
|
|
import {join, sep} from 'path';
|
|
import {Definition} from 'ts-json-schema-generator';
|
|
import {Application, ProjectReflection} from 'typedoc';
|
|
import {promisify} from 'util';
|
|
|
|
export const logger = new Logger();
|
|
|
|
export const globPromisified = promisify(glob);
|
|
export const mkdirPromisified = promisify(mkdir);
|
|
export const readFilePromisified = promisify(readFile);
|
|
export const writeFilePromisified = promisify(writeFile);
|
|
export const unlinkPromisified = promisify(unlink);
|
|
|
|
/**
|
|
* 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: {
|
|
errorNames: Error[];
|
|
method: string;
|
|
obligatoryParameters: {
|
|
[k: string]: string;
|
|
}
|
|
requestBodyName: string;
|
|
responseBodyName: string;
|
|
statusCodeSuccess: number;
|
|
urlFragment: string;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/**
|
|
* A schema with definitions
|
|
*/
|
|
interface SchemaWithDefinitions extends JSONSchema {
|
|
definitions: { [name: string]: Definition };
|
|
}
|
|
|
|
/**
|
|
* An expectable error
|
|
*/
|
|
export type ExpectableValidationError = ValidationError & { expected: boolean };
|
|
|
|
/**
|
|
* A map of files and their expectable validation errors
|
|
*/
|
|
export interface ExpectableValidationErrors {
|
|
[fileName: string]: ExpectableValidationError[];
|
|
}
|
|
|
|
/**
|
|
* Get a project reflection from a path
|
|
*
|
|
* @param srcPath Path to get reflection from
|
|
*/
|
|
export function getProjectReflection(srcPath: PathLike): ProjectReflection {
|
|
logger.info(`Generating project reflection for ${srcPath.toString()}.`);
|
|
|
|
const tsconfigPath = getTsconfigPath(srcPath.toString());
|
|
|
|
// initialize new Typedoc application
|
|
const app = new Application({
|
|
excludeExternals: true,
|
|
includeDeclarations: true,
|
|
module: 'commonjs',
|
|
tsconfig: join(tsconfigPath, 'tsconfig.json'),
|
|
});
|
|
|
|
let inputFilePath = srcPath;
|
|
if (inputFilePath === tsconfigPath) {
|
|
inputFilePath = join(tsconfigPath, 'src');
|
|
}
|
|
|
|
// get input files
|
|
const inputFiles = app.expandInputFiles([inputFilePath.toString()]);
|
|
|
|
// get project reflection from input files
|
|
const result = app.convert(inputFiles);
|
|
|
|
if (typeof result === 'undefined') {
|
|
throw new Error('Project reflection could not be generated.');
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check if a schema has definitions
|
|
*
|
|
* @param schema Schema to check
|
|
*/
|
|
export function isSchemaWithDefinitions(schema: JSONSchema): schema is SchemaWithDefinitions {
|
|
return typeof schema.definitions !== 'undefined';
|
|
}
|
|
|
|
/**
|
|
* Get path that contains a tsconfig.json
|
|
*
|
|
* @param startPath Path from where to start searching "upwards"
|
|
*/
|
|
export function getTsconfigPath(startPath: string): string {
|
|
let tsconfigPath = startPath;
|
|
|
|
// see https://stackoverflow.com/questions/9652043/identifying-the-file-system-root-with-node-js
|
|
const root = (platform() === 'win32') ? process.cwd().split(sep)[0] : '/';
|
|
|
|
// repeat until a tsconfig.json is found
|
|
while (!existsSync(join(tsconfigPath, 'tsconfig.json'))) {
|
|
if (tsconfigPath === root) {
|
|
throw new Error(`Reached file system root ${root} while searching for 'tsconfig.json' in ${startPath}!`);
|
|
}
|
|
|
|
// pop last directory
|
|
const tsconfigPathParts = tsconfigPath.split(sep);
|
|
tsconfigPathParts.pop();
|
|
tsconfigPath = tsconfigPathParts.join(sep);
|
|
}
|
|
|
|
logger.info(`Using 'tsconfig.json' from ${tsconfigPath}.`);
|
|
|
|
return tsconfigPath;
|
|
}
|