From 4d57b29b8d1e5f334a9602245f8e24e23c2157fc Mon Sep 17 00:00:00 2001 From: Jonas Lagoni Date: Thu, 25 Apr 2024 13:08:40 +0200 Subject: [PATCH] feat: refactor CLI for integration into AsyncAPI CLI (#1952) --- modelina-cli/.eslintrc | 3 +- modelina-cli/package.json | 3 +- modelina-cli/src/commands/generate.ts | 373 +------------------------ modelina-cli/src/helpers/csharp.ts | 85 ++++++ modelina-cli/src/helpers/csplusplus.ts | 26 ++ modelina-cli/src/helpers/dart.ts | 27 ++ modelina-cli/src/helpers/generate.ts | 132 +++++++++ modelina-cli/src/helpers/go.ts | 27 ++ modelina-cli/src/helpers/java.ts | 51 ++++ modelina-cli/src/helpers/javascript.ts | 19 ++ modelina-cli/src/helpers/kotlin.ts | 27 ++ modelina-cli/src/helpers/php.ts | 26 ++ modelina-cli/src/helpers/python.ts | 19 ++ modelina-cli/src/helpers/rust.ts | 19 ++ modelina-cli/src/helpers/scala.ts | 25 ++ modelina-cli/src/helpers/typescript.ts | 95 +++++++ modelina-cli/src/index.ts | 2 + 17 files changed, 594 insertions(+), 365 deletions(-) create mode 100644 modelina-cli/src/helpers/csharp.ts create mode 100644 modelina-cli/src/helpers/csplusplus.ts create mode 100644 modelina-cli/src/helpers/dart.ts create mode 100644 modelina-cli/src/helpers/generate.ts create mode 100644 modelina-cli/src/helpers/go.ts create mode 100644 modelina-cli/src/helpers/java.ts create mode 100644 modelina-cli/src/helpers/javascript.ts create mode 100644 modelina-cli/src/helpers/kotlin.ts create mode 100644 modelina-cli/src/helpers/php.ts create mode 100644 modelina-cli/src/helpers/python.ts create mode 100644 modelina-cli/src/helpers/rust.ts create mode 100644 modelina-cli/src/helpers/scala.ts create mode 100644 modelina-cli/src/helpers/typescript.ts diff --git a/modelina-cli/.eslintrc b/modelina-cli/.eslintrc index 900717fb3e..2044c8b836 100644 --- a/modelina-cli/.eslintrc +++ b/modelina-cli/.eslintrc @@ -22,6 +22,7 @@ "unicorn/no-await-expression-member": "off", "security/detect-non-literal-fs-filename": "off", "no-underscore-dangle": "off", - "unicorn/prefer-module": "off" + "unicorn/prefer-module": "off", + "valid-jsdoc": "off" } } diff --git a/modelina-cli/package.json b/modelina-cli/package.json index 790f82eed3..a89eb7bc50 100644 --- a/modelina-cli/package.json +++ b/modelina-cli/package.json @@ -44,7 +44,8 @@ "/lib", "/assets", "/npm-shrinkwrap.json", - "/oclif.manifest.json" + "/oclif.manifest.json", + "/README.md" ], "homepage": "https://github.com/asyncapi/modelina", "keywords": [ diff --git a/modelina-cli/src/commands/generate.ts b/modelina-cli/src/commands/generate.ts index 9f68d87fc5..dd0be21383 100644 --- a/modelina-cli/src/commands/generate.ts +++ b/modelina-cli/src/commands/generate.ts @@ -1,169 +1,14 @@ -import { CSharpFileGenerator, JavaFileGenerator, JavaScriptFileGenerator, TypeScriptFileGenerator, GoFileGenerator, Logger, DartFileGenerator, PythonFileGenerator, RustFileGenerator, TS_COMMON_PRESET, TS_JSONBINPACK_PRESET, CSHARP_NEWTONSOFT_SERIALIZER_PRESET, CSHARP_COMMON_PRESET, CSHARP_JSON_SERIALIZER_PRESET, KotlinFileGenerator, TS_DESCRIPTION_PRESET, PhpFileGenerator, CplusplusFileGenerator, JAVA_CONSTRAINTS_PRESET, JAVA_JACKSON_PRESET, JAVA_COMMON_PRESET, JAVA_DESCRIPTION_PRESET, ScalaFileGenerator } from '@asyncapi/modelina'; -import { Args, Flags } from '@oclif/core'; import ModelinaCommand from '../base'; - -import type { AbstractGenerator, AbstractFileGenerator } from '@asyncapi/modelina'; import { readFile } from 'node:fs/promises'; - -enum Languages { - typescript = 'typescript', - csharp = 'csharp', - golang = 'golang', - java = 'java', - javascript = 'javascript', - dart = 'dart', - python = 'python', - rust = 'rust', - kotlin='kotlin', - php='php', - cplusplus='cplusplus', - scala='scala' -} -const possibleLanguageValues = Object.values(Languages).join(', '); +import { Languages, ModelinaArgs, ModelinaFlags, generateModels } from '../helpers/generate'; export default class Models extends ModelinaCommand { static description = 'Generates typed models'; - static args = { - language: Args.string({description: 'The language you want the typed models generated for.', options: Object.keys(Languages), required: true}), - file: Args.string({description: 'Path or URL to the AsyncAPI document, or context-name', required: true}), - }; - - static flags = { - help: Flags.help({ char: 'h' }), - output: Flags.string({ - char: 'o', - description: 'The output directory where the models should be written to. Omitting this flag will write the models to `stdout`.', - required: false - }), - - /** - * TypeScript specific options - */ - tsModelType: Flags.string({ - type: 'option', - options: ['class', 'interface'], - description: 'TypeScript specific, define which type of model needs to be generated.', - required: false, - default: 'class', - }), - tsEnumType: Flags.string({ - type: 'option', - options: ['enum', 'union'], - description: 'TypeScript specific, define which type of enums needs to be generated.', - required: false, - default: 'enum', - }), - tsModuleSystem: Flags.string({ - type: 'option', - options: ['ESM', 'CJS'], - description: 'TypeScript specific, define the module system to be used.', - required: false, - default: 'ESM', - }), - tsIncludeComments: Flags.boolean({ - description: 'TypeScript specific, if enabled add comments while generating models.', - required: false, - default: false, - }), - tsExportType: Flags.string({ - type: 'option', - options: ['default', 'named'], - description: 'TypeScript specific, define which type of export needs to be generated.', - required: false, - default: 'default', - }), - tsJsonBinPack: Flags.boolean({ - description: 'TypeScript specific, define basic support for serializing to and from binary with jsonbinpack.', - required: false, - default: false, - }), - tsMarshalling: Flags.boolean({ - description: 'TypeScript specific, generate the models with marshalling functions.', - required: false, - default: false, - }), - tsExampleInstance: Flags.boolean({ - description: 'Typescript specific, generate example of the model.', - required: false, - default: false, - }), - - /** - * Go and Java specific package name to use for the generated models - */ - packageName: Flags.string({ - description: 'Go, Java and Kotlin specific, define the package to use for the generated models. This is required when language is `go`, `java` or `kotlin`.', - required: false - }), - - /** - * Java specific options - */ - javaIncludeComments: Flags.boolean({ - description: 'Java specific, if enabled add comments while generating models.', - required: false, - default: false - }), - javaJackson: Flags.boolean({ - description: 'Java specific, generate the models with Jackson serialization support', - required: false, - default: false - }), - javaConstraints: Flags.boolean({ - description: 'Java specific, generate the models with constraints', - required: false, - default: false - }), - - /** - * C++ and C# and PHP specific namespace to use for the generated models - */ - namespace: Flags.string({ - description: 'C#, C++ and PHP specific, define the namespace to use for the generated models. This is required when language is `csharp`,`c++` or `php`.', - required: false - }), + static args = ModelinaArgs; + static flags = ModelinaFlags; - /** - * C# specific options - */ - csharpAutoImplement: Flags.boolean({ - description: 'C# specific, define whether to generate auto-implemented properties or not.', - required: false, - default: false - }), - csharpNewtonsoft: Flags.boolean({ - description: 'C# specific, generate the models with newtonsoft serialization support', - required: false, - default: false - }), - csharpArrayType: Flags.string({ - type: 'option', - description: 'C# specific, define which type of array needs to be generated.', - options: ['Array', 'List'], - required: false, - default: 'Array' - }), - csharpHashcode: Flags.boolean({ - description: 'C# specific, generate the models with the GetHashCode method overwritten', - required: false, - default: false - }), - csharpEqual: Flags.boolean({ - description: 'C# specific, generate the models with the Equal method overwritten', - required: false, - default: false - }), - csharpSystemJson: Flags.boolean({ - description: 'C# specific, generate the models with System.Text.Json serialization support', - required: false, - default: false - }), - }; - - /* eslint-disable sonarjs/cognitive-complexity */ async run() { const { args, flags } = await this.parse(Models); - const { tsModelType, tsEnumType, tsIncludeComments, tsModuleSystem, tsExportType, tsJsonBinPack, tsMarshalling, tsExampleInstance, namespace, csharpAutoImplement, csharpArrayType, csharpNewtonsoft, csharpHashcode, csharpEqual, csharpSystemJson, packageName, javaIncludeComments, javaJackson, javaConstraints, output } = flags; const { language, file } = args; let document = ""; try { @@ -171,220 +16,22 @@ export default class Models extends ModelinaCommand { } catch { throw new Error('Unable to read input file content.'); } - - Logger.setLogger({ - info: (message) => { + + const logger = { + info: (message: string) => { this.log(message); }, - debug: (message) => { + debug: (message: string) => { this.debug(message); }, - warn: (message) => { + warn: (message: string) => { this.warn(message); }, - error: (message) => { + error: (message: string) => { this.error(message); }, - }); - - let fileGenerator: AbstractGenerator & AbstractFileGenerator; - let fileOptions: any = {}; - const presets = []; - const options = { - marshalling: tsMarshalling, - example: tsExampleInstance, - }; - switch (language) { - case Languages.typescript: { - presets.push({ - preset: TS_COMMON_PRESET, - options - }); - if (tsIncludeComments) {presets.push(TS_DESCRIPTION_PRESET);} - if (tsJsonBinPack) { - presets.push({ - preset: TS_COMMON_PRESET, - options - }, - TS_JSONBINPACK_PRESET); - } - - fileGenerator = new TypeScriptFileGenerator({ - modelType: tsModelType as 'class' | 'interface', - enumType: tsEnumType as 'enum' | 'union', - presets - }); - fileOptions = { - moduleSystem: tsModuleSystem, - exportType: tsExportType - }; - break; - } - - case Languages.python: { - fileGenerator = new PythonFileGenerator(); - break; - } - - case Languages.rust: { - fileGenerator = new RustFileGenerator(); - break; - } - - case Languages.csharp: { - if (namespace === undefined) { - throw new Error('In order to generate models to C#, we need to know which namespace they are under. Add `--namespace=NAMESPACE` to set the desired namespace.'); - } - - if (csharpNewtonsoft) { - presets.push(CSHARP_NEWTONSOFT_SERIALIZER_PRESET); - } - - if (csharpSystemJson) { - presets.push(CSHARP_JSON_SERIALIZER_PRESET); - } - - if (csharpHashcode || csharpEqual) { - presets.push({ - preset: CSHARP_COMMON_PRESET, - options: { - hashCode: csharpHashcode, - equals: csharpEqual - } - }); - } - - fileGenerator = new CSharpFileGenerator({ - presets, - collectionType: csharpArrayType as 'Array' | 'List', - autoImplementedProperties: csharpAutoImplement - }); - - fileOptions = { - namespace - }; - break; - } - - case Languages.cplusplus: { - if (namespace === undefined) { - throw new Error('In order to generate models to C++, we need to know which namespace they are under. Add `--namespace=NAMESPACE` to set the desired namespace.'); - } - - fileGenerator = new CplusplusFileGenerator({ - namespace - }); - break; - } - - case Languages.scala: { - if (packageName === undefined) { - throw new Error('In order to generate models to Scala, we need to know which package they are under. Add `--packageName=PACKAGENAME` to set the desired package name.'); - } - - fileGenerator = new ScalaFileGenerator(); - fileOptions = { - packageName - }; - break; - } - - case Languages.golang: { - if (packageName === undefined) { - throw new Error('In order to generate models to Go, we need to know which package they are under. Add `--packageName=PACKAGENAME` to set the desired package name.'); - } - - fileGenerator = new GoFileGenerator(); - fileOptions = { - packageName - }; - break; - } - - case Languages.java: { - if (packageName === undefined) { - throw new Error('In order to generate models to Java, we need to know which package they are under. Add `--packageName=PACKAGENAME` to set the desired package name.'); - } - - presets.push({ - preset: JAVA_COMMON_PRESET, - options - }); - if (javaIncludeComments) {presets.push(JAVA_DESCRIPTION_PRESET);} - if (javaJackson) {presets.push(JAVA_JACKSON_PRESET);} - if (javaConstraints) {presets.push(JAVA_CONSTRAINTS_PRESET);} - fileGenerator = new JavaFileGenerator({ presets }); - fileOptions = { - packageName - }; - break; - } - - case Languages.javascript: { - fileGenerator = new JavaScriptFileGenerator(); - break; - } - - case Languages.dart: { - if (packageName === undefined) { - throw new Error('In order to generate models to Dart, we need to know which package they are under. Add `--packageName=PACKAGENAME` to set the desired package name.'); - } - - fileGenerator = new DartFileGenerator(); - fileOptions = { - packageName - }; - break; - } - - case Languages.kotlin: { - if (packageName === undefined) { - throw new Error('In order to generate models to Kotlin, we need to know which package they are under. Add `--packageName=PACKAGENAME` to set the desired package name.'); - } - - fileGenerator = new KotlinFileGenerator(); - fileOptions = { - packageName - }; - break; - } - - case Languages.php: { - if (namespace === undefined) { - throw new Error('In order to generate models to PHP, we need to know which namespace they are under. Add `--namespace=NAMESPACE` to set the desired namespace.'); - } - - fileGenerator = new PhpFileGenerator(); - fileOptions = { - namespace - }; - break; - } - - default: { - throw new Error(`Could not determine generator for language ${language}, are you using one of the following values ${possibleLanguageValues}?`); - } - } - - if (output) { - const models = await fileGenerator.generateToFiles( - document, - output, - { ...fileOptions, }); - const generatedModels = models.map((model) => { return model.modelName; }); - this.log(`Successfully generated the following models: ${generatedModels.join(', ')}`); - return; } - const models = await fileGenerator.generateCompleteModels( - document, - { ...fileOptions }); - const generatedModels = models.map((model) => { - return ` -## Model name: ${model.modelName} -${model.result} -`; - }); - this.log(`Successfully generated the following models: ${generatedModels.join('\n')}`); + await generateModels(flags, document, logger, language as Languages); } } \ No newline at end of file diff --git a/modelina-cli/src/helpers/csharp.ts b/modelina-cli/src/helpers/csharp.ts new file mode 100644 index 0000000000..7fdfd7e0a8 --- /dev/null +++ b/modelina-cli/src/helpers/csharp.ts @@ -0,0 +1,85 @@ +import { CSHARP_COMMON_PRESET, CSHARP_JSON_SERIALIZER_PRESET, CSHARP_NEWTONSOFT_SERIALIZER_PRESET, CSharpFileGenerator } from "@asyncapi/modelina"; +import { Flags } from "@oclif/core"; +import { BuilderReturnType } from "./generate"; + +export const CSharpOclifFlags = { + csharpAutoImplement: Flags.boolean({ + description: 'C# specific, define whether to generate auto-implemented properties or not.', + required: false, + default: false + }), + csharpNewtonsoft: Flags.boolean({ + description: 'C# specific, generate the models with newtonsoft serialization support', + required: false, + default: false + }), + csharpArrayType: Flags.string({ + type: 'option', + description: 'C# specific, define which type of array needs to be generated.', + options: ['Array', 'List'], + required: false, + default: 'Array' + }), + csharpHashcode: Flags.boolean({ + description: 'C# specific, generate the models with the GetHashCode method overwritten', + required: false, + default: false + }), + csharpEqual: Flags.boolean({ + description: 'C# specific, generate the models with the Equal method overwritten', + required: false, + default: false + }), + csharpSystemJson: Flags.boolean({ + description: 'C# specific, generate the models with System.Text.Json serialization support', + required: false, + default: false + }), +} + +/** + * This function builds all the relevant information for the main generate command + * + * @param flags + * @returns + */ +export function buildCSharpGenerator(flags: any): BuilderReturnType { + const { namespace, csharpAutoImplement, csharpArrayType, csharpNewtonsoft, csharpHashcode, csharpEqual, csharpSystemJson } = flags; + const presets = []; + + if (namespace === undefined) { + throw new Error('In order to generate models to C#, we need to know which namespace they are under. Add `--namespace=NAMESPACE` to set the desired namespace.'); + } + + if (csharpNewtonsoft) { + presets.push(CSHARP_NEWTONSOFT_SERIALIZER_PRESET); + } + + if (csharpSystemJson) { + presets.push(CSHARP_JSON_SERIALIZER_PRESET); + } + + if (csharpHashcode || csharpEqual) { + presets.push({ + preset: CSHARP_COMMON_PRESET, + options: { + hashCode: csharpHashcode, + equals: csharpEqual + } + }); + } + + const fileGenerator = new CSharpFileGenerator({ + presets, + collectionType: csharpArrayType as 'Array' | 'List', + autoImplementedProperties: csharpAutoImplement + }); + + const fileOptions = { + namespace + }; + return { + fileOptions, + fileGenerator + }; +} \ No newline at end of file diff --git a/modelina-cli/src/helpers/csplusplus.ts b/modelina-cli/src/helpers/csplusplus.ts new file mode 100644 index 0000000000..43aa378328 --- /dev/null +++ b/modelina-cli/src/helpers/csplusplus.ts @@ -0,0 +1,26 @@ +import { CplusplusFileGenerator } from "@asyncapi/modelina"; +import { BuilderReturnType } from "./generate"; + +export const CplusplusOclifFlags = { } + +/** + * This function builds all the relevant information for the main generate command + * + * @param flags + * @returns + */ +export function buildCplusplusGenerator(flags: any): BuilderReturnType { + const { namespace } = flags; + if (namespace === undefined) { + throw new Error('In order to generate models to C++, we need to know which namespace they are under. Add `--namespace=NAMESPACE` to set the desired namespace.'); + } + + const fileGenerator = new CplusplusFileGenerator({ + namespace + }); + const fileOptions = undefined; + return { + fileOptions, + fileGenerator + }; +} \ No newline at end of file diff --git a/modelina-cli/src/helpers/dart.ts b/modelina-cli/src/helpers/dart.ts new file mode 100644 index 0000000000..cbad7565e8 --- /dev/null +++ b/modelina-cli/src/helpers/dart.ts @@ -0,0 +1,27 @@ +import { DartFileGenerator } from "@asyncapi/modelina"; +import { BuilderReturnType } from "./generate"; + +export const DartOclifFlags = { } + + +/** + * This function builds all the relevant information for the main generate command + * + * @param flags + * @returns + */ +export function buildDartGenerator(flags: any): BuilderReturnType { + const { packageName } = flags; + if (packageName === undefined) { + throw new Error('In order to generate models to Dart, we need to know which package they are under. Add `--packageName=PACKAGENAME` to set the desired package name.'); + } + + const fileGenerator = new DartFileGenerator(); + const fileOptions = { + packageName + }; + return { + fileOptions, + fileGenerator + }; +} \ No newline at end of file diff --git a/modelina-cli/src/helpers/generate.ts b/modelina-cli/src/helpers/generate.ts new file mode 100644 index 0000000000..0493a02569 --- /dev/null +++ b/modelina-cli/src/helpers/generate.ts @@ -0,0 +1,132 @@ +import { AbstractFileGenerator, AbstractGenerator, Logger } from "@asyncapi/modelina"; +import { TypeScriptOclifFlags, buildTypeScriptGenerator } from "./typescript"; +import { CplusplusOclifFlags, buildCplusplusGenerator } from "./csplusplus"; +import { CSharpOclifFlags, buildCSharpGenerator } from "./csharp"; +import { DartOclifFlags, buildDartGenerator } from "./dart"; +import { GoOclifFlags, buildGoGenerator } from "./go"; +import { JavaOclifFlags, buildJavaGenerator } from "./java"; +import { JavaScriptOclifFlags, buildJavaScriptGenerator } from "./javascript"; +import { KotlinOclifFlags, buildKotlinGenerator } from "./kotlin"; +import { PhpOclifFlags, buildPhpGenerator } from "./php"; +import { PythonOclifFlags, buildPythonGenerator } from "./python"; +import { RustOclifFlags, buildRustGenerator } from "./rust"; +import { ScalaOclifFlags, buildScalaGenerator } from "./scala"; +import { Args, Flags } from "@oclif/core"; + +export interface BuilderReturnType { + fileOptions: any, + fileGenerator: AbstractGenerator & AbstractFileGenerator +} + +export enum Languages { + typescript = 'typescript', + csharp = 'csharp', + golang = 'golang', + java = 'java', + javascript = 'javascript', + dart = 'dart', + python = 'python', + rust = 'rust', + kotlin = 'kotlin', + php = 'php', + cplusplus = 'cplusplus', + scala = 'scala' +} +const possibleLanguageValues = Object.values(Languages).join(', '); + +const buildMapper: { [key in Languages]: (flags: any) => BuilderReturnType } = { + typescript: buildTypeScriptGenerator, + cplusplus: buildCplusplusGenerator, + csharp: buildCSharpGenerator, + dart: buildDartGenerator, + golang: buildGoGenerator, + java: buildJavaGenerator, + javascript: buildJavaScriptGenerator, + kotlin: buildKotlinGenerator, + php: buildPhpGenerator, + python: buildPythonGenerator, + rust: buildRustGenerator, + scala: buildScalaGenerator, +} + +export const ModelinaArgs = { + language: Args.string({ description: 'The language you want the typed models generated for.', options: Object.keys(Languages), required: true }), + file: Args.string({ description: 'Path or URL to the AsyncAPI document, or context-name', required: true }), +}; +export const ModelinaFlags = { + help: Flags.help({ char: 'h' }), + output: Flags.string({ + char: 'o', + description: 'The output directory where the models should be written to. Omitting this flag will write the models to `stdout`.', + required: false + }), + /** + * Go and Java specific package name to use for the generated models + */ + packageName: Flags.string({ + description: 'Go, Java and Kotlin specific, define the package to use for the generated models. This is required when language is `go`, `java` or `kotlin`.', + required: false + }), + + /** + * C++ and C# and PHP specific namespace to use for the generated models + */ + namespace: Flags.string({ + description: 'C#, C++ and PHP specific, define the namespace to use for the generated models. This is required when language is `csharp`,`c++` or `php`.', + required: false + }), + ...TypeScriptOclifFlags, + ...CSharpOclifFlags, + ...CplusplusOclifFlags, + ...DartOclifFlags, + ...GoOclifFlags, + ...JavaOclifFlags, + ...JavaScriptOclifFlags, + ...KotlinOclifFlags, + ...PhpOclifFlags, + ...PythonOclifFlags, + ...RustOclifFlags, + ...ScalaOclifFlags, +}; + +/** + * Function for generating models from the CLI arguments, flags and inputs + * + * @param flags + * @param document + * @param logger + * @param language + * @returns + */ +export async function generateModels(flags: any, document: any, logger: any, language: Languages) { + const { output } = flags; + Logger.setLogger(logger); + // eslint-disable-next-line security/detect-object-injection + const mapper = buildMapper[language] + if (!mapper) { + throw new Error(`Could not determine generator for language ${language}, are you using one of the following values ${possibleLanguageValues}?`); + } + + const { fileGenerator, fileOptions } = mapper(flags); + + if (output) { + const models = await fileGenerator.generateToFiles( + document, + output, + { ...fileOptions, }); + const generatedModels = models.map((model) => { return model.modelName; }); + logger.info(`Successfully generated the following models: ${generatedModels.join(', ')}`); + return; + } + + const models = await fileGenerator.generateCompleteModels( + document, + { ...fileOptions }); + const generatedModels = models.map((model) => { + return ` + ## Model name: ${model.modelName} + ${model.result} + `; + }); + logger.info(`Successfully generated the following models: ${generatedModels.join('\n')}`); +} \ No newline at end of file diff --git a/modelina-cli/src/helpers/go.ts b/modelina-cli/src/helpers/go.ts new file mode 100644 index 0000000000..ffd3a58d91 --- /dev/null +++ b/modelina-cli/src/helpers/go.ts @@ -0,0 +1,27 @@ +import { GoFileGenerator } from "@asyncapi/modelina"; +import { BuilderReturnType } from "./generate"; + +export const GoOclifFlags = { } + +/** + * This function builds all the relevant information for the main generate command + * + * @param flags + * @returns + */ +export function buildGoGenerator(flags: any): BuilderReturnType { + const { packageName } = flags; + + if (packageName === undefined) { + throw new Error('In order to generate models to Go, we need to know which package they are under. Add `--packageName=PACKAGENAME` to set the desired package name.'); + } + + const fileGenerator = new GoFileGenerator(); + const fileOptions = { + packageName + }; + return { + fileOptions, + fileGenerator + }; +} \ No newline at end of file diff --git a/modelina-cli/src/helpers/java.ts b/modelina-cli/src/helpers/java.ts new file mode 100644 index 0000000000..4e0aefbf72 --- /dev/null +++ b/modelina-cli/src/helpers/java.ts @@ -0,0 +1,51 @@ +import { JAVA_COMMON_PRESET, JAVA_CONSTRAINTS_PRESET, JAVA_DESCRIPTION_PRESET, JAVA_JACKSON_PRESET, JavaFileGenerator } from "@asyncapi/modelina"; +import { Flags } from "@oclif/core"; +import { BuilderReturnType } from "./generate"; + +export const JavaOclifFlags = { + javaIncludeComments: Flags.boolean({ + description: 'Java specific, if enabled add comments while generating models.', + required: false, + default: false + }), + javaJackson: Flags.boolean({ + description: 'Java specific, generate the models with Jackson serialization support', + required: false, + default: false + }), + javaConstraints: Flags.boolean({ + description: 'Java specific, generate the models with constraints', + required: false, + default: false + }), +} + +/** + * This function builds all the relevant information for the main generate command + * + * @param flags + * @returns + */ +export function buildJavaGenerator(flags: any): BuilderReturnType { + const { packageName, javaIncludeComments, javaJackson, javaConstraints } = flags; + const presets = [] + + if (packageName === undefined) { + throw new Error('In order to generate models to Java, we need to know which package they are under. Add `--packageName=PACKAGENAME` to set the desired package name.'); + } + + presets.push({ + preset: JAVA_COMMON_PRESET, + }); + if (javaIncludeComments) {presets.push(JAVA_DESCRIPTION_PRESET);} + if (javaJackson) {presets.push(JAVA_JACKSON_PRESET);} + if (javaConstraints) {presets.push(JAVA_CONSTRAINTS_PRESET);} + const fileGenerator = new JavaFileGenerator({ presets }); + const fileOptions = { + packageName + }; + return { + fileOptions, + fileGenerator + }; +} \ No newline at end of file diff --git a/modelina-cli/src/helpers/javascript.ts b/modelina-cli/src/helpers/javascript.ts new file mode 100644 index 0000000000..acdb40cf0b --- /dev/null +++ b/modelina-cli/src/helpers/javascript.ts @@ -0,0 +1,19 @@ +import { JavaScriptFileGenerator } from "@asyncapi/modelina"; +import { BuilderReturnType } from "./generate"; + +export const JavaScriptOclifFlags = { } + +/** + * This function builds all the relevant information for the main generate command + * + * @param flags + * @returns + */ +export function buildJavaScriptGenerator(flags: any): BuilderReturnType { + const fileGenerator = new JavaScriptFileGenerator(); + const fileOptions = undefined; + return { + fileOptions, + fileGenerator + }; +} \ No newline at end of file diff --git a/modelina-cli/src/helpers/kotlin.ts b/modelina-cli/src/helpers/kotlin.ts new file mode 100644 index 0000000000..42c6fe91ad --- /dev/null +++ b/modelina-cli/src/helpers/kotlin.ts @@ -0,0 +1,27 @@ +import { KotlinFileGenerator } from "@asyncapi/modelina"; +import { BuilderReturnType } from "./generate"; + +export const KotlinOclifFlags = { } + +/** + * This function builds all the relevant information for the main generate command + * + * @param flags + * @returns + */ +export function buildKotlinGenerator(flags: any): BuilderReturnType { + const { packageName } = flags; + + if (packageName === undefined) { + throw new Error('In order to generate models to Kotlin, we need to know which package they are under. Add `--packageName=PACKAGENAME` to set the desired package name.'); + } + + const fileGenerator = new KotlinFileGenerator(); + const fileOptions = { + packageName + }; + return { + fileOptions, + fileGenerator + }; +} \ No newline at end of file diff --git a/modelina-cli/src/helpers/php.ts b/modelina-cli/src/helpers/php.ts new file mode 100644 index 0000000000..9272ca5e81 --- /dev/null +++ b/modelina-cli/src/helpers/php.ts @@ -0,0 +1,26 @@ +import { PhpFileGenerator } from "@asyncapi/modelina"; + +export const PhpOclifFlags = { } + +/** + * This function builds all the relevant information for the main generate command + * + * @param flags + * @returns + */ +export function buildPhpGenerator(flags: any) { + const { namespace } = flags; + + if (namespace === undefined) { + throw new Error('In order to generate models to PHP, we need to know which namespace they are under. Add `--namespace=NAMESPACE` to set the desired namespace.'); + } + + const fileGenerator = new PhpFileGenerator(); + const fileOptions = { + namespace + }; + return { + fileOptions, + fileGenerator + }; +} \ No newline at end of file diff --git a/modelina-cli/src/helpers/python.ts b/modelina-cli/src/helpers/python.ts new file mode 100644 index 0000000000..ec2aaa284d --- /dev/null +++ b/modelina-cli/src/helpers/python.ts @@ -0,0 +1,19 @@ +import { PythonFileGenerator } from "@asyncapi/modelina"; +import { BuilderReturnType } from "./generate"; + +export const PythonOclifFlags = { } + +/** + * This function builds all the relevant information for the main generate command + * + * @param flags + * @returns + */ +export function buildPythonGenerator(flags: any): BuilderReturnType { + const fileGenerator = new PythonFileGenerator(); + const fileOptions = undefined; + return { + fileOptions, + fileGenerator + }; +} \ No newline at end of file diff --git a/modelina-cli/src/helpers/rust.ts b/modelina-cli/src/helpers/rust.ts new file mode 100644 index 0000000000..f7e694a530 --- /dev/null +++ b/modelina-cli/src/helpers/rust.ts @@ -0,0 +1,19 @@ +import { RustFileGenerator } from "@asyncapi/modelina"; +import { BuilderReturnType } from "./generate"; + +export const RustOclifFlags = { } + +/** + * This function builds all the relevant information for the main generate command + * + * @param flags + * @returns + */ +export function buildRustGenerator(flags: any): BuilderReturnType { + const fileGenerator = new RustFileGenerator(); + const fileOptions = undefined; + return { + fileOptions, + fileGenerator + }; +} \ No newline at end of file diff --git a/modelina-cli/src/helpers/scala.ts b/modelina-cli/src/helpers/scala.ts new file mode 100644 index 0000000000..ec6c70965e --- /dev/null +++ b/modelina-cli/src/helpers/scala.ts @@ -0,0 +1,25 @@ +import { ScalaFileGenerator } from "@asyncapi/modelina"; + +export const ScalaOclifFlags = { } + +/** + * This function builds all the relevant information for the main generate command + * + * @param flags + * @returns + */ +export function buildScalaGenerator(flags: any) { + const { packageName } = flags; + if (packageName === undefined) { + throw new Error('In order to generate models to Scala, we need to know which package they are under. Add `--packageName=PACKAGENAME` to set the desired package name.'); + } + + const fileGenerator = new ScalaFileGenerator(); + const fileOptions = { + packageName + }; + return { + fileOptions, + fileGenerator + }; +} \ No newline at end of file diff --git a/modelina-cli/src/helpers/typescript.ts b/modelina-cli/src/helpers/typescript.ts new file mode 100644 index 0000000000..bfadb04eab --- /dev/null +++ b/modelina-cli/src/helpers/typescript.ts @@ -0,0 +1,95 @@ +import { TS_COMMON_PRESET, TS_DESCRIPTION_PRESET, TS_JSONBINPACK_PRESET, TypeScriptFileGenerator } from "@asyncapi/modelina"; +import { Flags } from "@oclif/core"; +import { BuilderReturnType } from "./generate"; + +export const TypeScriptOclifFlags = { + tsModelType: Flags.string({ + type: 'option', + options: ['class', 'interface'], + description: 'TypeScript specific, define which type of model needs to be generated.', + required: false, + default: 'class', + }), + tsEnumType: Flags.string({ + type: 'option', + options: ['enum', 'union'], + description: 'TypeScript specific, define which type of enums needs to be generated.', + required: false, + default: 'enum', + }), + tsModuleSystem: Flags.string({ + type: 'option', + options: ['ESM', 'CJS'], + description: 'TypeScript specific, define the module system to be used.', + required: false, + default: 'ESM', + }), + tsIncludeComments: Flags.boolean({ + description: 'TypeScript specific, if enabled add comments while generating models.', + required: false, + default: false, + }), + tsExportType: Flags.string({ + type: 'option', + options: ['default', 'named'], + description: 'TypeScript specific, define which type of export needs to be generated.', + required: false, + default: 'default', + }), + tsJsonBinPack: Flags.boolean({ + description: 'TypeScript specific, define basic support for serializing to and from binary with jsonbinpack.', + required: false, + default: false, + }), + tsMarshalling: Flags.boolean({ + description: 'TypeScript specific, generate the models with marshalling functions.', + required: false, + default: false, + }), + tsExampleInstance: Flags.boolean({ + description: 'Typescript specific, generate example of the model.', + required: false, + default: false, + }), +} + +/** + * This function builds all the relevant information for the main generate command + * + * @param flags + * @returns + */ +export function buildTypeScriptGenerator(flags: any): BuilderReturnType { + const { tsModelType, tsEnumType, tsIncludeComments, tsModuleSystem, tsExportType, tsJsonBinPack, tsMarshalling, tsExampleInstance } = flags; + const presets = []; + const options = { + marshalling: tsMarshalling, + example: tsExampleInstance, + }; + presets.push({ + preset: TS_COMMON_PRESET, + options + }); + if (tsIncludeComments) { presets.push(TS_DESCRIPTION_PRESET); } + if (tsJsonBinPack) { + presets.push({ + preset: TS_COMMON_PRESET, + options + }, + TS_JSONBINPACK_PRESET); + } + + const fileGenerator = new TypeScriptFileGenerator({ + modelType: tsModelType as 'class' | 'interface', + enumType: tsEnumType as 'enum' | 'union', + presets + }); + const fileOptions = { + moduleSystem: tsModuleSystem, + exportType: tsExportType + }; + return { + fileOptions, + fileGenerator + } +} \ No newline at end of file diff --git a/modelina-cli/src/index.ts b/modelina-cli/src/index.ts index e32b0b2e58..7727dae8ca 100644 --- a/modelina-cli/src/index.ts +++ b/modelina-cli/src/index.ts @@ -1 +1,3 @@ export {run} from '@oclif/core' + +export {generateModels, ModelinaArgs, ModelinaFlags, Languages} from './helpers/generate' \ No newline at end of file