mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-21 00:52:55 +00:00
feat: migrate to esm
This commit is contained in:
26
packages/core-tools/src/better-ajv-errors.d.ts
vendored
Normal file
26
packages/core-tools/src/better-ajv-errors.d.ts
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
declare module 'better-ajv-errors' {
|
||||
import type { ErrorObject } from 'ajv';
|
||||
|
||||
export interface IOutputError {
|
||||
start: { line: number; column: number; offset: number };
|
||||
// Optional for required
|
||||
end?: { line: number; column: number; offset: number };
|
||||
error: string;
|
||||
suggestion?: string;
|
||||
}
|
||||
|
||||
export interface IInputOptions {
|
||||
format?: 'cli' | 'js';
|
||||
indent?: number | null;
|
||||
|
||||
/** Raw JSON used when highlighting error location */
|
||||
json?: string | null;
|
||||
}
|
||||
|
||||
export default function <S, T, Options extends IInputOptions>(
|
||||
schema: S,
|
||||
data: T,
|
||||
errors: Array<ErrorObject>,
|
||||
options?: Options
|
||||
): Options extends { format: 'js' } ? Array<IOutputError> : string;
|
||||
}
|
||||
@@ -17,16 +17,17 @@ import {Command} from 'commander';
|
||||
import {existsSync, readFileSync, writeFileSync} from 'fs';
|
||||
import {copy} from 'fs-extra';
|
||||
import path from 'path';
|
||||
import {mkdirPromisified, readFilePromisified} from './common';
|
||||
import {lightweightDefinitionsFromPath, lightweightProjectFromPath} from './easy-ast/easy-ast';
|
||||
import {pack} from './pack';
|
||||
import {openapi3Template} from './resources/openapi-303-template';
|
||||
import {gatherRouteInformation, generateOpenAPIForRoute} from './routes';
|
||||
import {Converter, getValidatableTypesInPath} from './schema';
|
||||
import {createDiagram, createDiagramFromString} from './uml/create-diagram';
|
||||
import {UMLConfig} from './uml/uml-config';
|
||||
import {capitalize} from './util/string';
|
||||
import {validateFiles, writeReport} from './validate';
|
||||
import {mkdirPromisified, readFilePromisified} from './common.js';
|
||||
import {lightweightDefinitionsFromPath, lightweightProjectFromPath} from './easy-ast/easy-ast.js';
|
||||
import {pack} from './pack.js';
|
||||
import {openapi3Template} from './resources/openapi-303-template.js';
|
||||
import {gatherRouteInformation, generateOpenAPIForRoute} from './routes.js';
|
||||
import {Converter, getValidatableTypesInPath} from './schema.js';
|
||||
import {createDiagram, createDiagramFromString} from './uml/create-diagram.js';
|
||||
import {UMLConfig} from './uml/uml-config.js';
|
||||
import {capitalize} from './util/string.js';
|
||||
import {validateFiles, writeReport} from './validate.js';
|
||||
import {fileURLToPath} from "url";
|
||||
|
||||
// handle unhandled promise rejections
|
||||
process.on('unhandledRejection', async (reason: unknown) => {
|
||||
@@ -40,7 +41,7 @@ process.on('unhandledRejection', async (reason: unknown) => {
|
||||
const commander = new Command('openstapps-core-tools');
|
||||
|
||||
// eslint-disable-next-line unicorn/prefer-module
|
||||
commander.version(JSON.parse(readFileSync(path.resolve(__dirname, '..', 'package.json')).toString()).version);
|
||||
commander.version(JSON.parse(readFileSync(path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'package.json')).toString()).version);
|
||||
|
||||
commander.command('prototype <srcBundle> <out>').action(async (sourcePath, out) => {
|
||||
const files = lightweightProjectFromPath(sourcePath);
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
*/
|
||||
import {Logger} from '@openstapps/logger';
|
||||
import {existsSync, mkdir, readFile, unlink, writeFile} from 'fs';
|
||||
import {Glob} from 'glob';
|
||||
import glob from 'glob';
|
||||
import {platform} from 'os';
|
||||
import {promisify} from 'util';
|
||||
import path from 'path';
|
||||
|
||||
export const globPromisified = promisify(Glob);
|
||||
export const globPromisified = promisify(glob.Glob);
|
||||
export const mkdirPromisified = promisify(mkdir);
|
||||
export const readFilePromisified = promisify(readFile);
|
||||
export const writeFilePromisified = promisify(writeFile);
|
||||
|
||||
@@ -12,34 +12,9 @@
|
||||
* 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 {
|
||||
ArrayTypeNode,
|
||||
ClassDeclaration,
|
||||
ClassElement,
|
||||
EnumDeclaration,
|
||||
Identifier,
|
||||
InterfaceDeclaration,
|
||||
isArrayTypeNode,
|
||||
isClassDeclaration,
|
||||
isComputedPropertyName,
|
||||
isEnumDeclaration,
|
||||
isInterfaceDeclaration,
|
||||
isPropertyDeclaration,
|
||||
isPropertySignature,
|
||||
isTypeAliasDeclaration,
|
||||
isTypeReferenceNode,
|
||||
NodeArray,
|
||||
PropertyDeclaration,
|
||||
PropertyName,
|
||||
PropertySignature,
|
||||
TypeAliasDeclaration,
|
||||
TypeElement,
|
||||
TypeNode,
|
||||
TypeReferenceNode,
|
||||
} from 'typescript';
|
||||
import * as ts from 'typescript';
|
||||
import {cleanupEmpty} from '../util/collections';
|
||||
import {LightweightComment} from './types/lightweight-comment';
|
||||
import {cleanupEmpty} from '../util/collections.js';
|
||||
import {LightweightComment} from './types/lightweight-comment.js';
|
||||
|
||||
/** @internal */
|
||||
export function extractComment(node: ts.Node): LightweightComment | undefined {
|
||||
@@ -70,14 +45,14 @@ export function extractComment(node: ts.Node): LightweightComment | undefined {
|
||||
|
||||
/** @internal */
|
||||
export function isProperty(
|
||||
node: ClassElement | TypeElement,
|
||||
): node is PropertyDeclaration | PropertySignature {
|
||||
return isPropertyDeclaration(node) || isPropertySignature(node);
|
||||
node: ts.ClassElement | ts.TypeElement,
|
||||
): node is ts.PropertyDeclaration | ts.PropertySignature {
|
||||
return ts.isPropertyDeclaration(node) || ts.isPropertySignature(node);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function filterNodeTo<T extends ts.Node, S extends T>(
|
||||
node: NodeArray<T>,
|
||||
node: ts.NodeArray<T>,
|
||||
check: (node: T) => node is S,
|
||||
): S[] {
|
||||
return node.filter(check);
|
||||
@@ -107,36 +82,36 @@ export function getModifiers(text: string, kind: string): string[] {
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function resolvePropertyName(name?: PropertyName): string | undefined {
|
||||
export function resolvePropertyName(name?: ts.PropertyName): string | undefined {
|
||||
return name === undefined
|
||||
? undefined
|
||||
: isComputedPropertyName(name)
|
||||
: ts.isComputedPropertyName(name)
|
||||
? 'UNSUPPORTED_IDENTIFIER_TYPE'
|
||||
: name.getText();
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function resolveTypeName(type?: TypeNode): string | undefined {
|
||||
export function resolveTypeName(type?: ts.TypeNode): string | undefined {
|
||||
// @ts-expect-error typeName exists in reality
|
||||
return type?.typeName?.escapedText ?? type?.typeName?.right?.escapedText;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isArrayLikeType(typeNode?: TypeNode): typeNode is ArrayTypeNode | TypeReferenceNode {
|
||||
return typeNode !== undefined && (isArrayTypeNode(typeNode) || isArrayReference(typeNode));
|
||||
export function isArrayLikeType(typeNode?: ts.TypeNode): typeNode is ts.ArrayTypeNode | ts.TypeReferenceNode {
|
||||
return typeNode !== undefined && (ts.isArrayTypeNode(typeNode) || isArrayReference(typeNode));
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isArrayReference(typeNode: TypeNode): boolean {
|
||||
return isTypeReferenceNode(typeNode) && (typeNode.typeName as Identifier).escapedText === 'Array';
|
||||
export function isArrayReference(typeNode: ts.TypeNode): boolean {
|
||||
return ts.isTypeReferenceNode(typeNode) && (typeNode.typeName as ts.Identifier).escapedText === 'Array';
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isClassLikeNode(node: ts.Node): node is ClassDeclaration | InterfaceDeclaration {
|
||||
return isClassDeclaration(node) || isInterfaceDeclaration(node);
|
||||
export function isClassLikeNode(node: ts.Node): node is ts.ClassDeclaration | ts.InterfaceDeclaration {
|
||||
return ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function isEnumLikeNode(node: ts.Node): node is EnumDeclaration | TypeAliasDeclaration {
|
||||
return isEnumDeclaration(node) || isTypeAliasDeclaration(node);
|
||||
export function isEnumLikeNode(node: ts.Node): node is ts.EnumDeclaration | ts.TypeAliasDeclaration {
|
||||
return ts.isEnumDeclaration(node) || ts.isTypeAliasDeclaration(node);
|
||||
}
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
* 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 {TypeFlags} from 'typescript';
|
||||
import {LightweightAliasDefinition} from './types/lightweight-alias-definition';
|
||||
import {LightweightClassDefinition} from './types/lightweight-class-definition';
|
||||
import {LightweightDefinition} from './types/lightweight-definition';
|
||||
import {LightweightDefinitionKind} from './types/lightweight-definition-kind';
|
||||
import {LightweightProject} from './types/lightweight-project';
|
||||
import {LightweightType} from './types/lightweight-type';
|
||||
import {keyBy} from "@openstapps/collection-utils/lib/key-by";
|
||||
import ts from 'typescript';
|
||||
import {LightweightAliasDefinition} from './types/lightweight-alias-definition.js';
|
||||
import {LightweightClassDefinition} from './types/lightweight-class-definition.js';
|
||||
import {LightweightDefinition} from './types/lightweight-definition.js';
|
||||
import {LightweightDefinitionKind} from './types/lightweight-definition-kind.js';
|
||||
import {LightweightProject} from './types/lightweight-project.js';
|
||||
import {LightweightType} from './types/lightweight-type.js';
|
||||
import {keyBy} from "@openstapps/collection-utils/lib/key-by.js";
|
||||
|
||||
/**
|
||||
* Creates a printable name of a type
|
||||
@@ -46,28 +46,28 @@ export function definitionsOf(project: LightweightProject): Record<string, Light
|
||||
return keyBy(Object.values(project).flatMap(Object.values), it => it.name);
|
||||
}
|
||||
|
||||
export function isPrimitiveType(type: {flags: TypeFlags}): boolean {
|
||||
return (type.flags & TypeFlags.NonPrimitive) === 0;
|
||||
export function isPrimitiveType(type: { flags: ts.TypeFlags }): boolean {
|
||||
return (type.flags & ts.TypeFlags.NonPrimitive) === 0;
|
||||
}
|
||||
|
||||
export function isLiteralType(type: {flags: TypeFlags}): boolean {
|
||||
return (type.flags & TypeFlags.Literal) !== 0;
|
||||
export function isLiteralType(type: { flags: ts.TypeFlags }): boolean {
|
||||
return (type.flags & ts.TypeFlags.Literal) !== 0;
|
||||
}
|
||||
|
||||
export function isEnumLiteralType(type: {flags: TypeFlags}): boolean {
|
||||
return (type.flags & TypeFlags.EnumLiteral) !== 0;
|
||||
export function isEnumLiteralType(type: { flags: ts.TypeFlags }): boolean {
|
||||
return (type.flags & ts.TypeFlags.EnumLiteral) !== 0;
|
||||
}
|
||||
|
||||
export function isStringLiteralType(type: {flags: TypeFlags}): boolean {
|
||||
return (type.flags & TypeFlags.StringLiteral) !== 0;
|
||||
export function isStringLiteralType(type: { flags: ts.TypeFlags }): boolean {
|
||||
return (type.flags & ts.TypeFlags.StringLiteral) !== 0;
|
||||
}
|
||||
|
||||
export function isUnionOrIntersectionType(type: {flags: TypeFlags}): boolean {
|
||||
return (type.flags & TypeFlags.UnionOrIntersection) !== 0;
|
||||
export function isUnionOrIntersectionType(type: { flags: ts.TypeFlags }): boolean {
|
||||
return (type.flags & ts.TypeFlags.UnionOrIntersection) !== 0;
|
||||
}
|
||||
|
||||
export function isUnionType(type: {flags: TypeFlags}): boolean {
|
||||
return (type.flags & TypeFlags.Union) !== 0;
|
||||
export function isUnionType(type: { flags: ts.TypeFlags }): boolean {
|
||||
return (type.flags & ts.TypeFlags.Union) !== 0;
|
||||
}
|
||||
|
||||
export function isLightweightClass(node?: LightweightDefinition): node is LightweightClassDefinition {
|
||||
@@ -78,6 +78,6 @@ export function isLightweightEnum(node?: LightweightDefinition): node is Lightwe
|
||||
return node?.kind === LightweightDefinitionKind.ALIAS_LIKE;
|
||||
}
|
||||
|
||||
export function isTypeVariable(type: {flags: TypeFlags}): boolean {
|
||||
return (type.flags & TypeFlags.TypeVariable) !== 0;
|
||||
export function isTypeVariable(type: { flags: ts.TypeFlags }): boolean {
|
||||
return (type.flags & ts.TypeFlags.TypeVariable) !== 0;
|
||||
}
|
||||
|
||||
@@ -13,33 +13,9 @@
|
||||
* 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 * as ts from 'typescript';
|
||||
import {
|
||||
ClassDeclaration,
|
||||
ClassElement,
|
||||
EnumDeclaration,
|
||||
InterfaceDeclaration,
|
||||
isArrayTypeNode,
|
||||
isClassDeclaration,
|
||||
isEnumDeclaration,
|
||||
isIndexSignatureDeclaration,
|
||||
isPropertyDeclaration,
|
||||
isTypeLiteralNode,
|
||||
isTypeReferenceNode,
|
||||
NodeArray,
|
||||
Program,
|
||||
SourceFile,
|
||||
SyntaxKind,
|
||||
Type,
|
||||
TypeAliasDeclaration,
|
||||
TypeChecker,
|
||||
TypeElement,
|
||||
TypeFlags,
|
||||
TypeLiteralNode,
|
||||
TypeNode,
|
||||
} from 'typescript';
|
||||
import {cleanupEmpty, mapNotNil, rejectNil} from '../util/collections';
|
||||
import {expandPathToFilesSync} from '../util/io';
|
||||
import ts from 'typescript';
|
||||
import {cleanupEmpty, mapNotNil, rejectNil} from '../util/collections.js';
|
||||
import {expandPathToFilesSync} from '../util/io.js';
|
||||
import {
|
||||
extractComment,
|
||||
filterChildrenTo,
|
||||
@@ -51,19 +27,19 @@ import {
|
||||
isProperty,
|
||||
resolvePropertyName,
|
||||
resolveTypeName,
|
||||
} from './ast-internal-util';
|
||||
import {isEnumLiteralType, isTypeVariable} from './ast-util';
|
||||
import {LightweightAliasDefinition} from './types/lightweight-alias-definition';
|
||||
import {LightweightClassDefinition} from './types/lightweight-class-definition';
|
||||
import {LightweightDefinition} from './types/lightweight-definition';
|
||||
import {LightweightDefinitionKind} from './types/lightweight-definition-kind';
|
||||
import {LightweightProject} from './types/lightweight-project';
|
||||
import {LightweightType} from './types/lightweight-type';
|
||||
} from './ast-internal-util.js';
|
||||
import {isEnumLiteralType, isTypeVariable} from './ast-util.js';
|
||||
import {LightweightAliasDefinition} from './types/lightweight-alias-definition.js';
|
||||
import {LightweightClassDefinition} from './types/lightweight-class-definition.js';
|
||||
import {LightweightDefinition} from './types/lightweight-definition.js';
|
||||
import {LightweightDefinitionKind} from './types/lightweight-definition-kind.js';
|
||||
import {LightweightProject} from './types/lightweight-project.js';
|
||||
import {LightweightType} from './types/lightweight-type.js';
|
||||
import path from 'path';
|
||||
import {LightweightProperty} from './types/lightweight-property';
|
||||
import {mapValues} from "@openstapps/collection-utils/lib/map-values";
|
||||
import {groupBy} from "@openstapps/collection-utils/lib/group-by";
|
||||
import {keyBy} from "@openstapps/collection-utils/lib/key-by";
|
||||
import {LightweightProperty} from './types/lightweight-property.js';
|
||||
import {mapValues} from "@openstapps/collection-utils/lib/map-values.js";
|
||||
import {groupBy} from "@openstapps/collection-utils/lib/group-by.js";
|
||||
import {keyBy} from "@openstapps/collection-utils/lib/key-by.js";
|
||||
|
||||
/**
|
||||
* Convert a TypeScript project to a lightweight Type-AST representation of the project
|
||||
@@ -95,11 +71,11 @@ export function lightweightDefinitionsFromPath(
|
||||
* Reads the reflection model and converts it into a flatter, easier to handle model
|
||||
*/
|
||||
class LightweightDefinitionBuilder {
|
||||
readonly program: Program;
|
||||
readonly program: ts.Program;
|
||||
|
||||
readonly sourceFiles: readonly SourceFile[];
|
||||
readonly sourceFiles: readonly ts.SourceFile[];
|
||||
|
||||
readonly typeChecker: TypeChecker;
|
||||
readonly typeChecker: ts.TypeChecker;
|
||||
|
||||
constructor(sourcePath: string | string[], readonly includeComments: boolean) {
|
||||
const rootNames = Array.isArray(sourcePath)
|
||||
@@ -125,13 +101,13 @@ class LightweightDefinitionBuilder {
|
||||
this.sourceFiles = mapNotNil(this.program.getRootFileNames(), it => this.program.getSourceFile(it));
|
||||
}
|
||||
|
||||
private convertAliasLike(enumLike: EnumDeclaration | TypeAliasDeclaration): LightweightAliasDefinition {
|
||||
private convertAliasLike(enumLike: ts.EnumDeclaration | ts.TypeAliasDeclaration): LightweightAliasDefinition {
|
||||
return cleanupEmpty({
|
||||
comment: this.includeComments ? extractComment(enumLike) : undefined,
|
||||
name: enumLike.name.getText() ?? 'ERROR',
|
||||
kind: LightweightDefinitionKind.ALIAS_LIKE,
|
||||
modifiers: getModifiers(enumLike.getText(), isEnumDeclaration(enumLike) ? 'enum' : 'type'),
|
||||
type: isEnumDeclaration(enumLike)
|
||||
modifiers: getModifiers(enumLike.getText(), ts.isEnumDeclaration(enumLike) ? 'enum' : 'type'),
|
||||
type: ts.isEnumDeclaration(enumLike)
|
||||
? enumLike.members.length > 0
|
||||
? {
|
||||
flags: 1_048_576,
|
||||
@@ -142,7 +118,7 @@ class LightweightDefinitionBuilder {
|
||||
});
|
||||
}
|
||||
|
||||
private convertClassLike(classLike: ClassDeclaration | InterfaceDeclaration): LightweightClassDefinition {
|
||||
private convertClassLike(classLike: ts.ClassDeclaration | ts.InterfaceDeclaration): LightweightClassDefinition {
|
||||
const heritages = mapValues(
|
||||
groupBy([...(classLike.heritageClauses!)], it => it.token.toString()),
|
||||
heritages => heritages.flatMap(it => it.types),
|
||||
@@ -152,15 +128,15 @@ class LightweightDefinitionBuilder {
|
||||
comment: this.includeComments ? extractComment(classLike) : undefined,
|
||||
name: classLike.name?.escapedText ?? 'ERROR',
|
||||
kind: LightweightDefinitionKind.CLASS_LIKE,
|
||||
modifiers: getModifiers(classLike.getText(), isClassDeclaration(classLike) ? 'class' : 'interface'),
|
||||
modifiers: getModifiers(classLike.getText(), ts.isClassDeclaration(classLike) ? 'class' : 'interface'),
|
||||
extendedDefinitions: heritages[ts.SyntaxKind.ExtendsKeyword]?.map(it => this.lightweightTypeAtNode(it)),
|
||||
implementedDefinitions: heritages[ts.SyntaxKind.ImplementsKeyword]?.map(it =>
|
||||
this.lightweightTypeAtNode(it),
|
||||
),
|
||||
indexSignatures: keyBy(
|
||||
filterNodeTo(
|
||||
classLike.members as NodeArray<ClassElement | TypeElement>,
|
||||
isIndexSignatureDeclaration,
|
||||
classLike.members as ts.NodeArray<ts.ClassElement | ts.TypeElement>,
|
||||
ts.isIndexSignatureDeclaration,
|
||||
).map(indexSignature =>
|
||||
cleanupEmpty({
|
||||
name:
|
||||
@@ -183,15 +159,15 @@ class LightweightDefinitionBuilder {
|
||||
});
|
||||
}
|
||||
|
||||
collectProperties(members: NodeArray<ClassElement | TypeElement>): Record<string, LightweightProperty> {
|
||||
collectProperties(members: ts.NodeArray<ts.ClassElement | ts.TypeElement>): Record<string, LightweightProperty> {
|
||||
return keyBy(
|
||||
filterNodeTo(members as NodeArray<ClassElement | TypeElement>, isProperty).map(property =>
|
||||
filterNodeTo(members as ts.NodeArray<ts.ClassElement | ts.TypeElement>, isProperty).map(property =>
|
||||
cleanupEmpty({
|
||||
comment: this.includeComments ? extractComment(property) : undefined,
|
||||
name: resolvePropertyName(property.name) ?? property.getText(),
|
||||
type: this.lightweightTypeAtNode(property),
|
||||
properties: this.collectProperties((property.type as TypeLiteralNode)?.members),
|
||||
optional: isPropertyDeclaration(property)
|
||||
properties: this.collectProperties((property.type as ts.TypeLiteralNode)?.members),
|
||||
optional: ts.isPropertyDeclaration(property)
|
||||
? property.questionToken === undefined
|
||||
? undefined
|
||||
: true
|
||||
@@ -208,12 +184,12 @@ class LightweightDefinitionBuilder {
|
||||
return this.lightweightTypeFromType(type, this.typeChecker.typeToTypeNode(type, node, undefined));
|
||||
}
|
||||
|
||||
private lightweightTypeFromType(type: ts.Type, typeNode?: TypeNode): LightweightType {
|
||||
if (typeNode?.kind === SyntaxKind.ConditionalType) {
|
||||
return {value: 'UNSUPPORTED_CONDITIONAL_TYPE', flags: TypeFlags.Unknown};
|
||||
private lightweightTypeFromType(type: ts.Type, typeNode?: ts.TypeNode): LightweightType {
|
||||
if (typeNode?.kind === ts.SyntaxKind.ConditionalType) {
|
||||
return {value: 'UNSUPPORTED_CONDITIONAL_TYPE', flags: ts.TypeFlags.Unknown};
|
||||
}
|
||||
if (isArrayLikeType(typeNode)) {
|
||||
const elementType = isArrayTypeNode(typeNode) ? typeNode.elementType : typeNode.typeArguments?.[0]!;
|
||||
const elementType = ts.isArrayTypeNode(typeNode) ? typeNode.elementType : typeNode.typeArguments?.[0]!;
|
||||
const out = this.lightweightTypeFromType(
|
||||
this.typeChecker.getTypeFromTypeNode(elementType),
|
||||
elementType,
|
||||
@@ -222,8 +198,8 @@ class LightweightDefinitionBuilder {
|
||||
|
||||
return out;
|
||||
}
|
||||
const isReference = typeNode !== undefined && isTypeReferenceNode(typeNode) && !isEnumLiteralType(type);
|
||||
const isTypeLiteral = typeNode !== undefined && isTypeLiteralNode(typeNode);
|
||||
const isReference = typeNode !== undefined && ts.isTypeReferenceNode(typeNode) && !isEnumLiteralType(type);
|
||||
const isTypeLiteral = typeNode !== undefined && ts.isTypeLiteralNode(typeNode);
|
||||
// @ts-expect-error intrinsic name & value exist
|
||||
const intrinsicName = (type.intrinsicName ?? type.value) as string | undefined;
|
||||
|
||||
@@ -239,7 +215,7 @@ class LightweightDefinitionBuilder {
|
||||
.getApparentType(type)
|
||||
// @ts-expect-error resolvedTypeArguments exits
|
||||
?.resolvedTypeArguments?.filter(it => !it.isThisType)
|
||||
?.map((it: Type) => this.lightweightTypeFromType(it)),
|
||||
?.map((it: ts.Type) => this.lightweightTypeFromType(it)),
|
||||
specificationTypes:
|
||||
type.isUnionOrIntersection() && !isReference
|
||||
? type.types.map(it =>
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {LightweightDefinitionBase} from './lightweight-definition';
|
||||
import {LightweightDefinitionKind} from './lightweight-definition-kind';
|
||||
import {LightweightType} from './lightweight-type';
|
||||
import {LightweightDefinitionBase} from './lightweight-definition.js';
|
||||
import {LightweightDefinitionKind} from './lightweight-definition-kind.js';
|
||||
import {LightweightType} from './lightweight-type.js';
|
||||
/**
|
||||
* Represents an enum definition
|
||||
*/
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {LightweightDefinitionBase} from './lightweight-definition';
|
||||
import {LightweightDefinitionKind} from './lightweight-definition-kind';
|
||||
import {LightweightIndexSignature, LightweightProperty} from './lightweight-property';
|
||||
import {LightweightType} from './lightweight-type';
|
||||
import {LightweightDefinitionBase} from './lightweight-definition.js';
|
||||
import {LightweightDefinitionKind} from './lightweight-definition-kind.js';
|
||||
import {LightweightIndexSignature, LightweightProperty} from './lightweight-property.js';
|
||||
import {LightweightType} from './lightweight-type.js';
|
||||
|
||||
/**
|
||||
* Represents a class definition
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
* 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 {LightweightDefinitionKind} from './lightweight-definition-kind';
|
||||
import {LightweightComment} from './lightweight-comment';
|
||||
import {LightweightClassDefinition} from './lightweight-class-definition';
|
||||
import {LightweightAliasDefinition} from './lightweight-alias-definition';
|
||||
import {LightweightDefinitionKind} from './lightweight-definition-kind.js';
|
||||
import {LightweightComment} from './lightweight-comment.js';
|
||||
import {LightweightClassDefinition} from './lightweight-class-definition.js';
|
||||
import {LightweightAliasDefinition} from './lightweight-alias-definition.js';
|
||||
|
||||
export type LightweightDefinition = LightweightClassDefinition | LightweightAliasDefinition;
|
||||
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
* 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 {mapNotNil} from '../../util/collections';
|
||||
import {definitionsOf, isLightweightClass} from '../ast-util';
|
||||
import {lightweightProjectFromPath} from '../easy-ast';
|
||||
import {LightweightClassDefinition} from './lightweight-class-definition';
|
||||
import {LightweightDefinition} from './lightweight-definition';
|
||||
import {mapNotNil} from '../../util/collections.js';
|
||||
import {definitionsOf, isLightweightClass} from '../ast-util.js';
|
||||
import {lightweightProjectFromPath} from '../easy-ast.js';
|
||||
import {LightweightClassDefinition} from './lightweight-class-definition.js';
|
||||
import {LightweightDefinition} from './lightweight-definition.js';
|
||||
|
||||
/**
|
||||
* Build an index for a lightweight project
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
* 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 {LightweightComment} from './lightweight-comment';
|
||||
import {LightweightType} from './lightweight-type';
|
||||
import {LightweightComment} from './lightweight-comment.js';
|
||||
import {LightweightType} from './lightweight-type.js';
|
||||
|
||||
/**
|
||||
* Represents a property definition
|
||||
|
||||
@@ -17,8 +17,8 @@ import {Logger} from '@openstapps/logger';
|
||||
import del from 'del';
|
||||
import {existsSync} from 'fs';
|
||||
import {cwd} from 'process';
|
||||
import {globPromisified, readFilePromisified, unlinkPromisified, writeFilePromisified} from './common';
|
||||
import {JavaScriptModule} from './types/pack';
|
||||
import {globPromisified, readFilePromisified, unlinkPromisified, writeFilePromisified} from './common.js';
|
||||
import {JavaScriptModule} from './types/pack.js';
|
||||
import path from 'path';
|
||||
|
||||
const PACK_IDENTIFIER = '/* PACKED BY @openstapps/pack */';
|
||||
|
||||
@@ -12,15 +12,14 @@
|
||||
* 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 {assign, filter, map} from 'lodash';
|
||||
import {OpenAPIV3} from 'openapi-types';
|
||||
import {isLightweightClass} from './easy-ast/ast-util';
|
||||
import {LightweightProjectWithIndex} from './easy-ast/types/lightweight-project';
|
||||
import {RouteInstanceWithMeta, RouteWithMetaInformation} from './types/routes';
|
||||
import {rejectNil} from './util/collections';
|
||||
import {capitalize} from './util/string';
|
||||
import {isLightweightClass} from './easy-ast/ast-util.js';
|
||||
import {LightweightProjectWithIndex} from './easy-ast/types/lightweight-project.js';
|
||||
import {RouteInstanceWithMeta, RouteWithMetaInformation} from './types/routes.js';
|
||||
import {rejectNil} from './util/collections.js';
|
||||
import {capitalize} from './util/string.js';
|
||||
import path from 'path';
|
||||
import {lightweightProjectFromPath} from './easy-ast/easy-ast';
|
||||
import {lightweightProjectFromPath} from './easy-ast/easy-ast.js';
|
||||
|
||||
/**
|
||||
* Gather relevant information of routes
|
||||
@@ -34,7 +33,7 @@ export async function gatherRouteInformation(path: string): Promise<RouteWithMet
|
||||
// find all classes that implement the SCAbstractRoute
|
||||
return rejectNil(
|
||||
await Promise.all(
|
||||
map(filter(project.definitions, isLightweightClass), async node => {
|
||||
Object.values(project.definitions).filter(isLightweightClass).map(async node => {
|
||||
if (!node.extendedDefinitions?.some(it => it.referenceName === 'SCAbstractRoute')) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -47,7 +46,7 @@ export async function gatherRouteInformation(path: string): Promise<RouteWithMet
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
instantiatedRoute.errorNames.map(async (error: any) =>
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
assign((await project.instantiateDefinitionByName(error.name)) as object, {name: error.name}),
|
||||
Object.assign((await project.instantiateDefinitionByName(error.name)) as object, {name: error.name}),
|
||||
),
|
||||
);
|
||||
instantiatedRoute.responseBodyDescription =
|
||||
|
||||
@@ -14,17 +14,16 @@
|
||||
*/
|
||||
import Ajv from 'ajv';
|
||||
import {JSONSchema7 as JSONSchema} from 'json-schema';
|
||||
import {chain} from 'lodash';
|
||||
import {Config, DEFAULT_CONFIG, Definition, SchemaGenerator} from 'ts-json-schema-generator';
|
||||
import {createFormatter} from 'ts-json-schema-generator/dist/factory/formatter';
|
||||
import {createParser} from 'ts-json-schema-generator/dist/factory/parser';
|
||||
import {createProgram} from 'ts-json-schema-generator/dist/factory/program';
|
||||
import {getTsconfigPath} from './common';
|
||||
import {definitionsOf} from './easy-ast/ast-util';
|
||||
import {lightweightProjectFromPath} from './easy-ast/easy-ast';
|
||||
import {isSchemaWithDefinitions} from './util/guards';
|
||||
import {createFormatter} from 'ts-json-schema-generator';
|
||||
import {createParser} from 'ts-json-schema-generator';
|
||||
import {createProgram} from 'ts-json-schema-generator';
|
||||
import {getTsconfigPath} from './common.js';
|
||||
import {definitionsOf} from './easy-ast/ast-util.js';
|
||||
import {lightweightProjectFromPath} from './easy-ast/easy-ast.js';
|
||||
import {isSchemaWithDefinitions} from './util/guards.js';
|
||||
import path from 'path';
|
||||
import re2 from './types/re2';
|
||||
import re2 from './types/re2.js';
|
||||
|
||||
/**
|
||||
* StAppsCore converter
|
||||
@@ -40,7 +39,7 @@ export class Converter {
|
||||
/**
|
||||
* Schema validator instance
|
||||
*/
|
||||
private readonly schemaValidator: Ajv;
|
||||
private readonly schemaValidator: Ajv.default;
|
||||
|
||||
/**
|
||||
* Create a new converter
|
||||
@@ -66,9 +65,7 @@ export class Converter {
|
||||
this.generator = new SchemaGenerator(program, createParser(program, config), createFormatter(config));
|
||||
|
||||
// create Ajv instance
|
||||
this.schemaValidator = new Ajv({code: {regExp: re2}});
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires,unicorn/prefer-module
|
||||
this.schemaValidator.addMetaSchema(require('ajv/lib/refs/json-schema-draft-06.json'));
|
||||
this.schemaValidator = new Ajv.default({code: {regExp: re2}});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,8 +109,7 @@ export class Converter {
|
||||
* Get a list of validatable types from an API extractor file
|
||||
*/
|
||||
export function getValidatableTypesInPath(path: string): string[] {
|
||||
return chain(definitionsOf(lightweightProjectFromPath(path)))
|
||||
return Object.values(definitionsOf(lightweightProjectFromPath(path)))
|
||||
.filter(type => !!type.comment?.tags?.find(it => it.name === 'validatable'))
|
||||
.map(type => type.name)
|
||||
.value();
|
||||
}
|
||||
|
||||
@@ -15,14 +15,13 @@
|
||||
import {Logger} from '@openstapps/logger';
|
||||
import {createWriteStream} from 'fs';
|
||||
import * as request from 'got';
|
||||
import {forEach, map, isEmpty} from 'lodash';
|
||||
import {expandTypeValue, isLightweightClass, isUnionOrIntersectionType} from '../easy-ast/ast-util';
|
||||
import {LightweightAliasDefinition} from '../easy-ast/types/lightweight-alias-definition';
|
||||
import {LightweightClassDefinition} from '../easy-ast/types/lightweight-class-definition';
|
||||
import {LightweightDefinition} from '../easy-ast/types/lightweight-definition';
|
||||
import {LightweightProperty} from '../easy-ast/types/lightweight-property';
|
||||
import {LightweightType} from '../easy-ast/types/lightweight-type';
|
||||
import {UMLConfig} from './uml-config';
|
||||
import {expandTypeValue, isLightweightClass} from '../easy-ast/ast-util.js';
|
||||
import {LightweightAliasDefinition} from '../easy-ast/types/lightweight-alias-definition.js';
|
||||
import {LightweightClassDefinition} from '../easy-ast/types/lightweight-class-definition.js';
|
||||
import {LightweightDefinition} from '../easy-ast/types/lightweight-definition.js';
|
||||
import {LightweightProperty} from '../easy-ast/types/lightweight-property.js';
|
||||
import {LightweightType} from '../easy-ast/types/lightweight-type.js';
|
||||
import {UMLConfig} from './uml-config.js';
|
||||
|
||||
/**
|
||||
* Converts the lightweight class/enum definitions according to the configuration,
|
||||
@@ -39,7 +38,7 @@ export async function createDiagram(
|
||||
plantUmlBaseURL: string,
|
||||
): Promise<string> {
|
||||
// when non definitions were specified use all
|
||||
config.definitions = map(definitions, 'name');
|
||||
config.definitions = definitions.map(it => it.name);
|
||||
|
||||
// when providing definitions and either showing associations or inheritance the
|
||||
// inherited definitions will be added automatically
|
||||
@@ -54,9 +53,9 @@ export async function createDiagram(
|
||||
|
||||
// creates a UML definition for every specified definition name
|
||||
// however if no definitions were provided all definitions will be transformed
|
||||
const modelPlantUMLCode = map(
|
||||
definitions.filter(it => !config.definitions.includes(it.name)),
|
||||
definition =>
|
||||
const modelPlantUMLCode = definitions
|
||||
.filter(it => !config.definitions.includes(it.name))
|
||||
.map(definition =>
|
||||
isLightweightClass(definition)
|
||||
? createPlantUMLCodeForClass(config, definition)
|
||||
: createPlantUMLCodeForEnum(config, definition),
|
||||
@@ -152,18 +151,20 @@ function getReferenceTypes(type: LightweightType): string[] {
|
||||
types.push(type.referenceName);
|
||||
}
|
||||
|
||||
forEach(type.genericsTypes, specificType => {
|
||||
for (const value of getReferenceTypes(specificType)) {
|
||||
types.push(value);
|
||||
}
|
||||
});
|
||||
|
||||
if ((isUnionOrIntersectionType(type) && isEmpty(type.specificationTypes)) || type.isArray) {
|
||||
forEach(type.specificationTypes, specificType => {
|
||||
if (type.genericsTypes) {
|
||||
for (const specificType of type.genericsTypes) {
|
||||
for (const value of getReferenceTypes(specificType)) {
|
||||
types.push(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(type.specificationTypes)) {
|
||||
for (const specificType of type.specificationTypes) {
|
||||
for (const value of getReferenceTypes(specificType)) {
|
||||
types.push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return types;
|
||||
@@ -194,35 +195,39 @@ function createPlantUMLCodeForClass(config: UMLConfig, readerClass: LightweightC
|
||||
model += '{';
|
||||
|
||||
// add the properties to the definition body
|
||||
if (config.showProperties) {
|
||||
forEach(readerClass.properties, property => {
|
||||
if (config.showProperties && readerClass.properties) {
|
||||
for (const key in readerClass.properties) {
|
||||
const property = readerClass.properties[key];
|
||||
if (property.optional && !config.showOptionalProperties) {
|
||||
// don't show optional attributes
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
/*if (property.inherited && !config.showInheritedProperties) {
|
||||
// don't show inherited properties
|
||||
continue;
|
||||
}*/
|
||||
model += `\n\t${createPropertyLine(property)}`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// close the definition body
|
||||
model += '\n}\n';
|
||||
|
||||
// add associations from properties with references
|
||||
forEach(readerClass.properties, property => {
|
||||
const types: string[] = getReferenceTypes(property.type);
|
||||
for (const type of types) {
|
||||
if (config.showAssociations) {
|
||||
/*if (property.inherited && !config.showInheritedProperties) {
|
||||
continue;
|
||||
}*/
|
||||
model += `${readerClass.name} -up-> ${type} : ${property.name} >\n`;
|
||||
if (readerClass.properties) {
|
||||
for (const key in readerClass.properties) {
|
||||
const property = readerClass.properties[key];
|
||||
const types: string[] = getReferenceTypes(property.type);
|
||||
for (const type of types) {
|
||||
if (config.showAssociations) {
|
||||
/*if (property.inherited && !config.showInheritedProperties) {
|
||||
continue;
|
||||
}*/
|
||||
model += `${readerClass.name} -up-> ${type} : ${property.name} >\n`;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
@@ -237,10 +242,10 @@ function createPlantUMLCodeForEnum(config: UMLConfig, readerEnum: LightweightAli
|
||||
// create enum header
|
||||
let model = `enum ${readerEnum.name} {`;
|
||||
// add values
|
||||
if (config.showEnumValues) {
|
||||
forEach(readerEnum.type?.specificationTypes, value => {
|
||||
if (config.showEnumValues && readerEnum.type?.specificationTypes) {
|
||||
for (const value of readerEnum.type?.specificationTypes) {
|
||||
model += `\n\t${value.toString()}`;
|
||||
});
|
||||
}
|
||||
}
|
||||
model += '\n}\n';
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import {JSONSchema7 as JSONSchema} from 'json-schema';
|
||||
import {SchemaWithDefinitions} from '../types/schema';
|
||||
import {SchemaWithDefinitions} from '../types/schema.js';
|
||||
|
||||
/**
|
||||
* Guard for if a JSON schema is in fact a schema with definitions
|
||||
|
||||
@@ -17,14 +17,14 @@ import Ajv from 'ajv';
|
||||
import betterAjvErrors, {IOutputError} from 'better-ajv-errors';
|
||||
import {PathLike} from 'fs';
|
||||
import {JSONSchema7} from 'json-schema';
|
||||
import * as mustache from 'mustache';
|
||||
import mustache from 'mustache';
|
||||
import {Schema} from 'ts-json-schema-generator';
|
||||
import {globPromisified, readFilePromisified, writeFilePromisified} from './common';
|
||||
import {ExpectedValidationErrors, ValidationError, ValidationResult} from './types/validator';
|
||||
import {isThingWithType} from './util/guards';
|
||||
import {globPromisified, readFilePromisified, writeFilePromisified} from './common.js';
|
||||
import {ExpectedValidationErrors, ValidationError, ValidationResult} from './types/validator.js';
|
||||
import {isThingWithType} from './util/guards.js';
|
||||
import path from 'path';
|
||||
import re2 from './types/re2';
|
||||
import {toPosixPath} from './util/posix-path';
|
||||
import re2 from './types/re2.js';
|
||||
import {toPosixPath} from './util/posix-path.js';
|
||||
|
||||
/**
|
||||
* StAppsCore validator
|
||||
@@ -33,7 +33,7 @@ export class Validator {
|
||||
/**
|
||||
* JSON Schema Validator
|
||||
*/
|
||||
private readonly ajv = new Ajv({
|
||||
private readonly ajv = new Ajv.default({
|
||||
verbose: true,
|
||||
code: {regExp: re2},
|
||||
});
|
||||
@@ -132,7 +132,7 @@ function fromAjvResult(
|
||||
result: boolean | PromiseLike<unknown>,
|
||||
schema: JSONSchema7,
|
||||
instance: unknown,
|
||||
ajvInstance: Ajv,
|
||||
ajvInstance: Ajv.default,
|
||||
): ValidationResult {
|
||||
const betterErrorObject: IOutputError[] | undefined = betterAjvErrors(
|
||||
schema,
|
||||
|
||||
Reference in New Issue
Block a user