From 02c4de5407ab48b74e8bf9b3de6270a8e2b25350 Mon Sep 17 00:00:00 2001 From: Zbigniew Malcherczyk Date: Tue, 23 May 2023 15:53:57 +0200 Subject: [PATCH 01/79] chore: add ferror to PHP codeowners (#1308) --- CODEOWNERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 83e85af7f6..ece9d612c1 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -46,4 +46,5 @@ # Language Champions for Rust and its presets */generators/rust @leigh-johnson -# Language Champions for Kotlin and it's presets +# Language Champions for PHP and it's presets +*/generators/php @ferror From 7c14b4a0062cda3497d24b19df29440450644065 Mon Sep 17 00:00:00 2001 From: Sambhav Gupta <81870866+sambhavgupta0705@users.noreply.github.com> Date: Wed, 24 May 2023 15:42:51 +0530 Subject: [PATCH 02/79] chore(website): fixed the overlapping of playground loader (#1317) --- modelina-website/src/components/playground/Playground.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index ecfc776eb8..7c0dd20fad 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -217,13 +217,13 @@ class Playground extends React.Component< let loader; if (!isHardLoaded) { loader = ( -
+
Loading Modelina Playground. Connecting to playground server...
); } else if (!isSoftLoaded) { loader = ( -
+
Loading Modelina Playground. Rendering playground components...
); From 811c1f10caf0a24c78f6480a8e3f9d485cd556cc Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 24 May 2023 14:08:34 +0200 Subject: [PATCH 03/79] docs: add Bhavik-ag as a contributor for design (#1320) * update README.md * update .all-contributorsrc --------- Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 12 +++++++++++- README.md | 3 ++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index b950b3fe84..ea20369a16 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -579,6 +579,15 @@ "example", "review" ] + }, + { + "login": "Bhavik-ag", + "name": "Bhavik Agarwal", + "avatar_url": "https://avatars.githubusercontent.com/u/73033511?v=4", + "profile": "https://codeyt.com/", + "contributions": [ + "design" + ] } ], "contributorsPerLine": 7, @@ -587,5 +596,6 @@ "repoType": "github", "repoHost": "https://github.com", "skipCi": false, - "commitConvention": "none" + "commitConvention": "none", + "commitType": "docs" } diff --git a/README.md b/README.md index 9992c3b74a..c849fad8e4 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![Discussions](https://img.shields.io/github/discussions/asyncapi/modelina)](https://github.com/asyncapi/modelina/discussions) [![Website](https://img.shields.io/website?label=website&url=https%3A%2F%2Fwww.modelina.org)](https://www.modelina.org) [![Playground](https://img.shields.io/website?label=playground&url=https%3A%2F%2Fwww.modelina.org%2Fplayground)](https://www.modelina.org/playground) -[![All Contributors](https://img.shields.io/badge/all_contributors-52-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-53-orange.svg?style=flat-square)](#contributors-) Your one-stop tool for generating accurate and well-tested models for representing the message payloads. Use it as a tool in your development workflow, or a library in a larger integrations, entirely in your control. @@ -392,6 +392,7 @@ Thanks go out to these wonderful people ([emoji key](https://allcontributors.org beku-epitome
beku-epitome

💻 👀 ⚠️ Joshua Michael Daly
Joshua Michael Daly

🐛 Daniel KJ
Daniel KJ

💻 ⚠️ 💡 👀 + Bhavik Agarwal
Bhavik Agarwal

🎨 From f9fc5f4876b7706b19db29c646332fcfdfaee2b8 Mon Sep 17 00:00:00 2001 From: Bhavik Agarwal <73033511+Bhavik-ag@users.noreply.github.com> Date: Wed, 24 May 2023 17:39:12 +0530 Subject: [PATCH 04/79] chore(website): add responsive sidebar to examples (#1318) --- .../src/components/examples/Examples.tsx | 210 ++++++++++++------ 1 file changed, 142 insertions(+), 68 deletions(-) diff --git a/modelina-website/src/components/examples/Examples.tsx b/modelina-website/src/components/examples/Examples.tsx index 679490ac39..20f4b5c631 100644 --- a/modelina-website/src/components/examples/Examples.tsx +++ b/modelina-website/src/components/examples/Examples.tsx @@ -28,6 +28,7 @@ interface ModelinaExamplesProps extends WithRouterProps { type ModelinaExamplesState = { selectedExample?: string; + showMenu: boolean; }; class Examples extends React.Component< @@ -37,7 +38,8 @@ class Examples extends React.Component< constructor(props: ModelinaExamplesProps) { super(props); this.state = { - selectedExample: undefined + selectedExample: undefined, + showMenu: false }; this.setNewQuery = this.setNewQuery.bind(this); } @@ -49,7 +51,7 @@ class Examples extends React.Component< const newQuery = { query: { ...this.props.router.query } }; - if(queryValue) { + if (queryValue) { /* eslint-disable-next-line security/detect-object-injection */ newQuery.query[queryKey] = String(queryValue); } else { @@ -58,7 +60,7 @@ class Examples extends React.Component< Router.push(newQuery, undefined, { scroll: true }); } render() { - let { selectedExample } = this.state; + let { selectedExample, showMenu } = this.state; const query = this.props.router.query as ExampleQueryOptions; if (query.selectedExample !== undefined) { @@ -66,82 +68,154 @@ class Examples extends React.Component< } let example: Example | undefined; - if(selectedExample) { + if (selectedExample) { example = (ExamplesList as any)[selectedExample]; } - + return (
-
-
- { - examplesIterator.map((value) => { - return
{this.setNewQuery('selectedExample', value[0])}}>{value[1].displayName}
- }) - } -
-
- { - example ? -
-
- -
- {example.description} - Edit Description +
+ {!showMenu && ( +
+ +
+ )} + { + showMenu && ( +
+
+
+
{ this.setState({ showMenu: false }) }} + >
-
-
-
- + +
+
+ +
+
+ +
-
-
-
- +
+ {/* Force sidebar to shrink to fit close icon */}
- : -
-
- + ) + } + +
+
+
+
+ + +
- {ExamplesReadme}
- } +
+
+ { + example ? +
+
+ +
+ {example.description} + Edit Description +
+
+
+
+ +
+
+
+
+ +
+
+
+ : +
+
+ +
+ {ExamplesReadme} +
+ } +
From f34078ae327bf3a61e5564b85674274c6a7936fa Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 24 May 2023 14:10:03 +0200 Subject: [PATCH 05/79] docs: add sambhavgupta0705 as a contributor for review (#1321) * update README.md * update .all-contributorsrc --------- Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 3 ++- README.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index ea20369a16..cdd4f48cd7 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -483,7 +483,8 @@ "avatar_url": "https://avatars.githubusercontent.com/u/81870866?v=4", "profile": "https://github.com/sambhavgupta0705", "contributions": [ - "doc" + "doc", + "review" ] }, { diff --git a/README.md b/README.md index c849fad8e4..9d6a469bdf 100644 --- a/README.md +++ b/README.md @@ -380,7 +380,7 @@ Thanks go out to these wonderful people ([emoji key](https://allcontributors.org Louis Xhaferi
Louis Xhaferi

💻 - Sambhav Gupta
Sambhav Gupta

📖 + Sambhav Gupta
Sambhav Gupta

📖 👀 Abhay Garg
Abhay Garg

💻 💡 ⚠️ 📖 henrikjon
henrikjon

💻 ⚠️ 📖 💡 Mohammad Yasir
Mohammad Yasir

💻 From 4408df788a412abfaf75dda6620fd9e1c170411b Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 24 May 2023 14:11:48 +0200 Subject: [PATCH 06/79] docs: add sambhavgupta0705 as a contributor for design, code, and bug (#1322) * update README.md * update .all-contributorsrc --------- Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 5 ++++- README.md | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index cdd4f48cd7..272d447cb9 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -484,7 +484,10 @@ "profile": "https://github.com/sambhavgupta0705", "contributions": [ "doc", - "review" + "review", + "design", + "code", + "bug" ] }, { diff --git a/README.md b/README.md index 9d6a469bdf..ed5131c57b 100644 --- a/README.md +++ b/README.md @@ -380,7 +380,7 @@ Thanks go out to these wonderful people ([emoji key](https://allcontributors.org Louis Xhaferi
Louis Xhaferi

💻 - Sambhav Gupta
Sambhav Gupta

📖 👀 + Sambhav Gupta
Sambhav Gupta

📖 👀 🎨 💻 🐛 Abhay Garg
Abhay Garg

💻 💡 ⚠️ 📖 henrikjon
henrikjon

💻 ⚠️ 📖 💡 Mohammad Yasir
Mohammad Yasir

💻 From 0dc5d8df64c36b2466b3c356d82c161dc668c393 Mon Sep 17 00:00:00 2001 From: asyncapi-bot Date: Wed, 24 May 2023 17:42:58 +0200 Subject: [PATCH 07/79] ci: update of files from global .github repo (#1324) --- .github/workflows/if-nodejs-release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/if-nodejs-release.yml b/.github/workflows/if-nodejs-release.yml index 6f7db57520..4938a37dad 100644 --- a/.github/workflows/if-nodejs-release.yml +++ b/.github/workflows/if-nodejs-release.yml @@ -101,7 +101,7 @@ jobs: run: npm install - if: steps.packagejson.outputs.exists == 'true' name: Add plugin for conventional commits for semantic-release - run: npm install conventional-changelog-conventionalcommits@5.0.0 + run: npm install --save-dev conventional-changelog-conventionalcommits@5.0.0 - if: steps.packagejson.outputs.exists == 'true' name: Publish to any of NPM, Github, and Docker Hub id: release @@ -123,4 +123,4 @@ jobs: fields: repo,action,workflow text: 'Release workflow failed in release job' env: - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_CI_FAIL_NOTIFY }} \ No newline at end of file + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_CI_FAIL_NOTIFY }} From e0185a4f646485f12888fd07e3e0ec4ca2c7f501 Mon Sep 17 00:00:00 2001 From: Jonas Lagoni Date: Thu, 25 May 2023 14:34:49 +0200 Subject: [PATCH 08/79] feat: add support for AVRO, OpenAPI and RAML schema support for AsyncAPI (#1142) --- README.md | 2 +- docs/usage.md | 11 +- examples/README.md | 6 +- examples/asyncapi-avro-schema/README.md | 17 ++ .../__snapshots__/index.spec.ts.snap | 36 ++++ examples/asyncapi-avro-schema/index.spec.ts | 14 ++ examples/asyncapi-avro-schema/index.ts | 50 ++++++ examples/asyncapi-avro-schema/package.json | 10 ++ examples/asyncapi-openapi-schema/README.md | 17 ++ .../__snapshots__/index.spec.ts.snap | 30 ++++ .../asyncapi-openapi-schema/index.spec.ts | 14 ++ examples/asyncapi-openapi-schema/index.ts | 43 +++++ examples/asyncapi-openapi-schema/package.json | 10 ++ examples/asyncapi-raml-schema/README.md | 17 ++ .../__snapshots__/index.spec.ts.snap | 30 ++++ examples/asyncapi-raml-schema/index.spec.ts | 14 ++ examples/asyncapi-raml-schema/index.ts | 42 +++++ examples/asyncapi-raml-schema/package.json | 10 ++ .../integrate-with-react/package-lock.json | 115 +++++++++---- package-lock.json | 155 ++++++++++++++---- package.json | 3 + src/processors/AsyncAPIInputProcessor.ts | 19 ++- .../processors/AsyncAPIInputProcessor.spec.ts | 2 +- 23 files changed, 583 insertions(+), 84 deletions(-) create mode 100644 examples/asyncapi-avro-schema/README.md create mode 100644 examples/asyncapi-avro-schema/__snapshots__/index.spec.ts.snap create mode 100644 examples/asyncapi-avro-schema/index.spec.ts create mode 100644 examples/asyncapi-avro-schema/index.ts create mode 100644 examples/asyncapi-avro-schema/package.json create mode 100644 examples/asyncapi-openapi-schema/README.md create mode 100644 examples/asyncapi-openapi-schema/__snapshots__/index.spec.ts.snap create mode 100644 examples/asyncapi-openapi-schema/index.spec.ts create mode 100644 examples/asyncapi-openapi-schema/index.ts create mode 100644 examples/asyncapi-openapi-schema/package.json create mode 100644 examples/asyncapi-raml-schema/README.md create mode 100644 examples/asyncapi-raml-schema/__snapshots__/index.spec.ts.snap create mode 100644 examples/asyncapi-raml-schema/index.spec.ts create mode 100644 examples/asyncapi-raml-schema/index.ts create mode 100644 examples/asyncapi-raml-schema/package.json diff --git a/README.md b/README.md index ed5131c57b..62657690bf 100644 --- a/README.md +++ b/README.md @@ -194,7 +194,7 @@ The following table provides a short summary of available features for supported AsyncAPI - We support the following AsyncAPI versions: 2.0.0 -> 2.6.0, which generates models for all the defined message payloads. + We support the following AsyncAPI versions: 2.0.0 -> 2.6.0, which generates models for all the defined message payloads. It supports the following schemaFormats AsyncAPI Schema object, JSON Schema draft 7, AVRO 1.9, RAML 1.0 data type, and OpenAPI 3.0 Schema. JSON Schema diff --git a/docs/usage.md b/docs/usage.md index a59916657c..3b9129810c 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -86,21 +86,16 @@ There are two ways to generate models for an AsyncAPI document. - [Generate from a parsed AsyncAPI 2.x document, from the old v1 parser](../examples/asyncapi-from-v1-parser) - [Generate from an AsyncAPI 2.x JS object](../examples/asyncapi-from-object) -The library expects the `asyncapi` property for the document to be set in order to understand the input format. - -The message payloads, since it is a JSON Schema variant, is [interpreted as a such](./inputs/JSON_Schema.md). +The message payloads, regardless of schemaFormat, are converted to a JSON Schema variant and is [interpreted as a such](./inputs/JSON_Schema.md). ### Limitations and Compatibility These are the current known limitation of the AsyncAPI input. -#### Message Schema formats -Currently, only a limited number of schema formats are supported and we currently rely on the [AsyncAPI parser](https://github.com/asyncapi/parser-js/) to handle those schema formats and convert them into [AsyncAPI Schema format](https://github.com/asyncapi/parser-js/#custom-message-parsers). At some point in the future, Modelina will support all native schema formats, so it does not matter which standard you use to define the message payloads, you will be able to generate models from it. - #### Polymorphism Through the AsyncAPI Schema you are able to use `discriminator` for achieving polymorphism. Current version of Modelina does not generate the expected inheritance of models, instead it's current behavior is to [merge the schemas together](./inputs/JSON_Schema.md#processing-sub-schemas). This means you will still get access to the properties that missing inherited model has, but without the inheritance. -Long term if this is something you wish was supported, voice your [opionion here](https://github.com/asyncapi/modelina/issues/108). +Long term if this is something you wish was supported, voice your [opinion here](https://github.com/asyncapi/modelina/issues/108). ## Generate models from JSON Schema documents @@ -148,7 +143,7 @@ These are the current known limitation of the OpenAPI inputs. Through the OpenAPI 3.0 Schema you are able to use `discriminator` for achieving polymorphism. Current version of Modelina does not generate the expected inheritance of models, instead it's current behavior is to [merge the schemas together](./inputs/JSON_Schema.md#processing-sub-schemas). This means you will still get access to the properties that missing inherited model has, but without the inheritance. -Long term if this is something you wish was supported, voice your [opionion here](https://github.com/asyncapi/modelina/issues/108). +Long term if this is something you wish was supported, voice your [opinion here](https://github.com/asyncapi/modelina/issues/108). ## Generate models from TypeScript type files diff --git a/examples/README.md b/examples/README.md index c961eb12e6..70bfb7e79b 100644 --- a/examples/README.md +++ b/examples/README.md @@ -32,6 +32,9 @@ We love contributions and new examples that does not already exist, you can foll ## Input examples These examples show a specific input and how they can be used: - [asyncapi-from-object](./asyncapi-from-object) - A basic example where an AsyncAPI JS object is used to generate models. +- [asyncapi-avro-schema](./asyncapi-avro-schema) - A basic example of how to use Modelina with an AsyncAPI document using AVRO 1.9 as schema format for the payload. +- [asyncapi-openapi-schema](./asyncapi-openapi-schema) - A basic example of how to use Modelina with an AsyncAPI document using OpenAPI 3.0 Schema for the payload. +- [asyncapi-raml-schema](./asyncapi-raml-schema) - A basic example of how to use Modelina with an AsyncAPI document using RAML 1.0 data types as payload format. - [asyncapi-from-parser](./asyncapi-from-parser) - A basic example where an AsyncAPI JS object from the [parser-js](https://github.com/asyncapi/parser-js) is used to generate models. - [asyncapi-from-v1-parser](./asyncapi-from-v1-parser) - A basic example where an AsyncAPI JS object from the old v1 [parser-js](https://github.com/asyncapi/parser-js) is used to generate models. - [json-schema-draft7-from-object](./json-schema-draft7-from-object) - A basic example where a JSON Schema draft 7 JS object is used to generate models. @@ -44,14 +47,13 @@ These examples show a specific input and how they can be used: These are examples that can be applied in all scenarios. - [include-custom-function](./include-custom-function) - A basic example where a custom function is included. - [overwrite-naming-formatting](./overwrite-naming-formatting) - A basic example how to overwrite default naming format constraint in this case, overwriting returning a constant case format. -- [overwrite-default-constraint](./overwrite-default-constraint) - A basic example how to overwrite the entire constraint logic and not just a single single part of the default behavior, in this case overwriting the model naming constraint. +- [overwrite-default-constraint](./overwrite-default-constraint/) - A basic example how to overwrite the entire constraint logic and not just a single part of the default behavior, in this case overwriting the model naming constraint. - [custom-logging](./custom-logging) - A basic example where a custom logger is used. - [generate-to-files](./generate-to-files) - A basic example that shows how you can generate the models directly to files. - [indentation-type-and-size](./indentation-type-and-size) - This example shows how to change the indentation type and size of the generated model. - [change-type-mapping](./change-type-mapping) - A basic example showing how to change the type of a model in some context. - [change-type-mapping-with-dependency](./change-type-mapping-with-dependency) - A basic example showing how to use the dependency manager to inject your own custom type with a dependency instead of the default type. - ## Simple generator examples These are all the basic generator examples that shows a bare minimal example of a generator: - [generate-typescript-models](./generate-typescript-models) - A basic example to generate TypeScript data models diff --git a/examples/asyncapi-avro-schema/README.md b/examples/asyncapi-avro-schema/README.md new file mode 100644 index 0000000000..befdfd98b6 --- /dev/null +++ b/examples/asyncapi-avro-schema/README.md @@ -0,0 +1,17 @@ +# AsyncAPI using AVRO 1.9 schema + +A basic example of how to use Modelina with an AsyncAPI document using AVRO 1.9 as schema format for the payload. + +## How to run this example + +Run this example using: + +```sh +npm i && npm run start +``` + +If you are on Windows, use the `start:windows` script instead: + +```sh +npm i && npm run start:windows +``` diff --git a/examples/asyncapi-avro-schema/__snapshots__/index.spec.ts.snap b/examples/asyncapi-avro-schema/__snapshots__/index.spec.ts.snap new file mode 100644 index 0000000000..2f9435b5a6 --- /dev/null +++ b/examples/asyncapi-avro-schema/__snapshots__/index.spec.ts.snap @@ -0,0 +1,36 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Should be able to process an AsyncAPI object with AVRO schema type and should log expected output to console 1`] = ` +Array [ + "class ComDotCompanyDotUser { + private _displayName: string; + private _email: string; + private _age: number; + private _additionalProperties?: Map; + + constructor(input: { + displayName: string, + email: string, + age: number, + additionalProperties?: Map, + }) { + this._displayName = input.displayName; + this._email = input.email; + this._age = input.age; + this._additionalProperties = input.additionalProperties; + } + + get displayName(): string { return this._displayName; } + set displayName(displayName: string) { this._displayName = displayName; } + + get email(): string { return this._email; } + set email(email: string) { this._email = email; } + + get age(): number { return this._age; } + set age(age: number) { this._age = age; } + + get additionalProperties(): Map | undefined { return this._additionalProperties; } + set additionalProperties(additionalProperties: Map | undefined) { this._additionalProperties = additionalProperties; } +}", +] +`; diff --git a/examples/asyncapi-avro-schema/index.spec.ts b/examples/asyncapi-avro-schema/index.spec.ts new file mode 100644 index 0000000000..077a698dbc --- /dev/null +++ b/examples/asyncapi-avro-schema/index.spec.ts @@ -0,0 +1,14 @@ +const spy = jest.spyOn(global.console, 'log').mockImplementation(() => { + return; +}); +import { generate } from './index'; +describe('Should be able to process an AsyncAPI object with AVRO schema type', () => { + afterAll(() => { + jest.restoreAllMocks(); + }); + test('and should log expected output to console', async () => { + await generate(); + expect(spy.mock.calls.length).toEqual(1); + expect(spy.mock.calls[0]).toMatchSnapshot(); + }); +}); diff --git a/examples/asyncapi-avro-schema/index.ts b/examples/asyncapi-avro-schema/index.ts new file mode 100644 index 0000000000..9dfe78a06d --- /dev/null +++ b/examples/asyncapi-avro-schema/index.ts @@ -0,0 +1,50 @@ +import { TypeScriptGenerator } from '../../src'; + +const generator = new TypeScriptGenerator(); +const AsyncAPIDocument = { + asyncapi: '2.6.0', + info: { + title: 'Example with Avro', + version: '0.1.0' + }, + channels: { + example: { + publish: { + message: { + schemaFormat: 'application/vnd.apache.avro;version=1.9.0', + payload: { + type: 'record', + name: 'User', + namespace: 'com.company', + doc: 'User information', + fields: [ + { + name: 'displayName', + type: 'string' + }, + { + name: 'email', + type: 'string' + }, + { + name: 'age', + type: 'int' + } + ] + } + } + } + } + } +}; + +export async function generate(): Promise { + const models = await generator.generate(AsyncAPIDocument); + for (const model of models) { + console.log(model.result); + } +} + +if (require.main === module) { + generate(); +} diff --git a/examples/asyncapi-avro-schema/package.json b/examples/asyncapi-avro-schema/package.json new file mode 100644 index 0000000000..9eb724b82e --- /dev/null +++ b/examples/asyncapi-avro-schema/package.json @@ -0,0 +1,10 @@ +{ + "config" : { "example_name" : "asyncapi-avro-schema" }, + "scripts": { + "install": "cd ../.. && npm i", + "start": "../../node_modules/.bin/ts-node --cwd ../../ ./examples/$npm_package_config_example_name/index.ts", + "start:windows": "..\\..\\node_modules\\.bin\\ts-node --cwd ..\\..\\ .\\examples\\%npm_package_config_example_name%\\index.ts", + "test": "../../node_modules/.bin/jest --config=../../jest.config.js ./examples/$npm_package_config_example_name/index.spec.ts", + "test:windows": "..\\..\\node_modules\\.bin\\jest --config=..\\..\\jest.config.js examples/%npm_package_config_example_name%/index.spec.ts" + } +} diff --git a/examples/asyncapi-openapi-schema/README.md b/examples/asyncapi-openapi-schema/README.md new file mode 100644 index 0000000000..209b21481a --- /dev/null +++ b/examples/asyncapi-openapi-schema/README.md @@ -0,0 +1,17 @@ +# AsyncAPI using OpenAPI 3.0 schema + +A basic example of how to use Modelina with an AsyncAPI document using OpenAPI 3.0 Schema for the payload. + +## How to run this example + +Run this example using: + +```sh +npm i && npm run start +``` + +If you are on Windows, use the `start:windows` script instead: + +```sh +npm i && npm run start:windows +``` diff --git a/examples/asyncapi-openapi-schema/__snapshots__/index.spec.ts.snap b/examples/asyncapi-openapi-schema/__snapshots__/index.spec.ts.snap new file mode 100644 index 0000000000..f5a1982993 --- /dev/null +++ b/examples/asyncapi-openapi-schema/__snapshots__/index.spec.ts.snap @@ -0,0 +1,30 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Should be able to process an AsyncAPI object with OpenAPI schema type and should log expected output to console 1`] = ` +Array [ + "class AnonymousSchema_1 { + private _title?: string; + private _author?: string; + private _additionalProperties?: Map; + + constructor(input: { + title?: string, + author?: string, + additionalProperties?: Map, + }) { + this._title = input.title; + this._author = input.author; + this._additionalProperties = input.additionalProperties; + } + + get title(): string | undefined { return this._title; } + set title(title: string | undefined) { this._title = title; } + + get author(): string | undefined { return this._author; } + set author(author: string | undefined) { this._author = author; } + + get additionalProperties(): Map | undefined { return this._additionalProperties; } + set additionalProperties(additionalProperties: Map | undefined) { this._additionalProperties = additionalProperties; } +}", +] +`; diff --git a/examples/asyncapi-openapi-schema/index.spec.ts b/examples/asyncapi-openapi-schema/index.spec.ts new file mode 100644 index 0000000000..c4a1fa601e --- /dev/null +++ b/examples/asyncapi-openapi-schema/index.spec.ts @@ -0,0 +1,14 @@ +const spy = jest.spyOn(global.console, 'log').mockImplementation(() => { + return; +}); +import { generate } from './index'; +describe('Should be able to process an AsyncAPI object with OpenAPI schema type', () => { + afterAll(() => { + jest.restoreAllMocks(); + }); + test('and should log expected output to console', async () => { + await generate(); + expect(spy.mock.calls.length).toEqual(1); + expect(spy.mock.calls[0]).toMatchSnapshot(); + }); +}); diff --git a/examples/asyncapi-openapi-schema/index.ts b/examples/asyncapi-openapi-schema/index.ts new file mode 100644 index 0000000000..bfe1dff3c4 --- /dev/null +++ b/examples/asyncapi-openapi-schema/index.ts @@ -0,0 +1,43 @@ +import { TypeScriptGenerator } from '../../src'; + +const generator = new TypeScriptGenerator(); +const AsyncAPIDocument = { + asyncapi: '2.0.0', + info: { + title: 'Example with OpenAPI', + version: '0.1.0' + }, + channels: { + example: { + publish: { + message: { + schemaFormat: 'application/vnd.oai.openapi;version=3.0.0', + payload: { + type: 'object', + properties: { + title: { + type: 'string', + nullable: true + }, + author: { + type: 'string', + example: 'Jack Johnson' + } + } + } + } + } + } + } +}; + +export async function generate(): Promise { + const models = await generator.generate(AsyncAPIDocument); + for (const model of models) { + console.log(model.result); + } +} + +if (require.main === module) { + generate(); +} diff --git a/examples/asyncapi-openapi-schema/package.json b/examples/asyncapi-openapi-schema/package.json new file mode 100644 index 0000000000..70313b9849 --- /dev/null +++ b/examples/asyncapi-openapi-schema/package.json @@ -0,0 +1,10 @@ +{ + "config" : { "example_name" : "asyncapi-openapi-schema" }, + "scripts": { + "install": "cd ../.. && npm i", + "start": "../../node_modules/.bin/ts-node --cwd ../../ ./examples/$npm_package_config_example_name/index.ts", + "start:windows": "..\\..\\node_modules\\.bin\\ts-node --cwd ..\\..\\ .\\examples\\%npm_package_config_example_name%\\index.ts", + "test": "../../node_modules/.bin/jest --config=../../jest.config.js ./examples/$npm_package_config_example_name/index.spec.ts", + "test:windows": "..\\..\\node_modules\\.bin\\jest --config=..\\..\\jest.config.js examples/%npm_package_config_example_name%/index.spec.ts" + } +} diff --git a/examples/asyncapi-raml-schema/README.md b/examples/asyncapi-raml-schema/README.md new file mode 100644 index 0000000000..4d014d7f5d --- /dev/null +++ b/examples/asyncapi-raml-schema/README.md @@ -0,0 +1,17 @@ +# AsyncAPI using RAML 1.0 data types + +A basic example of how to use Modelina with an AsyncAPI document using RAML 1.0 data types as payload format. + +## How to run this example + +Run this example using: + +```sh +npm i && npm run start +``` + +If you are on Windows, use the `start:windows` script instead: + +```sh +npm i && npm run start:windows +``` diff --git a/examples/asyncapi-raml-schema/__snapshots__/index.spec.ts.snap b/examples/asyncapi-raml-schema/__snapshots__/index.spec.ts.snap new file mode 100644 index 0000000000..9368197ed8 --- /dev/null +++ b/examples/asyncapi-raml-schema/__snapshots__/index.spec.ts.snap @@ -0,0 +1,30 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Should be able to process an AsyncAPI object with RAML schema type and should log expected output to console 1`] = ` +Array [ + "class AnonymousSchema_1 { + private _title: string; + private _author: string; + private _additionalProperties?: Map; + + constructor(input: { + title: string, + author: string, + additionalProperties?: Map, + }) { + this._title = input.title; + this._author = input.author; + this._additionalProperties = input.additionalProperties; + } + + get title(): string { return this._title; } + set title(title: string) { this._title = title; } + + get author(): string { return this._author; } + set author(author: string) { this._author = author; } + + get additionalProperties(): Map | undefined { return this._additionalProperties; } + set additionalProperties(additionalProperties: Map | undefined) { this._additionalProperties = additionalProperties; } +}", +] +`; diff --git a/examples/asyncapi-raml-schema/index.spec.ts b/examples/asyncapi-raml-schema/index.spec.ts new file mode 100644 index 0000000000..08a8a87b12 --- /dev/null +++ b/examples/asyncapi-raml-schema/index.spec.ts @@ -0,0 +1,14 @@ +const spy = jest.spyOn(global.console, 'log').mockImplementation(() => { + return; +}); +import { generate } from './index'; +describe('Should be able to process an AsyncAPI object with RAML schema type', () => { + afterAll(() => { + jest.restoreAllMocks(); + }); + test('and should log expected output to console', async () => { + await generate(); + expect(spy.mock.calls.length).toEqual(1); + expect(spy.mock.calls[0]).toMatchSnapshot(); + }); +}); diff --git a/examples/asyncapi-raml-schema/index.ts b/examples/asyncapi-raml-schema/index.ts new file mode 100644 index 0000000000..70379a8736 --- /dev/null +++ b/examples/asyncapi-raml-schema/index.ts @@ -0,0 +1,42 @@ +import { TypeScriptGenerator } from '../../src'; + +const generator = new TypeScriptGenerator(); +const AsyncAPIDocument = { + asyncapi: '2.6.0', + info: { + title: 'Example with RAML', + version: '0.1.0' + }, + channels: { + example: { + publish: { + message: { + schemaFormat: 'application/raml+yaml;version=1.0', + payload: { + type: 'object', + properties: { + title: 'string', + author: { + type: 'string', + examples: { + anExample: 'Jack Johnson' + } + } + } + } + } + } + } + } +}; + +export async function generate(): Promise { + const models = await generator.generate(AsyncAPIDocument); + for (const model of models) { + console.log(model.result); + } +} + +if (require.main === module) { + generate(); +} diff --git a/examples/asyncapi-raml-schema/package.json b/examples/asyncapi-raml-schema/package.json new file mode 100644 index 0000000000..236f4cd84a --- /dev/null +++ b/examples/asyncapi-raml-schema/package.json @@ -0,0 +1,10 @@ +{ + "config" : { "example_name" : "asyncapi-raml-schema" }, + "scripts": { + "install": "cd ../.. && npm i", + "start": "../../node_modules/.bin/ts-node --cwd ../../ ./examples/$npm_package_config_example_name/index.ts", + "start:windows": "..\\..\\node_modules\\.bin\\ts-node --cwd ..\\..\\ .\\examples\\%npm_package_config_example_name%\\index.ts", + "test": "../../node_modules/.bin/jest --config=../../jest.config.js ./examples/$npm_package_config_example_name/index.spec.ts", + "test:windows": "..\\..\\node_modules\\.bin\\jest --config=..\\..\\jest.config.js examples/%npm_package_config_example_name%/index.spec.ts" + } +} diff --git a/examples/integrate-with-react/package-lock.json b/examples/integrate-with-react/package-lock.json index f2fb8c8087..d9681a5f12 100644 --- a/examples/integrate-with-react/package-lock.json +++ b/examples/integrate-with-react/package-lock.json @@ -14778,6 +14778,19 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -17186,12 +17199,14 @@ "@csstools/postcss-unset-value": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", - "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==" + "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", + "requires": {} }, "@csstools/selector-specificity": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz", - "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==" + "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==", + "requires": {} }, "@eslint/eslintrc": { "version": "1.3.0", @@ -18585,12 +18600,14 @@ "acorn-import-assertions": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==" + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "requires": {} }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "requires": {} }, "acorn-node": { "version": "1.8.2", @@ -18870,7 +18887,8 @@ "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} }, "json-schema-traverse": { "version": "0.4.1", @@ -18933,7 +18951,8 @@ "babel-plugin-named-asset-import": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz", - "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==" + "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==", + "requires": {} }, "babel-plugin-polyfill-corejs2": { "version": "0.3.2", @@ -19593,7 +19612,8 @@ "css-declaration-sorter": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.0.tgz", - "integrity": "sha512-OGT677UGHJTAVMRhPO+HJ4oKln3wkBTwtDFH0ojbqm+MJm6xuDMHp2nkhh/ThaBqq20IbraBQSWKfSLNHQO9Og==" + "integrity": "sha512-OGT677UGHJTAVMRhPO+HJ4oKln3wkBTwtDFH0ojbqm+MJm6xuDMHp2nkhh/ThaBqq20IbraBQSWKfSLNHQO9Og==", + "requires": {} }, "css-has-pseudo": { "version": "3.0.4", @@ -19660,7 +19680,8 @@ "css-prefers-color-scheme": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", - "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==" + "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", + "requires": {} }, "css-select": { "version": "2.1.0", @@ -19763,7 +19784,8 @@ "cssnano-utils": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==" + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "requires": {} }, "csso": { "version": "4.2.0", @@ -20638,7 +20660,8 @@ "eslint-plugin-react-hooks": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==" + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "requires": {} }, "eslint-plugin-testing-library": { "version": "5.6.0", @@ -21167,7 +21190,8 @@ "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} }, "chalk": { "version": "4.1.2", @@ -21688,7 +21712,8 @@ "icss-utils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==" + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "requires": {} }, "idb": { "version": "7.0.2", @@ -22603,7 +22628,8 @@ "jest-pnp-resolver": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==" + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "requires": {} }, "jest-regex-util": { "version": "27.5.1", @@ -24048,7 +24074,8 @@ "postcss-browser-comments": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz", - "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==" + "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==", + "requires": {} }, "postcss-calc": { "version": "8.2.4", @@ -24146,22 +24173,26 @@ "postcss-discard-comments": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", - "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==" + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "requires": {} }, "postcss-discard-duplicates": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==" + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "requires": {} }, "postcss-discard-empty": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==" + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "requires": {} }, "postcss-discard-overridden": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==" + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "requires": {} }, "postcss-double-position-gradients": { "version": "3.1.2", @@ -24183,7 +24214,8 @@ "postcss-flexbugs-fixes": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", - "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==" + "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", + "requires": {} }, "postcss-focus-visible": { "version": "6.0.4", @@ -24204,12 +24236,14 @@ "postcss-font-variant": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", - "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==" + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "requires": {} }, "postcss-gap-properties": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", - "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==" + "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", + "requires": {} }, "postcss-image-set-function": { "version": "4.0.7", @@ -24232,7 +24266,8 @@ "postcss-initial": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", - "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==" + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", + "requires": {} }, "postcss-js": { "version": "4.0.0", @@ -24273,12 +24308,14 @@ "postcss-logical": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", - "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==" + "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", + "requires": {} }, "postcss-media-minmax": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", - "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==" + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "requires": {} }, "postcss-merge-longhand": { "version": "5.1.6", @@ -24339,7 +24376,8 @@ "postcss-modules-extract-imports": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==" + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "requires": {} }, "postcss-modules-local-by-default": { "version": "4.0.0", @@ -24397,7 +24435,8 @@ "postcss-normalize-charset": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==" + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "requires": {} }, "postcss-normalize-display-values": { "version": "5.1.0", @@ -24490,7 +24529,8 @@ "postcss-page-break": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", - "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==" + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "requires": {} }, "postcss-place": { "version": "7.0.5", @@ -24582,7 +24622,8 @@ "postcss-replace-overflow-wrap": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", - "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==" + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "requires": {} }, "postcss-selector-not": { "version": "6.0.1", @@ -25432,7 +25473,8 @@ "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} }, "json-schema-traverse": { "version": "0.4.1", @@ -25880,7 +25922,8 @@ "style-loader": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", - "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==" + "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", + "requires": {} }, "stylehacks": { "version": "5.1.0", @@ -26232,6 +26275,12 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "peer": true + }, "unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -26557,7 +26606,8 @@ "ws": { "version": "8.8.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", - "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==" + "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", + "requires": {} } } }, @@ -26932,7 +26982,8 @@ "ws": { "version": "7.5.9", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==" + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} }, "xml-name-validator": { "version": "3.0.0", diff --git a/package-lock.json b/package-lock.json index ea152121c7..e9056f0c48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,10 @@ "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.9", "@apidevtools/swagger-parser": "^10.0.3", + "@asyncapi/avro-schema-parser": "^3.0.0", + "@asyncapi/openapi-schema-parser": "^3.0.0", "@asyncapi/parser": "^2.0.0", + "@asyncapi/raml-dt-schema-parser": "^4.0.0", "@swc/core": "^1.3.5", "@swc/jest": "^0.2.23", "alterschema": "^1.1.2", @@ -86,6 +89,29 @@ "openapi-types": ">=7" } }, + "node_modules/@asyncapi/avro-schema-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@asyncapi/avro-schema-parser/-/avro-schema-parser-3.0.0.tgz", + "integrity": "sha512-9zxRwtVV0dcDQgA5dN8HmfigfflgMRSJnSElhWZneClF8JhpPOKVs0N8UA1PmE9Sax5uOqx95ONboYnnz4xTLw==", + "dependencies": { + "@asyncapi/parser": "^2.0.0", + "@types/json-schema": "^7.0.11", + "avsc": "^5.7.6", + "conventional-changelog-conventionalcommits": "^5.0.0" + } + }, + "node_modules/@asyncapi/openapi-schema-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@asyncapi/openapi-schema-parser/-/openapi-schema-parser-3.0.0.tgz", + "integrity": "sha512-3s5rI//5KSvrPfv/jiiQi5uOerMc7Y7ejVDveuI7hhaujC+NemFwcc8imMwZzNHF6BsBGc9/HVtSjYIkQZpk4Q==", + "dependencies": { + "@asyncapi/parser": "^2.0.0", + "@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0", + "ajv": "^8.11.0", + "ajv-errors": "^3.0.0", + "ajv-formats": "^2.1.1" + } + }, "node_modules/@asyncapi/parser": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@asyncapi/parser/-/parser-2.0.0.tgz", @@ -120,19 +146,6 @@ "conventional-changelog-conventionalcommits": "^5.0.0" } }, - "node_modules/@asyncapi/parser/node_modules/conventional-changelog-conventionalcommits": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-5.0.0.tgz", - "integrity": "sha512-lCDbA+ZqVFQGUj7h9QBKoIpLhl8iihkO0nCTyRNzuXtcd7ubODpYB04IFy31JloiJgG0Uovu8ot8oxRzn7Nwtw==", - "dependencies": { - "compare-func": "^2.0.0", - "lodash": "^4.17.15", - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@asyncapi/parserV1": { "name": "@asyncapi/parser", "version": "1.18.1", @@ -189,6 +202,18 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/@asyncapi/raml-dt-schema-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@asyncapi/raml-dt-schema-parser/-/raml-dt-schema-parser-4.0.0.tgz", + "integrity": "sha512-dauYocjmyIKo7oq1rzBOY+mDHzvfa9j8p2luz4co2igZM9HN0L+Xck1M81uvye4Z5zTNW/BG2hu9ngiZAXcQng==", + "dependencies": { + "@asyncapi/parser": "^2.0.0", + "conventional-changelog-conventionalcommits": "^5.0.0", + "js-yaml": "^4.1.0", + "ramldt2jsonschema": "^1.2.3", + "webapi-parser": "^0.5.0" + } + }, "node_modules/@asyncapi/specs": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-4.1.2.tgz", @@ -4555,6 +4580,19 @@ "node": ">= 0.6" } }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-5.0.0.tgz", + "integrity": "sha512-lCDbA+ZqVFQGUj7h9QBKoIpLhl8iihkO0nCTyRNzuXtcd7ubODpYB04IFy31JloiJgG0Uovu8ot8oxRzn7Nwtw==", + "dependencies": { + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/convert-source-map": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", @@ -13494,6 +13532,29 @@ "z-schema": "^5.0.1" } }, + "@asyncapi/avro-schema-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@asyncapi/avro-schema-parser/-/avro-schema-parser-3.0.0.tgz", + "integrity": "sha512-9zxRwtVV0dcDQgA5dN8HmfigfflgMRSJnSElhWZneClF8JhpPOKVs0N8UA1PmE9Sax5uOqx95ONboYnnz4xTLw==", + "requires": { + "@asyncapi/parser": "^2.0.0", + "@types/json-schema": "^7.0.11", + "avsc": "^5.7.6", + "conventional-changelog-conventionalcommits": "^5.0.0" + } + }, + "@asyncapi/openapi-schema-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@asyncapi/openapi-schema-parser/-/openapi-schema-parser-3.0.0.tgz", + "integrity": "sha512-3s5rI//5KSvrPfv/jiiQi5uOerMc7Y7ejVDveuI7hhaujC+NemFwcc8imMwZzNHF6BsBGc9/HVtSjYIkQZpk4Q==", + "requires": { + "@asyncapi/parser": "^2.0.0", + "@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0", + "ajv": "^8.11.0", + "ajv-errors": "^3.0.0", + "ajv-formats": "^2.1.1" + } + }, "@asyncapi/parser": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@asyncapi/parser/-/parser-2.0.0.tgz", @@ -13527,16 +13588,6 @@ "@types/json-schema": "^7.0.11", "conventional-changelog-conventionalcommits": "^5.0.0" } - }, - "conventional-changelog-conventionalcommits": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-5.0.0.tgz", - "integrity": "sha512-lCDbA+ZqVFQGUj7h9QBKoIpLhl8iihkO0nCTyRNzuXtcd7ubODpYB04IFy31JloiJgG0Uovu8ot8oxRzn7Nwtw==", - "requires": { - "compare-func": "^2.0.0", - "lodash": "^4.17.15", - "q": "^1.5.1" - } } } }, @@ -13590,6 +13641,18 @@ } } }, + "@asyncapi/raml-dt-schema-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@asyncapi/raml-dt-schema-parser/-/raml-dt-schema-parser-4.0.0.tgz", + "integrity": "sha512-dauYocjmyIKo7oq1rzBOY+mDHzvfa9j8p2luz4co2igZM9HN0L+Xck1M81uvye4Z5zTNW/BG2hu9ngiZAXcQng==", + "requires": { + "@asyncapi/parser": "^2.0.0", + "conventional-changelog-conventionalcommits": "^5.0.0", + "js-yaml": "^4.1.0", + "ramldt2jsonschema": "^1.2.3", + "webapi-parser": "^0.5.0" + } + }, "@asyncapi/specs": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-4.1.2.tgz", @@ -14676,12 +14739,14 @@ "@jsep-plugin/regex": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.3.tgz", - "integrity": "sha512-XfZgry4DwEZvSFtS/6Y+R48D7qJYJK6R9/yJFyUFHCIUMEEHuJ4X95TDgJp5QkmzfLYvapMPzskV5HpIDrREug==" + "integrity": "sha512-XfZgry4DwEZvSFtS/6Y+R48D7qJYJK6R9/yJFyUFHCIUMEEHuJ4X95TDgJp5QkmzfLYvapMPzskV5HpIDrREug==", + "requires": {} }, "@jsep-plugin/ternary": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@jsep-plugin/ternary/-/ternary-1.1.3.tgz", - "integrity": "sha512-qtLGzCNzPVJ3kdH6/zoLWDPjauHIKiLSBAR71Wa0+PWvGA8wODUQvRgxtpUA5YqAYL3CQ8S4qXhd/9WuWTZirg==" + "integrity": "sha512-qtLGzCNzPVJ3kdH6/zoLWDPjauHIKiLSBAR71Wa0+PWvGA8wODUQvRgxtpUA5YqAYL3CQ8S4qXhd/9WuWTZirg==", + "requires": {} }, "@netlify/esbuild": { "version": "0.14.39", @@ -15717,7 +15782,8 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true + "dev": true, + "requires": {} }, "acorn-walk": { "version": "7.2.0", @@ -15755,12 +15821,14 @@ "ajv-draft-04": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", - "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==" + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "requires": {} }, "ajv-errors": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", - "integrity": "sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==" + "integrity": "sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==", + "requires": {} }, "ajv-formats": { "version": "2.1.1", @@ -16772,6 +16840,16 @@ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, + "conventional-changelog-conventionalcommits": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-5.0.0.tgz", + "integrity": "sha512-lCDbA+ZqVFQGUj7h9QBKoIpLhl8iihkO0nCTyRNzuXtcd7ubODpYB04IFy31JloiJgG0Uovu8ot8oxRzn7Nwtw==", + "requires": { + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" + } + }, "convert-source-map": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", @@ -17543,7 +17621,8 @@ "version": "8.5.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true + "dev": true, + "requires": {} }, "eslint-import-resolver-node": { "version": "0.3.6", @@ -17694,7 +17773,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-i18n-text/-/eslint-plugin-i18n-text-1.0.1.tgz", "integrity": "sha512-3G3UetST6rdqhqW9SfcfzNYMpQXS7wNkJvp6dsXnjzGiku6Iu5hl3B0kmk6lIcFPwYjhQIY+tXVRtK9TlGT7RA==", - "dev": true + "dev": true, + "requires": {} }, "eslint-plugin-import": { "version": "2.25.2", @@ -17771,7 +17851,8 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.10.0.tgz", "integrity": "sha512-FBRIBmWQh2UAfuLSnuYEfmle33jIup9hfkR0X8pkfjeCKNpHUG8qyZI63ahs3aw8CJrv47QJ9ccdK3ZxKH016A==", - "dev": true + "dev": true, + "requires": {} }, "eslint-rule-documentation": { "version": "1.0.23", @@ -19775,7 +19856,8 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true + "dev": true, + "requires": {} }, "jest-regex-util": { "version": "27.0.6", @@ -20970,7 +21052,8 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", - "dev": true + "dev": true, + "requires": {} }, "markdown-link": { "version": "0.1.1", @@ -21804,7 +21887,8 @@ "version": "8.8.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", - "dev": true + "dev": true, + "requires": {} } } }, @@ -23422,7 +23506,8 @@ "version": "7.5.5", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", - "dev": true + "dev": true, + "requires": {} }, "xml-name-validator": { "version": "3.0.0", diff --git a/package.json b/package.json index 115cabc24d..4ea4513039 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,10 @@ "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.9", "@apidevtools/swagger-parser": "^10.0.3", + "@asyncapi/avro-schema-parser": "^3.0.0", + "@asyncapi/openapi-schema-parser": "^3.0.0", "@asyncapi/parser": "^2.0.0", + "@asyncapi/raml-dt-schema-parser": "^4.0.0", "@swc/core": "^1.3.5", "@swc/jest": "^0.2.23", "alterschema": "^1.1.2", diff --git a/src/processors/AsyncAPIInputProcessor.ts b/src/processors/AsyncAPIInputProcessor.ts index 6b8c1dcd1d..f853098104 100644 --- a/src/processors/AsyncAPIInputProcessor.ts +++ b/src/processors/AsyncAPIInputProcessor.ts @@ -1,9 +1,16 @@ +/* eslint-disable no-undef */ +/* eslint-disable @typescript-eslint/no-var-requires */ import { createAsyncAPIDocument, isAsyncAPIDocument, isOldAsyncAPIDocument, - Parser + Parser, + AsyncAPIDocumentInterface, + SchemaInterface as AsyncAPISchema } from '@asyncapi/parser'; +import { AvroSchemaParser } from '@asyncapi/avro-schema-parser'; +import { OpenAPISchemaParser } from '@asyncapi/openapi-schema-parser'; +import { RamlDTSchemaParser } from '@asyncapi/raml-dt-schema-parser'; import { createDetailedAsyncAPI } from '@asyncapi/parser/cjs/utils'; import { AbstractInputProcessor } from './AbstractInputProcessor'; import { JsonSchemaInputProcessor } from './JsonSchemaInputProcessor'; @@ -11,16 +18,18 @@ import { InputMetaModel, ProcessorOptions } from '../models'; import { Logger } from '../utils'; import { AsyncapiV2Schema } from '../models/AsyncapiV2Schema'; import { convertToMetaModel } from '../helpers'; -import type { - AsyncAPIDocumentInterface, - SchemaInterface as AsyncAPISchema -} from '@asyncapi/parser'; /** * Class for processing AsyncAPI inputs */ export class AsyncAPIInputProcessor extends AbstractInputProcessor { private parser = new Parser(); + constructor() { + super(); + this.parser.registerSchemaParser(AvroSchemaParser()); + this.parser.registerSchemaParser(OpenAPISchemaParser()); + this.parser.registerSchemaParser(RamlDTSchemaParser()); + } static supportedVersions = [ '2.0.0', diff --git a/test/processors/AsyncAPIInputProcessor.spec.ts b/test/processors/AsyncAPIInputProcessor.spec.ts index 16b6c98d79..9203e00713 100644 --- a/test/processors/AsyncAPIInputProcessor.spec.ts +++ b/test/processors/AsyncAPIInputProcessor.spec.ts @@ -70,7 +70,7 @@ describe('AsyncAPIInputProcessor', () => { const parsedObject = { asyncapi: '2.6.0' }; expect(processor.shouldProcess(parsedObject)).toEqual(true); }); - test('should not be able to process AsyncAPI 2.x', () => { + test('should not be able to process unsupported AsyncAPI 2.x', () => { const parsedObject = { asyncapi: '2.123.0' }; expect(processor.shouldProcess(parsedObject)).toEqual(false); }); From c769710dacfe56af1924b2709629655ed825c164 Mon Sep 17 00:00:00 2001 From: asyncapi-bot Date: Thu, 25 May 2023 15:02:30 +0200 Subject: [PATCH 09/79] chore(release): v1.7.0 (#1327) --- docs/usage.md | 1 - package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 3b9129810c..247faf4a9e 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -14,7 +14,6 @@ For more specific integration options, please check out the [integration documen - [Understanding the output format](#understanding-the-output-format) - [Generate models from AsyncAPI documents](#generate-models-from-asyncapi-documents) * [Limitations and Compatibility](#limitations-and-compatibility) - + [Message Schema formats](#message-schema-formats) + [Polymorphism](#polymorphism) - [Generate models from JSON Schema documents](#generate-models-from-json-schema-documents) - [Generate models from Swagger 2.0 documents](#generate-models-from-swagger-20-documents) diff --git a/package-lock.json b/package-lock.json index e9056f0c48..c58e8f85c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@asyncapi/modelina", - "version": "1.6.1", + "version": "1.7.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@asyncapi/modelina", - "version": "1.6.1", + "version": "1.7.0", "license": "Apache-2.0", "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.9", diff --git a/package.json b/package.json index 4ea4513039..e48010381f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@asyncapi/modelina", - "version": "1.6.1", + "version": "1.7.0", "description": "Library for generating data models based on inputs such as AsyncAPI, OpenAPI, or JSON Schema documents", "license": "Apache-2.0", "homepage": "https://www.modelina.org", From 75621a90ed04c3be6232dd2b5ecad8fed18ed1d5 Mon Sep 17 00:00:00 2001 From: Rishi <52498617+kaushik-rishi@users.noreply.github.com> Date: Thu, 25 May 2023 19:06:19 +0530 Subject: [PATCH 10/79] chore(website): add System.Text.Json serialization support in the playground (#1325) --- .../src/components/playground/Playground.tsx | 8 +++++- .../options/CSharpGeneratorOptions.tsx | 27 ++++++++++++++++--- .../helpers/GeneratorCode/CSharpGenerator.ts | 7 +++++ .../pages/api/functions/CSharpGenerator.ts | 23 ++++++++-------- modelina-website/src/types/index.ts | 2 ++ 5 files changed, 50 insertions(+), 17 deletions(-) diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index 7c0dd20fad..e6127dc078 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -78,6 +78,7 @@ class Playground extends React.Component< csharpArrayType: 'Array', csharpAutoImplemented: false, csharpOverwriteHashcode: false, + csharpIncludeJson: false, }; hasLoadedQuery: boolean = false; constructor(props: ModelinaPlaygroundProps) { @@ -209,6 +210,10 @@ class Playground extends React.Component< this.config.csharpOverwriteHashcode = query.csharpOverwriteHashcode === 'true'; } + if (query.csharpIncludeJson !== undefined) { + this.config.csharpIncludeJson = + query.csharpIncludeJson === 'true'; + } if (this.props.router.isReady && !this.hasLoadedQuery) { this.hasLoadedQuery = true; this.generateNewCode(this.state.input); @@ -309,7 +314,8 @@ class Playground extends React.Component< value={{ csharpArrayType: this.config.csharpArrayType, csharpAutoImplemented: this.config.csharpAutoImplemented, - csharpOverwriteHashcode: this.config.csharpOverwriteHashcode + csharpOverwriteHashcode: this.config.csharpOverwriteHashcode, + csharpIncludeJson: this.config.csharpIncludeJson }} > diff --git a/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx b/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx index cbd77f80c6..2274e760a1 100644 --- a/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx @@ -20,10 +20,9 @@ class CSharpGeneratorOptions extends React.Component< super(props); this.state = defaultState; this.onChangeArrayType = this.onChangeArrayType.bind(this); - this.onChangeAutoImplementProperties = - this.onChangeAutoImplementProperties.bind(this); - this.onChangeOverwriteHashCodeSupport = - this.onChangeOverwriteHashCodeSupport.bind(this); + this.onChangeAutoImplementProperties = this.onChangeAutoImplementProperties.bind(this); + this.onChangeOverwriteHashCodeSupport = this.onChangeOverwriteHashCodeSupport.bind(this); + this.onChangeIncludeJson = this.onChangeIncludeJson.bind(this); } onChangeArrayType(arrayType: any) { @@ -44,6 +43,12 @@ class CSharpGeneratorOptions extends React.Component< } } + onChangeIncludeJson(event: any) { + if (this.props.setNewConfig) { + this.props.setNewConfig('csharpIncludeJson', event.target.checked); + } + } + render() { return (
    @@ -94,6 +99,20 @@ class CSharpGeneratorOptions extends React.Component< /> +
  • + +
); } diff --git a/modelina-website/src/helpers/GeneratorCode/CSharpGenerator.ts b/modelina-website/src/helpers/GeneratorCode/CSharpGenerator.ts index fd21e304f2..d537a9186b 100644 --- a/modelina-website/src/helpers/GeneratorCode/CSharpGenerator.ts +++ b/modelina-website/src/helpers/GeneratorCode/CSharpGenerator.ts @@ -27,6 +27,13 @@ export function getCSharpGeneratorCode( } }`) } + + if (generatorOptions.csharpIncludeJson) { + optionStringPresets.push(` + CSHARP_JSON_SERIALIZER_PRESET + `) + } + const presetOptions = optionStringPresets.length > 0 ? `${optionString.length > 0 ? ',' : ''} diff --git a/modelina-website/src/pages/api/functions/CSharpGenerator.ts b/modelina-website/src/pages/api/functions/CSharpGenerator.ts index cca68697c3..c16ee6b089 100644 --- a/modelina-website/src/pages/api/functions/CSharpGenerator.ts +++ b/modelina-website/src/pages/api/functions/CSharpGenerator.ts @@ -2,7 +2,7 @@ import { CSharpGenerator, CSharpOptions } from '../../../../../'; import { convertModelsToProps } from './Helpers'; import { ModelinaCSharpOptions, ModelProps } from '../../../types'; -import {CSHARP_COMMON_PRESET} from '../../../../../'; +import { CSHARP_COMMON_PRESET, CSHARP_JSON_SERIALIZER_PRESET } from '../../../../../'; /** * This is the server side part of the CSharp generator, that takes input and generator parameters and generate the models. @@ -14,25 +14,24 @@ export async function getCSharpModels( const options: Partial = { presets: [] }; + options.presets = []; if (generatorOptions.csharpArrayType) { options.collectionType = generatorOptions.csharpArrayType as any; options.autoImplementedProperties = generatorOptions.csharpAutoImplemented; } if (generatorOptions.csharpOverwriteHashcode) { - options.presets = [ - { - preset: CSHARP_COMMON_PRESET, - options: { - equal: false, - hashCode: generatorOptions.csharpOverwriteHashcode - } + options.presets.push({ + preset: CSHARP_COMMON_PRESET, + options: { + equal: false, + hashCode: generatorOptions.csharpOverwriteHashcode } - ] + }) + } + if (generatorOptions.csharpIncludeJson) { + options.presets.push(CSHARP_JSON_SERIALIZER_PRESET) } - - - try { const generator = new CSharpGenerator(options); diff --git a/modelina-website/src/types/index.ts b/modelina-website/src/types/index.ts index a448de3eb6..8be5d98cb1 100644 --- a/modelina-website/src/types/index.ts +++ b/modelina-website/src/types/index.ts @@ -24,6 +24,7 @@ export interface ModelinaCSharpOptions { csharpArrayType: 'List' | 'Array' | undefined; csharpAutoImplemented: boolean; csharpOverwriteHashcode: boolean; + csharpIncludeJson: boolean; } export interface ModelinaKotlinOptions {} export interface ModelinaRustOptions {} @@ -53,6 +54,7 @@ export interface ModelinaCSharpQueryOptions { csharpArrayType?: string; csharpAutoImplemented?: string; csharpOverwriteHashcode?:string; + csharpIncludeJson?: string; } export interface ModelinaKotlinQueryOptions {} export interface ModelinaRustQueryOptions {} From 1b22344e70b55e4c19c847bb8b83ffe4d456fba9 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Thu, 25 May 2023 15:56:07 +0200 Subject: [PATCH 11/79] docs: add kaushik-rishi as a contributor for code, and design (#1329) * update README.md * update .all-contributorsrc --------- Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 10 ++++++++++ README.md | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 272d447cb9..e75b548251 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -592,6 +592,16 @@ "contributions": [ "design" ] + }, + { + "login": "kaushik-rishi", + "name": "Rishi", + "avatar_url": "https://avatars.githubusercontent.com/u/52498617?v=4", + "profile": "https://github.com/kaushik-rishi", + "contributions": [ + "code", + "design" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 62657690bf..bc6cd51187 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![Discussions](https://img.shields.io/github/discussions/asyncapi/modelina)](https://github.com/asyncapi/modelina/discussions) [![Website](https://img.shields.io/website?label=website&url=https%3A%2F%2Fwww.modelina.org)](https://www.modelina.org) [![Playground](https://img.shields.io/website?label=playground&url=https%3A%2F%2Fwww.modelina.org%2Fplayground)](https://www.modelina.org/playground) -[![All Contributors](https://img.shields.io/badge/all_contributors-53-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-54-orange.svg?style=flat-square)](#contributors-) Your one-stop tool for generating accurate and well-tested models for representing the message payloads. Use it as a tool in your development workflow, or a library in a larger integrations, entirely in your control. @@ -393,6 +393,7 @@ Thanks go out to these wonderful people ([emoji key](https://allcontributors.org Joshua Michael Daly
Joshua Michael Daly

🐛 Daniel KJ
Daniel KJ

💻 ⚠️ 💡 👀 Bhavik Agarwal
Bhavik Agarwal

🎨 + Rishi
Rishi

💻 🎨 From 25f7845cbf1a96bc14f9f32e17edea26469c34b9 Mon Sep 17 00:00:00 2001 From: Rishi <52498617+kaushik-rishi@users.noreply.github.com> Date: Tue, 30 May 2023 17:58:59 +0530 Subject: [PATCH 12/79] chore(website): add Newtonsoft support in the playground (#1337) --- .../src/components/playground/Playground.tsx | 8 ++++++- .../options/CSharpGeneratorOptions.tsx | 21 +++++++++++++++++++ .../helpers/GeneratorCode/CSharpGenerator.ts | 5 +++++ .../pages/api/functions/CSharpGenerator.ts | 5 ++++- modelina-website/src/types/index.ts | 2 ++ 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index e6127dc078..a1a8a4b4a0 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -79,6 +79,7 @@ class Playground extends React.Component< csharpAutoImplemented: false, csharpOverwriteHashcode: false, csharpIncludeJson: false, + csharpIncludeNewtonsoft: false, }; hasLoadedQuery: boolean = false; constructor(props: ModelinaPlaygroundProps) { @@ -214,6 +215,10 @@ class Playground extends React.Component< this.config.csharpIncludeJson = query.csharpIncludeJson === 'true'; } + if (query.csharpIncludeNewtonsoft !== undefined) { + this.config.csharpIncludeNewtonsoft = + query.csharpIncludeNewtonsoft === 'true'; + } if (this.props.router.isReady && !this.hasLoadedQuery) { this.hasLoadedQuery = true; this.generateNewCode(this.state.input); @@ -315,7 +320,8 @@ class Playground extends React.Component< csharpArrayType: this.config.csharpArrayType, csharpAutoImplemented: this.config.csharpAutoImplemented, csharpOverwriteHashcode: this.config.csharpOverwriteHashcode, - csharpIncludeJson: this.config.csharpIncludeJson + csharpIncludeJson: this.config.csharpIncludeJson, + csharpIncludeNewtonsoft: this.config.csharpIncludeNewtonsoft }} > diff --git a/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx b/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx index 2274e760a1..0b8ea46d03 100644 --- a/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx @@ -23,6 +23,7 @@ class CSharpGeneratorOptions extends React.Component< this.onChangeAutoImplementProperties = this.onChangeAutoImplementProperties.bind(this); this.onChangeOverwriteHashCodeSupport = this.onChangeOverwriteHashCodeSupport.bind(this); this.onChangeIncludeJson = this.onChangeIncludeJson.bind(this); + this.onChangeIncludeNewtonsoft = this.onChangeIncludeNewtonsoft.bind(this); } onChangeArrayType(arrayType: any) { @@ -49,6 +50,12 @@ class CSharpGeneratorOptions extends React.Component< } } + onChangeIncludeNewtonsoft(event: any) { + if (this.props.setNewConfig) { + this.props.setNewConfig('csharpIncludeNewtonsoft', event.target.checked); + } + } + render() { return (
    @@ -113,6 +120,20 @@ class CSharpGeneratorOptions extends React.Component< /> +
  • + +
); } diff --git a/modelina-website/src/helpers/GeneratorCode/CSharpGenerator.ts b/modelina-website/src/helpers/GeneratorCode/CSharpGenerator.ts index d537a9186b..b41217faf7 100644 --- a/modelina-website/src/helpers/GeneratorCode/CSharpGenerator.ts +++ b/modelina-website/src/helpers/GeneratorCode/CSharpGenerator.ts @@ -33,6 +33,11 @@ export function getCSharpGeneratorCode( CSHARP_JSON_SERIALIZER_PRESET `) } + if (generatorOptions.csharpIncludeNewtonsoft) { + optionStringPresets.push(` + CSHARP_NEWTONSOFT_SERIALIZER_PRESET + `) + } const presetOptions = optionStringPresets.length > 0 diff --git a/modelina-website/src/pages/api/functions/CSharpGenerator.ts b/modelina-website/src/pages/api/functions/CSharpGenerator.ts index c16ee6b089..153a83c7c9 100644 --- a/modelina-website/src/pages/api/functions/CSharpGenerator.ts +++ b/modelina-website/src/pages/api/functions/CSharpGenerator.ts @@ -2,7 +2,7 @@ import { CSharpGenerator, CSharpOptions } from '../../../../../'; import { convertModelsToProps } from './Helpers'; import { ModelinaCSharpOptions, ModelProps } from '../../../types'; -import { CSHARP_COMMON_PRESET, CSHARP_JSON_SERIALIZER_PRESET } from '../../../../../'; +import { CSHARP_COMMON_PRESET, CSHARP_JSON_SERIALIZER_PRESET, CSHARP_NEWTONSOFT_SERIALIZER_PRESET } from '../../../../../'; /** * This is the server side part of the CSharp generator, that takes input and generator parameters and generate the models. @@ -32,6 +32,9 @@ export async function getCSharpModels( if (generatorOptions.csharpIncludeJson) { options.presets.push(CSHARP_JSON_SERIALIZER_PRESET) } + if (generatorOptions.csharpIncludeNewtonsoft) { + options.presets.push(CSHARP_NEWTONSOFT_SERIALIZER_PRESET) + } try { const generator = new CSharpGenerator(options); diff --git a/modelina-website/src/types/index.ts b/modelina-website/src/types/index.ts index 8be5d98cb1..731593f78b 100644 --- a/modelina-website/src/types/index.ts +++ b/modelina-website/src/types/index.ts @@ -25,6 +25,7 @@ export interface ModelinaCSharpOptions { csharpAutoImplemented: boolean; csharpOverwriteHashcode: boolean; csharpIncludeJson: boolean; + csharpIncludeNewtonsoft: boolean; } export interface ModelinaKotlinOptions {} export interface ModelinaRustOptions {} @@ -55,6 +56,7 @@ export interface ModelinaCSharpQueryOptions { csharpAutoImplemented?: string; csharpOverwriteHashcode?:string; csharpIncludeJson?: string; + csharpIncludeNewtonsoft?: string; } export interface ModelinaKotlinQueryOptions {} export interface ModelinaRustQueryOptions {} From 580aae3f11cde7db2167cae9fb68190d3e24cbc9 Mon Sep 17 00:00:00 2001 From: asyncapi-bot Date: Tue, 30 May 2023 16:02:22 +0200 Subject: [PATCH 13/79] fix: update @asyncapi/parser to 2.0.1 version (#1341) --- package-lock.json | 38 +++++++++++++++++--------------------- package.json | 2 +- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/package-lock.json b/package-lock.json index c58e8f85c7..bb441d05e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@apidevtools/swagger-parser": "^10.0.3", "@asyncapi/avro-schema-parser": "^3.0.0", "@asyncapi/openapi-schema-parser": "^3.0.0", - "@asyncapi/parser": "^2.0.0", + "@asyncapi/parser": "^2.0.1", "@asyncapi/raml-dt-schema-parser": "^4.0.0", "@swc/core": "^1.3.5", "@swc/jest": "^0.2.23", @@ -113,11 +113,11 @@ } }, "node_modules/@asyncapi/parser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@asyncapi/parser/-/parser-2.0.0.tgz", - "integrity": "sha512-xQm3LVChLGGTOo6OxGM4wIwTC7/uMHZvQMcGHnCvdyqcqn4H1sZQdE+MHhxPM7SnKNko86Pub0UDavwk0Jfwyw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@asyncapi/parser/-/parser-2.0.1.tgz", + "integrity": "sha512-T6Z8PPD+U3XPL05sjT0yLHtDyoqA16pj1j7xNbvpt8SCFzdzw4QMsbvJFAKaXk1/bztzlMq+oWVmeiGazt5WGA==", "dependencies": { - "@asyncapi/specs": "^5.0.0", + "@asyncapi/specs": "^5.0.1", "@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0", "@stoplight/json-ref-resolver": "^3.1.5", "@stoplight/spectral-core": "^1.16.1", @@ -129,7 +129,6 @@ "ajv-errors": "^3.0.0", "ajv-formats": "^2.1.1", "avsc": "^5.7.5", - "conventional-changelog-conventionalcommits": "^5.0.0", "js-yaml": "^4.1.0", "jsonpath-plus": "^7.2.0", "node-fetch": "2.6.7", @@ -138,12 +137,11 @@ } }, "node_modules/@asyncapi/parser/node_modules/@asyncapi/specs": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-5.0.0.tgz", - "integrity": "sha512-ua89EYhNAL6IPrX/P5O+K5DEQYfMXwHhG207+8yCSvcVXevZ1wLEj/nsNHYi2jBRDr10kp7+O99tGWIdASJtOA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-5.0.1.tgz", + "integrity": "sha512-hWIko4JDZtBaRPO3OiDBCctNIOug+dux+p6TWmsxcgHBX4ziMmkBUfPZp6cMZtzEq/S9Nw7rKct1lPhZGfJHyg==", "dependencies": { - "@types/json-schema": "^7.0.11", - "conventional-changelog-conventionalcommits": "^5.0.0" + "@types/json-schema": "^7.0.11" } }, "node_modules/@asyncapi/parserV1": { @@ -13556,11 +13554,11 @@ } }, "@asyncapi/parser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@asyncapi/parser/-/parser-2.0.0.tgz", - "integrity": "sha512-xQm3LVChLGGTOo6OxGM4wIwTC7/uMHZvQMcGHnCvdyqcqn4H1sZQdE+MHhxPM7SnKNko86Pub0UDavwk0Jfwyw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@asyncapi/parser/-/parser-2.0.1.tgz", + "integrity": "sha512-T6Z8PPD+U3XPL05sjT0yLHtDyoqA16pj1j7xNbvpt8SCFzdzw4QMsbvJFAKaXk1/bztzlMq+oWVmeiGazt5WGA==", "requires": { - "@asyncapi/specs": "^5.0.0", + "@asyncapi/specs": "^5.0.1", "@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0", "@stoplight/json-ref-resolver": "^3.1.5", "@stoplight/spectral-core": "^1.16.1", @@ -13572,7 +13570,6 @@ "ajv-errors": "^3.0.0", "ajv-formats": "^2.1.1", "avsc": "^5.7.5", - "conventional-changelog-conventionalcommits": "^5.0.0", "js-yaml": "^4.1.0", "jsonpath-plus": "^7.2.0", "node-fetch": "2.6.7", @@ -13581,12 +13578,11 @@ }, "dependencies": { "@asyncapi/specs": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-5.0.0.tgz", - "integrity": "sha512-ua89EYhNAL6IPrX/P5O+K5DEQYfMXwHhG207+8yCSvcVXevZ1wLEj/nsNHYi2jBRDr10kp7+O99tGWIdASJtOA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-5.0.1.tgz", + "integrity": "sha512-hWIko4JDZtBaRPO3OiDBCctNIOug+dux+p6TWmsxcgHBX4ziMmkBUfPZp6cMZtzEq/S9Nw7rKct1lPhZGfJHyg==", "requires": { - "@types/json-schema": "^7.0.11", - "conventional-changelog-conventionalcommits": "^5.0.0" + "@types/json-schema": "^7.0.11" } } } diff --git a/package.json b/package.json index e48010381f..b917624349 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "@apidevtools/swagger-parser": "^10.0.3", "@asyncapi/avro-schema-parser": "^3.0.0", "@asyncapi/openapi-schema-parser": "^3.0.0", - "@asyncapi/parser": "^2.0.0", + "@asyncapi/parser": "^2.0.1", "@asyncapi/raml-dt-schema-parser": "^4.0.0", "@swc/core": "^1.3.5", "@swc/jest": "^0.2.23", From 288f24cff27793e34a5e45348aea9cb223d34070 Mon Sep 17 00:00:00 2001 From: asyncapi-bot Date: Tue, 30 May 2023 16:28:25 +0200 Subject: [PATCH 14/79] fix: update @asyncapi/openapi-schema-parser to 3.0.1 version (#1342) --- package-lock.json | 18 +++++++++--------- package.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index bb441d05e2..0fe71ed3b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@apidevtools/json-schema-ref-parser": "^9.0.9", "@apidevtools/swagger-parser": "^10.0.3", "@asyncapi/avro-schema-parser": "^3.0.0", - "@asyncapi/openapi-schema-parser": "^3.0.0", + "@asyncapi/openapi-schema-parser": "^3.0.1", "@asyncapi/parser": "^2.0.1", "@asyncapi/raml-dt-schema-parser": "^4.0.0", "@swc/core": "^1.3.5", @@ -101,11 +101,11 @@ } }, "node_modules/@asyncapi/openapi-schema-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@asyncapi/openapi-schema-parser/-/openapi-schema-parser-3.0.0.tgz", - "integrity": "sha512-3s5rI//5KSvrPfv/jiiQi5uOerMc7Y7ejVDveuI7hhaujC+NemFwcc8imMwZzNHF6BsBGc9/HVtSjYIkQZpk4Q==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@asyncapi/openapi-schema-parser/-/openapi-schema-parser-3.0.1.tgz", + "integrity": "sha512-Ps1KAinQHF6YzJJwm0pJNeVnfZC6nFE76dYn5ZzE6l/mUNYtedoiqbCdF+NYA8nDTsXg3087c/drQZuEd/6BgQ==", "dependencies": { - "@asyncapi/parser": "^2.0.0", + "@asyncapi/parser": "^2.0.1", "@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0", "ajv": "^8.11.0", "ajv-errors": "^3.0.0", @@ -13542,11 +13542,11 @@ } }, "@asyncapi/openapi-schema-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@asyncapi/openapi-schema-parser/-/openapi-schema-parser-3.0.0.tgz", - "integrity": "sha512-3s5rI//5KSvrPfv/jiiQi5uOerMc7Y7ejVDveuI7hhaujC+NemFwcc8imMwZzNHF6BsBGc9/HVtSjYIkQZpk4Q==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@asyncapi/openapi-schema-parser/-/openapi-schema-parser-3.0.1.tgz", + "integrity": "sha512-Ps1KAinQHF6YzJJwm0pJNeVnfZC6nFE76dYn5ZzE6l/mUNYtedoiqbCdF+NYA8nDTsXg3087c/drQZuEd/6BgQ==", "requires": { - "@asyncapi/parser": "^2.0.0", + "@asyncapi/parser": "^2.0.1", "@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0", "ajv": "^8.11.0", "ajv-errors": "^3.0.0", diff --git a/package.json b/package.json index b917624349..0b53971288 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "@apidevtools/json-schema-ref-parser": "^9.0.9", "@apidevtools/swagger-parser": "^10.0.3", "@asyncapi/avro-schema-parser": "^3.0.0", - "@asyncapi/openapi-schema-parser": "^3.0.0", + "@asyncapi/openapi-schema-parser": "^3.0.1", "@asyncapi/parser": "^2.0.1", "@asyncapi/raml-dt-schema-parser": "^4.0.0", "@swc/core": "^1.3.5", From d60b1e6f9321999cd4e1e1d6f6bbac97e7bcaaee Mon Sep 17 00:00:00 2001 From: asyncapi-bot Date: Tue, 30 May 2023 17:01:54 +0200 Subject: [PATCH 15/79] chore(release): v1.7.1 (#1345) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0fe71ed3b9..e41a69e5bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@asyncapi/modelina", - "version": "1.7.0", + "version": "1.7.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@asyncapi/modelina", - "version": "1.7.0", + "version": "1.7.1", "license": "Apache-2.0", "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.9", diff --git a/package.json b/package.json index 0b53971288..923f8127da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@asyncapi/modelina", - "version": "1.7.0", + "version": "1.7.1", "description": "Library for generating data models based on inputs such as AsyncAPI, OpenAPI, or JSON Schema documents", "license": "Apache-2.0", "homepage": "https://www.modelina.org", From a30b38dbf1b8b4b3ff6627bce7a677a59add4243 Mon Sep 17 00:00:00 2001 From: Jonas Lagoni Date: Tue, 30 May 2023 21:09:41 +0200 Subject: [PATCH 16/79] ci: remove unused website deploy script (#1164) --- .github/workflows/website-deploy.yml | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 .github/workflows/website-deploy.yml diff --git a/.github/workflows/website-deploy.yml b/.github/workflows/website-deploy.yml deleted file mode 100644 index 9cb9a13335..0000000000 --- a/.github/workflows/website-deploy.yml +++ /dev/null @@ -1,17 +0,0 @@ - -name: Deploy to Netlify -on: - issues: - types: [opened, deleted, closed, reopened, labeled, unlabeled] - -jobs: - publish: - runs-on: ubuntu-latest - - steps: - - name: Trigger deploy on Netlify - run: | - curl -X POST "https://api.netlify.com/api/v1/sites/$NETLIFY_SITE_ID/builds" -H "Authorization: Bearer $NETLIFY_AUTH_TOKEN" - env: - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} \ No newline at end of file From 47217bca6f8325b4e38d89a42243ba50deb25281 Mon Sep 17 00:00:00 2001 From: Jonas Lagoni Date: Tue, 30 May 2023 21:10:57 +0200 Subject: [PATCH 17/79] chore(website): add PHP playground support (#1306) --- .../contexts/PlaygroundConfigContext.ts | 5 +- .../src/components/playground/Playground.tsx | 44 ++++++++++----- .../playground/PlaygroundOptions.tsx | 5 ++ .../options/PhpGeneratorOptions.tsx | 55 +++++++++++++++++++ .../src/helpers/GeneratorCode/PhpGenerator.ts | 38 +++++++++++++ .../src/pages/api/functions/PhpGenerator.ts | 40 ++++++++++++++ modelina-website/src/pages/api/generate.ts | 4 +- modelina-website/src/types/index.ts | 19 ++++++- 8 files changed, 190 insertions(+), 20 deletions(-) create mode 100644 modelina-website/src/components/playground/options/PhpGeneratorOptions.tsx create mode 100644 modelina-website/src/helpers/GeneratorCode/PhpGenerator.ts create mode 100644 modelina-website/src/pages/api/functions/PhpGenerator.ts diff --git a/modelina-website/src/components/contexts/PlaygroundConfigContext.ts b/modelina-website/src/components/contexts/PlaygroundConfigContext.ts index 54de4ff2d9..a3af2dcdb7 100644 --- a/modelina-website/src/components/contexts/PlaygroundConfigContext.ts +++ b/modelina-website/src/components/contexts/PlaygroundConfigContext.ts @@ -6,6 +6,7 @@ import { ModelinaJavaOptions, ModelinaJavaScriptOptions, ModelinaKotlinOptions, + ModelinaPhpOptions, ModelinaPythonOptions, ModelinaRustOptions, ModelinaTypeScriptOptions @@ -30,5 +31,7 @@ export const PlaygroundCSharpConfigContext = createContext(null); export const PlaygroundPythonConfigContext = createContext(null); - export const PlaygroundCplusplusConfigContext = +export const PlaygroundCplusplusConfigContext = createContext(null); +export const PlaygroundPhpConfigContext = + createContext(null); diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index a1a8a4b4a0..39a8a87aec 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -25,7 +25,8 @@ import { PlaygroundKotlinConfigContext, PlaygroundPythonConfigContext, PlaygroundRustConfigContext, - PlaygroundCplusplusConfigContext + PlaygroundCplusplusConfigContext, + PlaygroundPhpConfigContext } from '../contexts/PlaygroundConfigContext'; import { getTypeScriptGeneratorCode } from '@/helpers/GeneratorCode/TypeScriptGenerator'; import { getJavaScriptGeneratorCode } from '@/helpers/GeneratorCode/JavaScriptGenerator'; @@ -37,6 +38,7 @@ import { getPythonGeneratorCode } from '@/helpers/GeneratorCode/PythonGenerator' import { getDartGeneratorCode } from '@/helpers/GeneratorCode/DartGenerator'; import { getCplusplusGeneratorCode } from '@/helpers/GeneratorCode/CplusplusGenerator'; import CustomError from '../CustomError'; +import { getPhpGeneratorCode } from '@/helpers/GeneratorCode/PhpGenerator'; interface WithRouterProps { router: NextRouter; @@ -77,6 +79,7 @@ class Playground extends React.Component< tsIncludeDescriptions: false, csharpArrayType: 'Array', csharpAutoImplemented: false, + phpIncludeDescriptions: false, csharpOverwriteHashcode: false, csharpIncludeJson: false, csharpIncludeNewtonsoft: false, @@ -143,7 +146,8 @@ class Playground extends React.Component< rust: getRustGeneratorCode, python: getPythonGeneratorCode, dart: getDartGeneratorCode, - cplusplus: getCplusplusGeneratorCode + cplusplus: getCplusplusGeneratorCode, + php: getPhpGeneratorCode } const generatorCode = generators[this.config.language](message); fetch(`${process.env.NEXT_PUBLIC_API_PATH}/generate`, { @@ -211,6 +215,10 @@ class Playground extends React.Component< this.config.csharpOverwriteHashcode = query.csharpOverwriteHashcode === 'true'; } + if (query.phpIncludeDescriptions !== undefined) { + this.config.phpIncludeDescriptions = + query.phpIncludeDescriptions === 'true'; + } if (query.csharpIncludeJson !== undefined) { this.config.csharpIncludeJson = query.csharpIncludeJson === 'true'; @@ -327,19 +335,25 @@ class Playground extends React.Component< - - - - - - - - - + + + + + + + + + + + diff --git a/modelina-website/src/components/playground/PlaygroundOptions.tsx b/modelina-website/src/components/playground/PlaygroundOptions.tsx index 68f44647e7..924632f92d 100644 --- a/modelina-website/src/components/playground/PlaygroundOptions.tsx +++ b/modelina-website/src/components/playground/PlaygroundOptions.tsx @@ -11,6 +11,7 @@ import KotlinGeneratorOptions from './options/KotlinGeneratorOptions'; import RustGeneratorOptions from './options/RustGeneratorOptions'; import PythonGeneratorOptions from './options/PythonGeneratorOptions'; import CplusplusGeneratorOptions from './options/CplusplusGeneratorOptions'; +import PhpGeneratorOptions from './options/PhpGeneratorOptions'; interface WithRouterProps { setNewConfig?: (queryKey: string, queryValue: string) => void; @@ -72,6 +73,10 @@ class PlaygroundOptions extends React.Component< generatorOptions = ( ); + } else if (this.context?.language === 'php') { + generatorOptions = ( + + ); } return (
diff --git a/modelina-website/src/components/playground/options/PhpGeneratorOptions.tsx b/modelina-website/src/components/playground/options/PhpGeneratorOptions.tsx new file mode 100644 index 0000000000..2f306a53ed --- /dev/null +++ b/modelina-website/src/components/playground/options/PhpGeneratorOptions.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import { PlaygroundPhpConfigContext } from '@/components/contexts/PlaygroundConfigContext'; + +interface PhpGeneratorOptionsProps { + setNewConfig?: (queryKey: string, queryValue: string) => void; +} + +interface PhpGeneratorState {} + +export const defaultState: PhpGeneratorState = {}; + +class PhpGeneratorOptions extends React.Component< + PhpGeneratorOptionsProps, + PhpGeneratorState +> { + static contextType = PlaygroundPhpConfigContext; + declare context: React.ContextType; + constructor(props: any) { + super(props); + this.state = defaultState; + this.onChangeIncludeDescriptions = + this.onChangeIncludeDescriptions.bind(this); + } + + onChangeIncludeDescriptions(event: any) { + if (this.props.setNewConfig) { + this.props.setNewConfig('phpIncludeDescriptions', event.target.checked); + } + } + + render() { + return ( +
    +

    + PHP Specific options +

    +
  • + +
  • +
+ ); + } +} +export default PhpGeneratorOptions; diff --git a/modelina-website/src/helpers/GeneratorCode/PhpGenerator.ts b/modelina-website/src/helpers/GeneratorCode/PhpGenerator.ts new file mode 100644 index 0000000000..344656a6f8 --- /dev/null +++ b/modelina-website/src/helpers/GeneratorCode/PhpGenerator.ts @@ -0,0 +1,38 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { ModelinaPhpOptions } from '../../types'; + +export function getPhpGeneratorCode(generatorOptions: ModelinaPhpOptions) { + const optionString: string[] = []; + const optionStringPresets: string[] = []; + + if (generatorOptions.phpIncludeDescriptions === true) { + optionStringPresets.push(`{ + preset: PHP_DESCRIPTION_PRESET, + }`); + } + + const presetOptions = + optionStringPresets.length > 0 + ? `${optionString.length > 0 ? ',' : ''} + presets: [ + ${optionStringPresets.join(', \n')} + ]` + : ''; + let fullOptions = ''; + if (optionStringPresets.length > 0 || optionString.length > 0) { + fullOptions = `{ + ${optionString.join(';\n')}${presetOptions} + }`; + } + const generateInstanceCode = + `const generator = new PhpGenerator(${fullOptions});`.replace( + /^\s*\n/gm, + '' + ); + + return `// Use the following code as starting point +// To generate the models exactly as displayed in the playground +import { PhpGenerator, PHP_DESCRIPTION_PRESET } from '@asyncapi/modelina'; + +${generateInstanceCode}`; +} diff --git a/modelina-website/src/pages/api/functions/PhpGenerator.ts b/modelina-website/src/pages/api/functions/PhpGenerator.ts new file mode 100644 index 0000000000..6ea758ca46 --- /dev/null +++ b/modelina-website/src/pages/api/functions/PhpGenerator.ts @@ -0,0 +1,40 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { + InputProcessor, + PHP_DESCRIPTION_PRESET, + PhpGenerator, + PhpOptions +} from '../../../../../'; +import { convertModelsToProps } from './Helpers'; +import { ModelinaPhpOptions, ModelProps } from '../../../types'; + +/** + * This is the server side part of the PHP generator, that takes input and generator parameters and generate the models. + */ +export async function getPhpModels( + input: any, + generatorOptions: ModelinaPhpOptions +): Promise { + const options: Partial = { + presets: [] + }; + if (generatorOptions.phpIncludeDescriptions === true) { + options.presets?.push({ + preset: PHP_DESCRIPTION_PRESET, + options: {} + }); + } + try { + const processedInput = await InputProcessor.processor.process(input); + const generator = new PhpGenerator(options); + const generatedModels = await generator.generateCompleteModels( + processedInput, + { namespace: 'asyncapi.models' } + ); + return convertModelsToProps(generatedModels); + } catch (e : any) { + console.error('Could not generate models'); + console.error(e); + return e.message; + } +} diff --git a/modelina-website/src/pages/api/generate.ts b/modelina-website/src/pages/api/generate.ts index d79bd33227..6394f91fce 100644 --- a/modelina-website/src/pages/api/generate.ts +++ b/modelina-website/src/pages/api/generate.ts @@ -15,6 +15,7 @@ import { getPythonModels } from '@/pages/api/functions/PythonGenerator'; import { getRustModels } from '@/pages/api/functions/RustGenerator'; import { getCSharpModels } from '@/pages/api/functions/CSharpGenerator'; import { getCplusplusModels } from './functions/CplusplusGenerator'; +import { getPhpModels } from './functions/PhpGenerator'; export async function generateNewCode(message: GenerateMessage): Promise { let input: any = defaultAsyncapiDocument; @@ -36,7 +37,8 @@ export async function generateNewCode(message: GenerateMessage): Promise Date: Tue, 30 May 2023 21:15:36 +0200 Subject: [PATCH 18/79] docs: add missing preset hooks for Kotlin, PHP and C++ (#1312) --- docs/presets.md | 71 ++++++++++++++++++++++++++++++++++++++++++++++--- package.json | 2 +- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/docs/presets.md b/docs/presets.md index 416cd2e0fc..e348523da2 100644 --- a/docs/presets.md +++ b/docs/presets.md @@ -40,9 +40,17 @@ Modelina uses something called **presets** to extend the rendered model. You can - [**Class**](#class-4) - [**Enum**](#enum-4) + [Python](#python) - - [**Class: plain Python**](#class-5) - - [**Class: pydantic**](#class-6) + - [**Class**](#class-5) - [**Enum**](#enum-5) + + [C++ (csplusplus)](#c-csplusplus) + - [**Class**](#class-6) + - [**Enum**](#enum-6) + + [Kotlin](#kotlin) + - [**Class**](#class-7) + - [**Enum**](#enum-7) + + [PHP](#php) + - [**Class**](#class-8) + - [**Enum**](#enum-8) - [Limitations](#limitations) * [Hard for two presets to write to the exact same location within a class](#hard-for-two-presets-to-write-to-the-exact-same-location-within-a-class) @@ -408,7 +416,6 @@ This preset is a generator for the meta model `ConstrainedObjectModel` and [can |---|---|---| | `field` | A method to extend rendered given field. | `field` object as a [`ConstrainedObjectPropertyModel`](./internal-model.md#the-constrained-meta-model) instance. | - ### C# #### **Class** @@ -519,6 +526,64 @@ This preset is a generator for the meta model `ConstrainedEnumModel` and [can be | Method | Description | Additional arguments | |---|---|---| | `item` | A method to extend enum's item. | `item` object as a [`ConstrainedEnumValueModel`](./internal-model.md#the-constrained-meta-model) instance, which contains the value and key of enum's item. | + +### C++ (csplusplus) + +#### **Class** + +This preset is a generator for the meta model `ConstrainedObjectModel` and [can be accessed through the `model` argument](#presets-shape). + +| Method | Description | Additional arguments | +|---|---|---| +| `property` | A method to extend rendered given property. | `property` object as a [`ConstrainedObjectPropertyModel`](./internal-model.md#the-constrained-meta-model) instance. | + +#### **Enum** + +This preset is a generator for the meta model `ConstrainedEnumModel` and [can be accessed through the `model` argument](#presets-shape). + +| Method | Description | Additional arguments | +|---|---|---| +| `item` | A method to extend enum's item. | `item` object as a [`ConstrainedEnumValueModel`](./internal-model.md#the-constrained-meta-model) instance, which contains the value and key of enum's item. | + +### Kotlin + +#### **Class** + +This preset is a generator for the meta model `ConstrainedObjectModel` and [can be accessed through the `model` argument](#presets-shape). + +| Method | Description | Additional arguments | +|---|---|---| +| `ctor` | A method to extend rendered constructor for a given class. | - | +| `property` | A method to extend rendered given property. | `property` object as a [`ConstrainedObjectPropertyModel`](./internal-model.md#the-constrained-meta-model) instance. | +#### **Enum** + +This preset is a generator for the meta model `ConstrainedEnumModel` and [can be accessed through the `model` argument](#presets-shape). + +| Method | Description | Additional arguments | +|---|---|---| +| `item` | A method to extend enum's item. | `item` object as a [`ConstrainedEnumValueModel`](./internal-model.md#the-constrained-meta-model) instance, which contains the value and key of enum's item. | + +### PHP + +#### **Class** + +This preset is a generator for the meta model `ConstrainedObjectModel` and [can be accessed through the `model` argument](#presets-shape). + +| Method | Description | Additional arguments | +|---|---|---| +| `ctor` | A method to extend rendered constructor for a given class. | - | +| `property` | A method to extend rendered given property. | `property` object as a [`ConstrainedObjectPropertyModel`](./internal-model.md#the-constrained-meta-model) instance. | +| `setter` | A method to extend setter for a given property. | `property` object as a [`ConstrainedObjectPropertyModel`](./internal-model.md#the-constrained-meta-model) instance. | +| `getter` | A method to extend getter for a given property. | `property` object as a [`ConstrainedObjectPropertyModel`](./internal-model.md#the-constrained-meta-model) instance. | + +#### **Enum** + +This preset is a generator for the meta model `ConstrainedEnumModel` and [can be accessed through the `model` argument](#presets-shape). + +| Method | Description | Additional arguments | +|---|---|---| +| `item` | A method to extend enum's item. | `item` object as a [`ConstrainedEnumValueModel`](./internal-model.md#the-constrained-meta-model) instance, which contains the value and key of enum's item. | + # Limitations With features natually comes limitations, and same applies for presets, so here are the known limitations the architecture of presets for Modelina. diff --git a/package.json b/package.json index 923f8127da..d6ddd9d8f4 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "lint": "eslint --max-warnings 0 --config .eslintrc .", "lint:fix": "eslint --max-warnings 0 --config .eslintrc . --fix", "release": "semantic-release", - "generate:readme:toc": "markdown-toc -i README.md && markdown-toc -i ./docs/other-tools.md && markdown-toc -i ./docs/languages/Php.md && markdown-toc -i ./docs/languages/Cplusplus.md && markdown-toc -i ./examples/README.md && markdown-toc -i ./docs/languages/Python.md && markdown-toc -i ./docs/usage.md && markdown-toc -i ./docs/integration.md && markdown-toc -i ./docs/advanced.md && markdown-toc -i ./docs/languages/Dart.md && markdown-toc -i ./docs/languages/TypeScript.md && markdown-toc -i ./docs/languages/Java.md && markdown-toc -i ./docs/languages/JavaScript.md && markdown-toc -i ./docs/languages/Csharp.md && markdown-toc -i ./docs/README.md && markdown-toc -i ./docs/generators.md", + "generate:readme:toc": "markdown-toc -i README.md && markdown-toc -i ./docs/other-tools.md && markdown-toc -i ./docs/languages/Php.md && markdown-toc -i ./docs/languages/Cplusplus.md && markdown-toc -i ./examples/README.md && markdown-toc -i ./docs/languages/Python.md && markdown-toc -i ./docs/usage.md && markdown-toc -i ./docs/integration.md && markdown-toc -i ./docs/advanced.md && markdown-toc -i ./docs/languages/Dart.md && markdown-toc -i ./docs/languages/TypeScript.md && markdown-toc -i ./docs/languages/Java.md && markdown-toc -i ./docs/languages/JavaScript.md && markdown-toc -i ./docs/languages/Csharp.md && markdown-toc -i ./docs/README.md && markdown-toc -i ./docs/generators.md && markdown-toc -i ./docs/presets.md", "generate:assets": "npm run build:prod && npm run docs && npm run generate:readme:toc && npm run format", "bump:version": "npm --no-git-tag-version --allow-same-version version $VERSION", "prepublishOnly": "npm run build:prod && npm run generate:readme:toc && npm run format", From 4983a4079b58433fb03ed5dc0cb3c3abd0c0c17e Mon Sep 17 00:00:00 2001 From: Jonas Lagoni Date: Tue, 30 May 2023 21:17:42 +0200 Subject: [PATCH 19/79] chore: add AsyncAPI website tool listing (#1298) --- .asyncapi-tool | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .asyncapi-tool diff --git a/.asyncapi-tool b/.asyncapi-tool new file mode 100644 index 0000000000..59557c4a50 --- /dev/null +++ b/.asyncapi-tool @@ -0,0 +1,16 @@ +{ + "title": "AsyncAPI Modelina", + "description": "Generate payload models into Java, TypeScript, Go, etc, you name it, from AsyncAPI documents. This tool gives you full control over the models through high customization", + "links": { + "websiteUrl": "https://modelina.org", + "docsUrl": "https://github.com/asyncapi/modelina/tree/master/docs", + "repoUrl": "https://github.com/asyncapi/modelina" + }, + "filters": { + "language": "TypeScript", + "technology": ["React JS", "Docker"], + "categories": ["code-generator"], + "hasCommercial": false, + "isAsyncAPIOwner": true + } +} \ No newline at end of file From 4d7f31f6e384b8fdf8ecd4ebbbd246d443ec6438 Mon Sep 17 00:00:00 2001 From: Jonas Lagoni Date: Tue, 30 May 2023 21:30:48 +0200 Subject: [PATCH 20/79] chore(website): fix playground kotlin generation not working (#1307) --- modelina-website/src/components/playground/Playground.tsx | 2 ++ modelina-website/src/pages/api/generate.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index 39a8a87aec..2132d4c976 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -38,6 +38,7 @@ import { getPythonGeneratorCode } from '@/helpers/GeneratorCode/PythonGenerator' import { getDartGeneratorCode } from '@/helpers/GeneratorCode/DartGenerator'; import { getCplusplusGeneratorCode } from '@/helpers/GeneratorCode/CplusplusGenerator'; import CustomError from '../CustomError'; +import { getKotlinGeneratorCode } from '@/helpers/GeneratorCode/KotlinGenerator'; import { getPhpGeneratorCode } from '@/helpers/GeneratorCode/PhpGenerator'; interface WithRouterProps { @@ -147,6 +148,7 @@ class Playground extends React.Component< python: getPythonGeneratorCode, dart: getDartGeneratorCode, cplusplus: getCplusplusGeneratorCode, + kotlin: getKotlinGeneratorCode, php: getPhpGeneratorCode } const generatorCode = generators[this.config.language](message); diff --git a/modelina-website/src/pages/api/generate.ts b/modelina-website/src/pages/api/generate.ts index 6394f91fce..8ed4cd88f4 100644 --- a/modelina-website/src/pages/api/generate.ts +++ b/modelina-website/src/pages/api/generate.ts @@ -15,6 +15,7 @@ import { getPythonModels } from '@/pages/api/functions/PythonGenerator'; import { getRustModels } from '@/pages/api/functions/RustGenerator'; import { getCSharpModels } from '@/pages/api/functions/CSharpGenerator'; import { getCplusplusModels } from './functions/CplusplusGenerator'; +import { getKotlinModels } from './functions/KotlinGenerator'; import { getPhpModels } from './functions/PhpGenerator'; export async function generateNewCode(message: GenerateMessage): Promise { @@ -36,6 +37,7 @@ export async function generateNewCode(message: GenerateMessage): Promise Date: Tue, 30 May 2023 21:46:56 +0200 Subject: [PATCH 21/79] chore(website): add remaining playground TypeScript options (#1301) --- .../src/components/playground/Playground.tsx | 30 ++++++++--- .../options/TypeScriptGeneratorOptions.tsx | 53 ++++++++++++++++++- .../GeneratorCode/TypeScriptGenerator.ts | 40 +++++++++----- .../api/functions/TypeScriptGenerator.ts | 26 +++++++-- modelina-website/src/types/index.ts | 4 ++ 5 files changed, 128 insertions(+), 25 deletions(-) diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index 2132d4c976..57b37dcbce 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -78,6 +78,8 @@ class Playground extends React.Component< tsEnumType: 'enum', tsModuleSystem: 'CJS', tsIncludeDescriptions: false, + tsIncludeExampleFunction: false, + tsIncludeJsonBinPack: false, csharpArrayType: 'Array', csharpAutoImplemented: false, phpIncludeDescriptions: false, @@ -106,11 +108,13 @@ class Playground extends React.Component< this.generateNewCode = this.generateNewCode.bind(this); } - setNewConfig(config: string, configValue: any) { + setNewConfig(config: string, configValue: any, updateCode?: boolean) { this.setNewQuery(config, configValue); /* eslint-disable-next-line security/detect-object-injection */ (this.config as any)[config] = configValue; - this.generateNewCode(this.state.input); + if(updateCode === true || updateCode === undefined) { + this.generateNewCode(this.state.input); + } } /** @@ -120,8 +124,12 @@ class Playground extends React.Component< const newQuery = { query: { ...this.props.router.query } }; - /* eslint-disable-next-line security/detect-object-injection */ - newQuery.query[queryKey] = String(queryValue); + if(queryValue === false) { + delete newQuery.query[queryKey]; + } else { + /* eslint-disable-next-line security/detect-object-injection */ + newQuery.query[queryKey] = String(queryValue); + } Router.push(newQuery, undefined, { scroll: false }); } @@ -203,6 +211,14 @@ class Playground extends React.Component< this.config.tsIncludeDescriptions = query.tsIncludeDescriptions === 'true'; } + if (query.tsIncludeJsonBinPack !== undefined) { + this.config.tsIncludeJsonBinPack = + query.tsIncludeJsonBinPack === 'true'; + } + if (query.tsIncludeExampleFunction !== undefined) { + this.config.tsIncludeExampleFunction = + query.tsIncludeExampleFunction === 'true'; + } if (query.language !== undefined) { this.config.language = query.language as any; } @@ -265,7 +281,7 @@ class Playground extends React.Component< className={`grid grid-cols-2 gap-4 mt-4 ${isLoaded ? '' : 'invisible' }`} > -
+

@@ -321,7 +337,9 @@ class Playground extends React.Component< tsModelType: this.config.tsModelType, tsModuleSystem: this.config.tsModuleSystem, tsEnumType: this.config.tsEnumType, - tsIncludeDescriptions: this.config.tsIncludeDescriptions + tsIncludeDescriptions: this.config.tsIncludeDescriptions, + tsIncludeExampleFunction: this.config.tsIncludeExampleFunction, + tsIncludeJsonBinPack: this.config.tsIncludeJsonBinPack }} > diff --git a/modelina-website/src/components/playground/options/TypeScriptGeneratorOptions.tsx b/modelina-website/src/components/playground/options/TypeScriptGeneratorOptions.tsx index 77a2f92bbb..040b82c5ca 100644 --- a/modelina-website/src/components/playground/options/TypeScriptGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/TypeScriptGeneratorOptions.tsx @@ -3,7 +3,7 @@ import Select from '../../Select'; import { PlaygroundTypeScriptConfigContext } from '@/components/contexts/PlaygroundConfigContext'; interface TypeScriptGeneratorOptionsProps { - setNewConfig?: (queryKey: string, queryValue: string) => void; + setNewConfig?: (queryKey: string, queryValue: any, updateCode?: boolean) => void; } interface TypeScriptGeneratorState {} @@ -23,6 +23,8 @@ class TypeScriptGeneratorOptions extends React.Component< this.onChangeVariant = this.onChangeVariant.bind(this); this.onChangeEnumType = this.onChangeEnumType.bind(this); this.onChangeModuleSystem = this.onChangeModuleSystem.bind(this); + this.onChangeIncludeExampleFunction = this.onChangeIncludeExampleFunction.bind(this); + this.onChangeIncludeJsonBinPack = this.onChangeIncludeJsonBinPack.bind(this); this.onChangeIncludeDescriptions = this.onChangeIncludeDescriptions.bind(this); } @@ -57,6 +59,23 @@ class TypeScriptGeneratorOptions extends React.Component< } } + onChangeIncludeJsonBinPack(event: any) { + if (this.props.setNewConfig) { + const shouldIncludeMarshalling = this.context?.tsMarshalling === false && event.target.checked === true; + this.props.setNewConfig('tsIncludeJsonBinPack', event.target.checked, shouldIncludeMarshalling ? false : true); + + if(shouldIncludeMarshalling) { + this.props.setNewConfig('tsMarshalling', event.target.checked); + } + } + } + + onChangeIncludeExampleFunction(event: any) { + if (this.props.setNewConfig) { + this.props.setNewConfig('tsIncludeExampleFunction', event.target.checked); + } + } + render() { return (
    @@ -141,6 +160,38 @@ class TypeScriptGeneratorOptions extends React.Component< ) : null} + {this.context?.tsModelType === 'class' ? ( +
  • + +
  • + ) : null} + {this.context?.tsModelType === 'class' ? ( +
  • + +
  • + ) : null}
); } diff --git a/modelina-website/src/helpers/GeneratorCode/TypeScriptGenerator.ts b/modelina-website/src/helpers/GeneratorCode/TypeScriptGenerator.ts index 16ac4dac67..2e1a9d5897 100644 --- a/modelina-website/src/helpers/GeneratorCode/TypeScriptGenerator.ts +++ b/modelina-website/src/helpers/GeneratorCode/TypeScriptGenerator.ts @@ -11,41 +11,53 @@ export function getTypeScriptGeneratorCode( optionString.push(`modelType: '${generatorOptions.tsModelType}'`); } - if (generatorOptions.tsMarshalling === true) { - optionStringPresets.push(`{ + if (generatorOptions.tsMarshalling === true || + generatorOptions.tsIncludeExampleFunction === true) { + let commonOptions: any = {}; + if(generatorOptions.tsMarshalling === true) { + commonOptions.marshalling = true; + } + + if (generatorOptions.tsIncludeExampleFunction === true) { + commonOptions.example = true; + } + + optionStringPresets.push(` { preset: TS_COMMON_PRESET, - options: { - marshalling: true - } + options: ${JSON.stringify(commonOptions)} }`); } if (generatorOptions.tsEnumType) { - optionString.push(` enumType: '${generatorOptions.tsEnumType}'`); + optionString.push(` enumType: '${generatorOptions.tsEnumType}'`); } if (generatorOptions.tsIncludeDescriptions === true) { - optionStringPresets.push(`{ + optionStringPresets.push(` { preset: TS_DESCRIPTION_PRESET, }`); } + if (generatorOptions.tsIncludeJsonBinPack === true) { + optionStringPresets.push(` TS_JSONBINPACK_PRESET`); + } + if (generatorOptions.tsModuleSystem) { - optionString.push(`moduleSystem: '${generatorOptions.tsModuleSystem}'`); + optionString.push(` moduleSystem: '${generatorOptions.tsModuleSystem}'`); } const presetOptions = optionStringPresets.length > 0 ? `${optionString.length > 0 ? ',' : ''} - presets: [ - ${optionStringPresets.join(', \n')} - ]` + presets: [ +${optionStringPresets.join(', \n')} + ]` : ''; let fullOptions = ''; if (optionStringPresets.length > 0 || optionString.length > 0) { fullOptions = `{ - ${optionString.join(';\n')}${presetOptions} - }`; + ${optionString.join(', \n')}${presetOptions} +}`; } const generateInstanceCode = `const generator = new TypeScriptGenerator(${fullOptions});`.replace( @@ -55,7 +67,7 @@ export function getTypeScriptGeneratorCode( return `// Use the following code as starting point // To generate the models exactly as displayed in the playground -import { TypeScriptGenerator, TS_COMMON_PRESET } from '@asyncapi/modelina'; +import { TypeScriptGenerator, TS_COMMON_PRESET, TS_JSONBINPACK_PRESET } from '@asyncapi/modelina'; ${generateInstanceCode}`; } diff --git a/modelina-website/src/pages/api/functions/TypeScriptGenerator.ts b/modelina-website/src/pages/api/functions/TypeScriptGenerator.ts index 86529db9fb..202f9cee15 100644 --- a/modelina-website/src/pages/api/functions/TypeScriptGenerator.ts +++ b/modelina-website/src/pages/api/functions/TypeScriptGenerator.ts @@ -3,6 +3,7 @@ import { InputProcessor, TS_COMMON_PRESET, TS_DESCRIPTION_PRESET, + TS_JSONBINPACK_PRESET, TypeScriptGenerator, TypeScriptOptions } from '../../../../../'; @@ -22,26 +23,43 @@ export async function getTypeScriptModels( if (generatorOptions.tsModelType) { options.modelType = generatorOptions.tsModelType as any; } - if (generatorOptions.tsMarshalling === true) { + + if (generatorOptions.tsMarshalling === true || + generatorOptions.tsIncludeExampleFunction === true) { + let commonOptions: any = {}; + if(generatorOptions.tsMarshalling === true) { + commonOptions.marshalling = true; + } + + if (generatorOptions.tsIncludeExampleFunction === true) { + commonOptions.example = true; + } + options.presets?.push({ preset: TS_COMMON_PRESET, - options: { - marshalling: true - } + options: commonOptions }); } + + if (generatorOptions.tsIncludeJsonBinPack === true) { + options.presets?.push(TS_JSONBINPACK_PRESET); + } + if (generatorOptions.tsIncludeDescriptions === true) { options.presets?.push({ preset: TS_DESCRIPTION_PRESET, options: {} }); } + if (generatorOptions.tsModuleSystem) { options.moduleSystem = generatorOptions.tsModuleSystem as any; } + if (generatorOptions.tsEnumType) { options.enumType = generatorOptions.tsEnumType as any; } + try { const processedInput = await InputProcessor.processor.process(input); const generator = new TypeScriptGenerator(options); diff --git a/modelina-website/src/types/index.ts b/modelina-website/src/types/index.ts index 5d6140a38b..0d94b2931b 100644 --- a/modelina-website/src/types/index.ts +++ b/modelina-website/src/types/index.ts @@ -15,6 +15,8 @@ export interface ModelinaTypeScriptOptions { tsEnumType: 'union' | 'enum' | undefined; tsModuleSystem: 'ESM' | 'CJS' | undefined; tsIncludeDescriptions: boolean; + tsIncludeJsonBinPack: boolean; + tsIncludeExampleFunction: boolean; } export interface ModelinaJavaOptions {} export interface ModelinaCplusplusOptions {} @@ -76,6 +78,8 @@ export interface ModelinaTypeScriptQueryOptions { tsModelType?: string; tsEnumType?: string; tsIncludeDescriptions?: string; + tsIncludeJsonBinPack?: string; + tsIncludeExampleFunction?: string; } export interface ModelinaOptions From 840669fc28fe715c11dbd13f74fe49d7ea6d312a Mon Sep 17 00:00:00 2001 From: asyncapi-bot Date: Tue, 30 May 2023 23:35:06 +0200 Subject: [PATCH 22/79] fix: update @asyncapi/raml-dt-schema-parser to 4.0.1 version (#1343) Co-authored-by: asyncapi-bot Co-authored-by: asyncapi-bot-eve --- package-lock.json | 20 +++++++++----------- package.json | 2 +- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index e41a69e5bc..de9296a7c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@asyncapi/avro-schema-parser": "^3.0.0", "@asyncapi/openapi-schema-parser": "^3.0.1", "@asyncapi/parser": "^2.0.1", - "@asyncapi/raml-dt-schema-parser": "^4.0.0", + "@asyncapi/raml-dt-schema-parser": "^4.0.1", "@swc/core": "^1.3.5", "@swc/jest": "^0.2.23", "alterschema": "^1.1.2", @@ -201,12 +201,11 @@ } }, "node_modules/@asyncapi/raml-dt-schema-parser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@asyncapi/raml-dt-schema-parser/-/raml-dt-schema-parser-4.0.0.tgz", - "integrity": "sha512-dauYocjmyIKo7oq1rzBOY+mDHzvfa9j8p2luz4co2igZM9HN0L+Xck1M81uvye4Z5zTNW/BG2hu9ngiZAXcQng==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@asyncapi/raml-dt-schema-parser/-/raml-dt-schema-parser-4.0.1.tgz", + "integrity": "sha512-Cf4fzskfVFaESIdMInN5V0ZukSaOG7wzSuFcZiPhni5/m0G8H2+k/ABblHFClsjonLzo1Bhp5JKguW9dbC5oHw==", "dependencies": { - "@asyncapi/parser": "^2.0.0", - "conventional-changelog-conventionalcommits": "^5.0.0", + "@asyncapi/parser": "^2.0.1", "js-yaml": "^4.1.0", "ramldt2jsonschema": "^1.2.3", "webapi-parser": "^0.5.0" @@ -13638,12 +13637,11 @@ } }, "@asyncapi/raml-dt-schema-parser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@asyncapi/raml-dt-schema-parser/-/raml-dt-schema-parser-4.0.0.tgz", - "integrity": "sha512-dauYocjmyIKo7oq1rzBOY+mDHzvfa9j8p2luz4co2igZM9HN0L+Xck1M81uvye4Z5zTNW/BG2hu9ngiZAXcQng==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@asyncapi/raml-dt-schema-parser/-/raml-dt-schema-parser-4.0.1.tgz", + "integrity": "sha512-Cf4fzskfVFaESIdMInN5V0ZukSaOG7wzSuFcZiPhni5/m0G8H2+k/ABblHFClsjonLzo1Bhp5JKguW9dbC5oHw==", "requires": { - "@asyncapi/parser": "^2.0.0", - "conventional-changelog-conventionalcommits": "^5.0.0", + "@asyncapi/parser": "^2.0.1", "js-yaml": "^4.1.0", "ramldt2jsonschema": "^1.2.3", "webapi-parser": "^0.5.0" diff --git a/package.json b/package.json index d6ddd9d8f4..b31e81a640 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@asyncapi/avro-schema-parser": "^3.0.0", "@asyncapi/openapi-schema-parser": "^3.0.1", "@asyncapi/parser": "^2.0.1", - "@asyncapi/raml-dt-schema-parser": "^4.0.0", + "@asyncapi/raml-dt-schema-parser": "^4.0.1", "@swc/core": "^1.3.5", "@swc/jest": "^0.2.23", "alterschema": "^1.1.2", From b4cc721085bbfc970cc1208aacb1fb555f45e852 Mon Sep 17 00:00:00 2001 From: Jonas Lagoni Date: Tue, 30 May 2023 23:48:19 +0200 Subject: [PATCH 23/79] chore(website): add generic playground options (#1309) --- .../contexts/PlaygroundConfigContext.ts | 3 + .../PlaygroundGeneralConfigContext.ts | 9 - .../src/components/playground/Playground.tsx | 82 ++++----- .../playground/PlaygroundOptions.tsx | 2 +- .../playground/options/GeneralOptions.tsx | 131 +++++++++++++- .../helpers/GeneratorCode/CSharpGenerator.ts | 68 ++++---- .../GeneratorCode/CplusplusGenerator.ts | 47 ++--- .../helpers/GeneratorCode/DartGenerator.ts | 45 ++--- .../helpers/GeneratorCode/GeneralGenerator.ts | 163 ++++++++++++++++++ .../src/helpers/GeneratorCode/GoGenerator.ts | 47 ++--- .../helpers/GeneratorCode/JavaGenerator.ts | 45 ++--- .../GeneratorCode/JavaScriptGenerator.ts | 31 ++-- .../helpers/GeneratorCode/KotlinGenerator.ts | 41 +++-- .../src/helpers/GeneratorCode/PhpGenerator.ts | 47 ++--- .../helpers/GeneratorCode/PythonGenerator.ts | 33 ++-- .../helpers/GeneratorCode/RustGenerator.ts | 45 ++--- .../GeneratorCode/TypeScriptGenerator.ts | 68 ++++---- modelina-website/src/helpers/Utils.ts | 49 ++++++ .../pages/api/functions/CSharpGenerator.ts | 30 +++- .../pages/api/functions/CplusplusGenerator.ts | 17 +- .../src/pages/api/functions/DartGenerator.ts | 17 +- .../src/pages/api/functions/GoGenerator.ts | 17 +- .../src/pages/api/functions/Helpers.ts | 127 +++++++++++++- .../src/pages/api/functions/JavaGenerator.ts | 17 +- .../api/functions/JavaScriptGenerator.ts | 8 +- .../pages/api/functions/KotlinGenerator.ts | 17 +- .../src/pages/api/functions/PhpGenerator.ts | 22 ++- .../pages/api/functions/PythonGenerator.ts | 5 +- .../src/pages/api/functions/RustGenerator.ts | 19 +- .../api/functions/TypeScriptGenerator.ts | 21 ++- modelina-website/src/pages/api/generate.ts | 1 + modelina-website/src/types/index.ts | 53 ++++-- 32 files changed, 973 insertions(+), 354 deletions(-) delete mode 100644 modelina-website/src/components/contexts/PlaygroundGeneralConfigContext.ts create mode 100644 modelina-website/src/helpers/GeneratorCode/GeneralGenerator.ts create mode 100644 modelina-website/src/helpers/Utils.ts diff --git a/modelina-website/src/components/contexts/PlaygroundConfigContext.ts b/modelina-website/src/components/contexts/PlaygroundConfigContext.ts index a3af2dcdb7..84e15a4b40 100644 --- a/modelina-website/src/components/contexts/PlaygroundConfigContext.ts +++ b/modelina-website/src/components/contexts/PlaygroundConfigContext.ts @@ -2,6 +2,7 @@ import { ModelinaCplusplusOptions, ModelinaCSharpOptions, ModelinaDartOptions, + ModelinaGeneralOptions, ModelinaGoOptions, ModelinaJavaOptions, ModelinaJavaScriptOptions, @@ -33,5 +34,7 @@ export const PlaygroundPythonConfigContext = createContext(null); export const PlaygroundCplusplusConfigContext = createContext(null); +export const PlaygroundGeneralConfigContext = + createContext(null); export const PlaygroundPhpConfigContext = createContext(null); diff --git a/modelina-website/src/components/contexts/PlaygroundGeneralConfigContext.ts b/modelina-website/src/components/contexts/PlaygroundGeneralConfigContext.ts deleted file mode 100644 index 9174828a2a..0000000000 --- a/modelina-website/src/components/contexts/PlaygroundGeneralConfigContext.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createContext } from 'react'; - -export interface PlaygroundGeneralConfig { - language: string; - showAllInOneFile?: boolean; -} - -export const PlaygroundGeneralConfigContext = - createContext(null); diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index 57b37dcbce..23bafcdea5 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -14,7 +14,6 @@ import PlaygroundOptions from './PlaygroundOptions'; import Heading from '../typography/Heading'; import Paragraph from '../typography/Paragraph'; import { PlaygroundGeneratedContext } from '../contexts/PlaygroundGeneratedContext'; -import { PlaygroundGeneralConfigContext } from '../contexts/PlaygroundGeneralConfigContext'; import { PlaygroundTypeScriptConfigContext, PlaygroundCSharpConfigContext, @@ -26,6 +25,7 @@ import { PlaygroundPythonConfigContext, PlaygroundRustConfigContext, PlaygroundCplusplusConfigContext, + PlaygroundGeneralConfigContext, PlaygroundPhpConfigContext } from '../contexts/PlaygroundConfigContext'; import { getTypeScriptGeneratorCode } from '@/helpers/GeneratorCode/TypeScriptGenerator'; @@ -73,6 +73,11 @@ class Playground extends React.Component< > { config: ModelinaOptions = { language: 'typescript', + propertyNamingFormat: 'default', + modelNamingFormat: 'default', + enumKeyNamingFormat: 'default', + indentationType: 'spaces', + showTypeMappingExample: false, tsMarshalling: false, tsModelType: 'class', tsEnumType: 'enum', @@ -198,6 +203,24 @@ class Playground extends React.Component< const isLoaded = isHardLoaded && isSoftLoaded; const query = this.props.router.query as ModelinaQueryOptions; + if (query.language !== undefined) { + this.config.language = query.language as any; + } + if (query.enumKeyNamingFormat !== undefined) { + this.config.enumKeyNamingFormat = query.enumKeyNamingFormat as any; + } + if (query.propertyNamingFormat !== undefined) { + this.config.propertyNamingFormat = query.propertyNamingFormat as any; + } + if (query.modelNamingFormat !== undefined) { + this.config.modelNamingFormat = query.modelNamingFormat as any; + } + if (query.showTypeMappingExample !== undefined) { + this.config.showTypeMappingExample = query.showTypeMappingExample === 'true'; + } + if (query.indentationType !== undefined) { + this.config.indentationType = query.indentationType as any; + } if (query.tsMarshalling !== undefined) { this.config.tsMarshalling = query.tsMarshalling === 'true'; } @@ -219,9 +242,6 @@ class Playground extends React.Component< this.config.tsIncludeExampleFunction = query.tsIncludeExampleFunction === 'true'; } - if (query.language !== undefined) { - this.config.language = query.language as any; - } if (query.csharpArrayType !== undefined) { this.config.csharpArrayType = query.csharpArrayType as any; } @@ -328,47 +348,19 @@ class Playground extends React.Component< />

) : ( - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/modelina-website/src/components/playground/PlaygroundOptions.tsx b/modelina-website/src/components/playground/PlaygroundOptions.tsx index 924632f92d..85ec5a1de3 100644 --- a/modelina-website/src/components/playground/PlaygroundOptions.tsx +++ b/modelina-website/src/components/playground/PlaygroundOptions.tsx @@ -1,7 +1,6 @@ import React from 'react'; import TypeScriptGeneratorOptions from './options/TypeScriptGeneratorOptions'; import GeneralOptions from './options/GeneralOptions'; -import { PlaygroundGeneralConfigContext } from '../contexts/PlaygroundGeneralConfigContext'; import JavaScriptGeneratorOptions from './options/JavaScriptGeneratorOptions'; import CSharpGeneratorOptions from './options/CSharpGeneratorOptions'; import DartGeneratorOptions from './options/DartGeneratorOptions'; @@ -12,6 +11,7 @@ import RustGeneratorOptions from './options/RustGeneratorOptions'; import PythonGeneratorOptions from './options/PythonGeneratorOptions'; import CplusplusGeneratorOptions from './options/CplusplusGeneratorOptions'; import PhpGeneratorOptions from './options/PhpGeneratorOptions'; +import { PlaygroundGeneralConfigContext } from '../contexts/PlaygroundConfigContext'; interface WithRouterProps { setNewConfig?: (queryKey: string, queryValue: string) => void; diff --git a/modelina-website/src/components/playground/options/GeneralOptions.tsx b/modelina-website/src/components/playground/options/GeneralOptions.tsx index 221fe6e5c5..c8ddcb181b 100644 --- a/modelina-website/src/components/playground/options/GeneralOptions.tsx +++ b/modelina-website/src/components/playground/options/GeneralOptions.tsx @@ -1,7 +1,7 @@ import React from 'react'; import Select from '../../Select'; import { modelinaLanguageOptions } from '@/types'; -import { PlaygroundGeneralConfigContext } from '@/components/contexts/PlaygroundGeneralConfigContext'; +import { PlaygroundGeneralConfigContext } from '@/components/contexts/PlaygroundConfigContext'; interface WithRouterProps { setNewConfig?: (queryKey: string, queryValue: string) => void; @@ -21,6 +21,11 @@ class GeneralOptions extends React.Component< super(props); this.state = defaultState; this.onChangeLanguage = this.onChangeLanguage.bind(this); + this.onChangeShowTypeMappingExample = this.onChangeShowTypeMappingExample.bind(this); + this.onChangeIndentationType = this.onChangeIndentationType.bind(this); + this.onChangePropertyNamingFormat = this.onChangePropertyNamingFormat.bind(this); + this.onChangeModelNamingFormat = this.onChangeModelNamingFormat.bind(this); + this.onChangeEnumKeyNamingFormat = this.onChangeEnumKeyNamingFormat.bind(this); } onChangeLanguage(language: any) { @@ -29,6 +34,36 @@ class GeneralOptions extends React.Component< } } + onChangeShowTypeMappingExample(event: any) { + if (this.props.setNewConfig) { + this.props.setNewConfig('showTypeMappingExample', event.target.checked); + } + } + + onChangeIndentationType(value: any) { + if (this.props.setNewConfig) { + this.props.setNewConfig('indentationType', String(value)); + } + } + + onChangePropertyNamingFormat(value: any) { + if (this.props.setNewConfig) { + this.props.setNewConfig('propertyNamingFormat', String(value)); + } + } + + onChangeModelNamingFormat(value: any) { + if (this.props.setNewConfig) { + this.props.setNewConfig('modelNamingFormat', String(value)); + } + } + + onChangeEnumKeyNamingFormat(value: any) { + if (this.props.setNewConfig) { + this.props.setNewConfig('enumKeyNamingFormat', String(value)); + } + } + render() { return (
    @@ -48,6 +83,100 @@ class GeneralOptions extends React.Component< /> +
  • + +
  • +
  • + +
  • +
  • + +
); } diff --git a/modelina-website/src/helpers/GeneratorCode/CSharpGenerator.ts b/modelina-website/src/helpers/GeneratorCode/CSharpGenerator.ts index b41217faf7..f003418cd8 100644 --- a/modelina-website/src/helpers/GeneratorCode/CSharpGenerator.ts +++ b/modelina-website/src/helpers/GeneratorCode/CSharpGenerator.ts @@ -1,10 +1,11 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { ModelinaCSharpOptions } from '../../types'; +import { getGeneralGeneratorCode, renderGeneratorInstanceCode } from './GeneralGenerator'; export function getCSharpGeneratorCode( generatorOptions: ModelinaCSharpOptions ) { - const optionString: string[] = []; + const optionString: string[] = getGeneralGeneratorCode(generatorOptions, 'csharpDefaultEnumKeyConstraints', 'csharpDefaultPropertyKeyConstraints', 'csharpDefaultModelNameConstraints'); const optionStringPresets: string[] = []; if (generatorOptions.csharpArrayType) { @@ -13,54 +14,51 @@ export function getCSharpGeneratorCode( if (generatorOptions.csharpAutoImplemented) { optionString.push( - ` autoImplementedProperties: ${generatorOptions.csharpAutoImplemented}` + `autoImplementedProperties: ${generatorOptions.csharpAutoImplemented}` ); } + if(generatorOptions.showTypeMappingExample === true) { + optionString.push(`typeMapping: { + Integer: ({ dependencyManager, constrainedModel, options, partOfProperty }) => { + // Add custom dependency for your type if required. + dependencyManager.addDependency('using My.Namespace;'); + + //Return the type for the integer model + return 'MyIntegerType'; + } +}`); + } + if (generatorOptions.csharpOverwriteHashcode) { - optionStringPresets.push(` - { - preset: CSHARP_COMMON_PRESET, - options: { - equal: false, - hashCode: true - } - }`) + optionStringPresets.push(`{ + preset: CSHARP_COMMON_PRESET, + options: { + equal: false, + hashCode: true + } +}`) } if (generatorOptions.csharpIncludeJson) { - optionStringPresets.push(` - CSHARP_JSON_SERIALIZER_PRESET - `) + optionStringPresets.push(`CSHARP_JSON_SERIALIZER_PRESET`) } if (generatorOptions.csharpIncludeNewtonsoft) { - optionStringPresets.push(` - CSHARP_NEWTONSOFT_SERIALIZER_PRESET - `) + optionStringPresets.push(`CSHARP_NEWTONSOFT_SERIALIZER_PRESET`) } - const presetOptions = - optionStringPresets.length > 0 - ? `${optionString.length > 0 ? ',' : ''} - presets: [ - ${optionStringPresets.join(', \n')} - ]` - : ''; - let fullOptions = ''; - if (optionStringPresets.length > 0 || optionString.length > 0) { - fullOptions = `{ - ${optionString.join(';\n')}${presetOptions} - }`; - } - const generateInstanceCode = - `const generator = new CSharpGenerator(${fullOptions});`.replace( - /^\s*\n/gm, - '' - ); + const generateInstanceCode = renderGeneratorInstanceCode(optionString, optionStringPresets, 'CSharpGenerator'); return `// Use the following code as starting point // To generate the models exactly as displayed in the playground -import { CSharpGenerator } from '@asyncapi/modelina'; +import { + CSharpGenerator, + IndentationTypes, + FormatHelpers, + csharpDefaultEnumKeyConstraints, + csharpDefaultModelNameConstraints, + csharpDefaultPropertyKeyConstraints +} from '@asyncapi/modelina'; ${generateInstanceCode}`; } diff --git a/modelina-website/src/helpers/GeneratorCode/CplusplusGenerator.ts b/modelina-website/src/helpers/GeneratorCode/CplusplusGenerator.ts index 790312ec24..304a25bc25 100644 --- a/modelina-website/src/helpers/GeneratorCode/CplusplusGenerator.ts +++ b/modelina-website/src/helpers/GeneratorCode/CplusplusGenerator.ts @@ -1,32 +1,37 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { ModelinaCplusplusOptions } from '../../types'; +import { getGeneralGeneratorCode, renderGeneratorInstanceCode } from './GeneralGenerator'; -export function getCplusplusGeneratorCode(generatorOptions: ModelinaCplusplusOptions) { - const optionString: string[] = []; +export function getCplusplusGeneratorCode( + generatorOptions: ModelinaCplusplusOptions +) { + const optionString: string[] = getGeneralGeneratorCode(generatorOptions, 'cplusplusDefaultEnumKeyConstraints', 'cplusplusDefaultPropertyKeyConstraints', 'cplusplusDefaultModelNameConstraints'); const optionStringPresets: string[] = []; - const presetOptions = - optionStringPresets.length > 0 - ? `${optionString.length > 0 ? ',' : ''} - presets: [ - ${optionStringPresets.join(', \n')} - ]` - : ''; - let fullOptions = ''; - if (optionStringPresets.length > 0 || optionString.length > 0) { - fullOptions = `{ - ${optionString.join(';\n')}${presetOptions} - }`; + if(generatorOptions.showTypeMappingExample === true) { + optionString.push(`typeMapping: { + Integer: ({ dependencyManager, constrainedModel, options, partOfProperty }) => { + // Add custom dependency for your type if required. + dependencyManager.addDependency('#include '); + + //Return the type for the integer model + return 'MyIntegerType'; + } +}`); } - const generateInstanceCode = - `const generator = new CplusplusGenerator(${fullOptions});`.replace( - /^\s*\n/gm, - '' - ); + + const generateInstanceCode = renderGeneratorInstanceCode(optionString, optionStringPresets, 'CplusplusGenerator'); return `// Use the following code as starting point // To generate the models exactly as displayed in the playground -import { CplusplusGenerator } from '@asyncapi/modelina'; - +import { + CplusplusGenerator, + IndentationTypes, + FormatHelpers, + cplusplusDefaultEnumKeyConstraints, + cplusplusDefaultPropertyKeyConstraints, + cplusplusDefaultModelNameConstraints +} from '@asyncapi/modelina'; + ${generateInstanceCode}`; } diff --git a/modelina-website/src/helpers/GeneratorCode/DartGenerator.ts b/modelina-website/src/helpers/GeneratorCode/DartGenerator.ts index 93929d6473..44811687cb 100644 --- a/modelina-website/src/helpers/GeneratorCode/DartGenerator.ts +++ b/modelina-website/src/helpers/GeneratorCode/DartGenerator.ts @@ -1,32 +1,37 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { ModelinaDartOptions } from '../../types'; +import { getGeneralGeneratorCode, renderGeneratorInstanceCode } from './GeneralGenerator'; -export function getDartGeneratorCode(generatorOptions: ModelinaDartOptions) { - const optionString: string[] = []; +export function getDartGeneratorCode( + generatorOptions: ModelinaDartOptions +) { + const optionString: string[] = getGeneralGeneratorCode(generatorOptions, 'dartDefaultEnumKeyConstraints', 'dartDefaultPropertyKeyConstraints', 'dartDefaultModelNameConstraints'); const optionStringPresets: string[] = []; - const presetOptions = - optionStringPresets.length > 0 - ? `${optionString.length > 0 ? ',' : ''} - presets: [ - ${optionStringPresets.join(', \n')} - ]` - : ''; - let fullOptions = ''; - if (optionStringPresets.length > 0 || optionString.length > 0) { - fullOptions = `{ - ${optionString.join(';\n')}${presetOptions} - }`; + if(generatorOptions.showTypeMappingExample === true) { + optionString.push(`typeMapping: { + Integer: ({ dependencyManager, constrainedModel, options, partOfProperty }) => { + // Add custom dependency for your type if required. + dependencyManager.addDependency('import 'package:lib/lib.dart' as lib;'); + + //Return the type for the integer model + return 'lib.MyIntegerType'; + } +}`); } - const generateInstanceCode = - `const generator = new DartGenerator(${fullOptions});`.replace( - /^\s*\n/gm, - '' - ); + + const generateInstanceCode = renderGeneratorInstanceCode(optionString, optionStringPresets, 'DartGenerator'); return `// Use the following code as starting point // To generate the models exactly as displayed in the playground -import { DartGenerator } from '@asyncapi/modelina'; +import { + DartGenerator, + IndentationTypes, + FormatHelpers, + dartDefaultEnumKeyConstraints, + dartDefaultModelNameConstraints, + dartDefaultPropertyKeyConstraints +} from '@asyncapi/modelina'; ${generateInstanceCode}`; } diff --git a/modelina-website/src/helpers/GeneratorCode/GeneralGenerator.ts b/modelina-website/src/helpers/GeneratorCode/GeneralGenerator.ts new file mode 100644 index 0000000000..e7358e60bb --- /dev/null +++ b/modelina-website/src/helpers/GeneratorCode/GeneralGenerator.ts @@ -0,0 +1,163 @@ +import { ModelinaGeneralOptions } from "@/types"; +import { IndentationTypes, indent } from "../Utils"; + +/** + * Even if each language has their own constraints, naming formatting, is something that always remain the same + */ +export function getGeneralGeneratorCode( + generatorOptions: ModelinaGeneralOptions, + enumKeyConstraints: string, + propertyKeyConstraints: string, + modelNameConstraints: string): string[] { + const optionString: string[] = []; + const constraints = []; + + if (generatorOptions.enumKeyNamingFormat !== 'default') { + switch (generatorOptions.enumKeyNamingFormat) { + case 'camel_case': + constraints.push(`enumKey: ${enumKeyConstraints}({ + NAMING_FORMATTER: FormatHelpers.toCamelCase +})`); + break; + case 'constant_case': + constraints.push(`enumKey: ${enumKeyConstraints}({ + NAMING_FORMATTER: FormatHelpers.toConstantCase +})`); + break; + case 'param_case': + constraints.push(`enumKey: ${enumKeyConstraints}({ + NAMING_FORMATTER: FormatHelpers.toParamCase +})`); + break; + case 'pascal_case': + constraints.push(`enumKey: ${enumKeyConstraints}({ + NAMING_FORMATTER: FormatHelpers.toPascalCase +})`); + break; + case 'snake_case': + constraints.push(`enumKey: ${enumKeyConstraints}({ + NAMING_FORMATTER: FormatHelpers.toSnakeCase +})`); + break; + default: + break; + } + } + if (generatorOptions.propertyNamingFormat !== 'default') { + switch (generatorOptions.propertyNamingFormat) { + case 'camel_case': + constraints.push(`propertyKey: ${propertyKeyConstraints}({ + NAMING_FORMATTER: FormatHelpers.toCamelCase +})`); + break; + case 'constant_case': + constraints.push(`propertyKey: ${propertyKeyConstraints}({ + NAMING_FORMATTER: FormatHelpers.toConstantCase +})`); + break; + case 'param_case': + constraints.push(`propertyKey: ${propertyKeyConstraints}({ + NAMING_FORMATTER: FormatHelpers.toParamCase +})`); + break; + case 'pascal_case': + constraints.push(`propertyKey: ${propertyKeyConstraints}({ + NAMING_FORMATTER: FormatHelpers.toPascalCase +})`); + break; + case 'snake_case': + constraints.push(`propertyKey: ${propertyKeyConstraints}({ + NAMING_FORMATTER: FormatHelpers.toSnakeCase +})`); + break; + default: + break; + } + } + if (generatorOptions.modelNamingFormat !== 'default') { + switch (generatorOptions.modelNamingFormat) { + case 'camel_case': + constraints.push(`modelName: ${modelNameConstraints}({ + NAMING_FORMATTER: FormatHelpers.toCamelCase +})`); + break; + case 'constant_case': + constraints.push(`modelName: ${modelNameConstraints}({ + NAMING_FORMATTER: FormatHelpers.toConstantCase +})`); + break; + case 'param_case': + constraints.push(`modelName: ${modelNameConstraints}({ + NAMING_FORMATTER: FormatHelpers.toParamCase +})`); + break; + case 'pascal_case': + constraints.push(`modelName: ${modelNameConstraints}({ + NAMING_FORMATTER: FormatHelpers.toPascalCase +})`); + break; + case 'snake_case': + constraints.push(`modelName: ${modelNameConstraints}({ + NAMING_FORMATTER: FormatHelpers.toSnakeCase +})`); + break; + default: + break; + } + } + if(constraints.length > 0) { + optionString.push(`constraints: { +${constraints.map((value) => { + return indent(value, 2, IndentationTypes.SPACES); +}).join(',\n')} +}`); + } + + if (generatorOptions.indentationType) { + switch (generatorOptions.indentationType) { + case 'spaces': + optionString.push(`indentation: { + type: IndentationTypes.SPACES +}`); + break; + case 'tabs': + optionString.push(`indentation: { + type: IndentationTypes.TABS +}`); + break; + default: + break; + } + } + return optionString; +} + +/** + * Rendering of options are pretty generic, this function handles that rendering. + */ +export function renderGeneratorInstanceCode(optionString: string[], optionStringPresets: string[], generatorName: string) { + const renderedPresets = optionStringPresets.map((value) => { + return indent(value, 2, IndentationTypes.SPACES); + }).join(', \n'); + const spacer = optionString.length > 0 ? ',' : ''; + const presetOptions = + optionStringPresets.length > 0 + ? `${spacer}\n presets: [ +${renderedPresets} +]` : ''; + let fullOptions = ''; + if (optionStringPresets.length > 0 || optionString.length > 0) { + const renderedOptions = optionString.map((value) => { + return indent(value, 2, IndentationTypes.SPACES); + }).join(',\n'); + fullOptions = `{ +${renderedOptions} +${presetOptions} +}`; + } + const generateInstanceCode = `const generator = new ${generatorName}(${fullOptions});`.replace( + /^\s*\n/gm, + '' + ); + return generateInstanceCode; +} \ No newline at end of file diff --git a/modelina-website/src/helpers/GeneratorCode/GoGenerator.ts b/modelina-website/src/helpers/GeneratorCode/GoGenerator.ts index 87a6b19054..856bc45766 100644 --- a/modelina-website/src/helpers/GeneratorCode/GoGenerator.ts +++ b/modelina-website/src/helpers/GeneratorCode/GoGenerator.ts @@ -1,32 +1,37 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { ModelinaGoOptions } from '../../types'; +import { getGeneralGeneratorCode, renderGeneratorInstanceCode } from './GeneralGenerator'; -export function getGoGeneratorCode(generatorOptions: ModelinaGoOptions) { - const optionString: string[] = []; +export function getGoGeneratorCode( + generatorOptions: ModelinaGoOptions +) { + const optionString: string[] = getGeneralGeneratorCode(generatorOptions, 'goDefaultEnumKeyConstraints', 'goDefaultPropertyKeyConstraints', 'goDefaultModelNameConstraints'); const optionStringPresets: string[] = []; - const presetOptions = - optionStringPresets.length > 0 - ? `${optionString.length > 0 ? ',' : ''} - presets: [ - ${optionStringPresets.join(', \n')} - ]` - : ''; - let fullOptions = ''; - if (optionStringPresets.length > 0 || optionString.length > 0) { - fullOptions = `{ - ${optionString.join(';\n')}${presetOptions} - }`; + if(generatorOptions.showTypeMappingExample === true) { + optionString.push(`typeMapping: { + Integer: ({ dependencyManager, constrainedModel, options, partOfProperty }) => { + // Add custom dependency for your type if required. + dependencyManager.addDependency('parent "family/father"'); + + //Return the type for the integer model + return 'int64'; + } +}`); } - const generateInstanceCode = - `const generator = new GoGenerator(${fullOptions});`.replace( - /^\s*\n/gm, - '' - ); + + const generateInstanceCode = renderGeneratorInstanceCode(optionString, optionStringPresets, 'GoGenerator'); return `// Use the following code as starting point // To generate the models exactly as displayed in the playground -import { GoGenerator } from '@asyncapi/modelina'; - +import { + GoGenerator, + IndentationTypes, + FormatHelpers, + goDefaultEnumKeyConstraints, + goDefaultModelNameConstraints, + goDefaultPropertyKeyConstraints +} from '@asyncapi/modelina'; + ${generateInstanceCode}`; } diff --git a/modelina-website/src/helpers/GeneratorCode/JavaGenerator.ts b/modelina-website/src/helpers/GeneratorCode/JavaGenerator.ts index 40a5b7a554..495eec1b80 100644 --- a/modelina-website/src/helpers/GeneratorCode/JavaGenerator.ts +++ b/modelina-website/src/helpers/GeneratorCode/JavaGenerator.ts @@ -1,32 +1,37 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { ModelinaJavaOptions } from '../../types'; +import { getGeneralGeneratorCode, renderGeneratorInstanceCode } from './GeneralGenerator'; -export function getJavaGeneratorCode(generatorOptions: ModelinaJavaOptions) { - const optionString: string[] = []; +export function getJavaGeneratorCode( + generatorOptions: ModelinaJavaOptions +) { + const optionString: string[] = getGeneralGeneratorCode(generatorOptions, 'javaDefaultEnumKeyConstraints', 'javaDefaultPropertyKeyConstraints', 'javaDefaultModelNameConstraints'); const optionStringPresets: string[] = []; - const presetOptions = - optionStringPresets.length > 0 - ? `${optionString.length > 0 ? ',' : ''} - presets: [ - ${optionStringPresets.join(', \n')} - ]` - : ''; - let fullOptions = ''; - if (optionStringPresets.length > 0 || optionString.length > 0) { - fullOptions = `{ - ${optionString.join(';\n')}${presetOptions} - }`; + if(generatorOptions.showTypeMappingExample === true) { + optionString.push(`typeMapping: { + Integer: ({ dependencyManager, constrainedModel, options, partOfProperty }) => { + // Add custom dependency for your type if required. + dependencyManager.addDependency('import java.util.ArrayList;'); + + //Return the type for the integer model + return 'long'; + } +}`); } - const generateInstanceCode = - `const generator = new JavaGenerator(${fullOptions});`.replace( - /^\s*\n/gm, - '' - ); + + const generateInstanceCode = renderGeneratorInstanceCode(optionString, optionStringPresets, 'JavaGenerator'); return `// Use the following code as starting point // To generate the models exactly as displayed in the playground -import { JavaGenerator } from '@asyncapi/modelina'; +import { + JavaGenerator, + IndentationTypes, + FormatHelpers, + javaDefaultEnumKeyConstraints, + javaDefaultModelNameConstraints, + javaDefaultPropertyKeyConstraints +} from '@asyncapi/modelina'; ${generateInstanceCode}`; } diff --git a/modelina-website/src/helpers/GeneratorCode/JavaScriptGenerator.ts b/modelina-website/src/helpers/GeneratorCode/JavaScriptGenerator.ts index 0897240bc7..1796284aa0 100644 --- a/modelina-website/src/helpers/GeneratorCode/JavaScriptGenerator.ts +++ b/modelina-website/src/helpers/GeneratorCode/JavaScriptGenerator.ts @@ -1,34 +1,25 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { ModelinaJavaScriptOptions } from '../../types'; +import { getGeneralGeneratorCode, renderGeneratorInstanceCode } from './GeneralGenerator'; export function getJavaScriptGeneratorCode( generatorOptions: ModelinaJavaScriptOptions ) { - const optionString: string[] = []; + const optionString: string[] = getGeneralGeneratorCode(generatorOptions, 'javaScriptDefaultEnumKeyConstraints', 'javaScriptDefaultPropertyKeyConstraints', 'javaScriptDefaultModelNameConstraints'); const optionStringPresets: string[] = []; - const presetOptions = - optionStringPresets.length > 0 - ? `${optionString.length > 0 ? ',' : ''} - presets: [ - ${optionStringPresets.join(', \n')} - ]` - : ''; - let fullOptions = ''; - if (optionStringPresets.length > 0 || optionString.length > 0) { - fullOptions = `{ - ${optionString.join(';\n')}${presetOptions} - }`; - } - const generateInstanceCode = - `const generator = new JavaScriptGenerator(${fullOptions});`.replace( - /^\s*\n/gm, - '' - ); + const generateInstanceCode = renderGeneratorInstanceCode(optionString, optionStringPresets, 'JavaScriptGenerator'); return `// Use the following code as starting point // To generate the models exactly as displayed in the playground -import { JavaScriptGenerator } from '@asyncapi/modelina'; +import { + JavaScriptGenerator, + IndentationTypes, + FormatHelpers, + javaScriptDefaultEnumKeyConstraints, + javaScriptDefaultModelNameConstraints, + javaScriptDefaultPropertyKeyConstraints +} from '@asyncapi/modelina'; ${generateInstanceCode}`; } diff --git a/modelina-website/src/helpers/GeneratorCode/KotlinGenerator.ts b/modelina-website/src/helpers/GeneratorCode/KotlinGenerator.ts index 0f605ef648..1447cde640 100644 --- a/modelina-website/src/helpers/GeneratorCode/KotlinGenerator.ts +++ b/modelina-website/src/helpers/GeneratorCode/KotlinGenerator.ts @@ -1,34 +1,37 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { ModelinaKotlinOptions } from '../../types'; +import { getGeneralGeneratorCode, renderGeneratorInstanceCode } from './GeneralGenerator'; export function getKotlinGeneratorCode( generatorOptions: ModelinaKotlinOptions ) { - const optionString: string[] = []; + const optionString: string[] = getGeneralGeneratorCode(generatorOptions, 'kotlinDefaultEnumKeyConstraints', 'kotlinDefaultPropertyKeyConstraints', 'kotlinDefaultModelNameConstraints'); const optionStringPresets: string[] = []; - const presetOptions = - optionStringPresets.length > 0 - ? `${optionString.length > 0 ? ',' : ''} - presets: [ - ${optionStringPresets.join(', \n')} - ]` - : ''; - let fullOptions = ''; - if (optionStringPresets.length > 0 || optionString.length > 0) { - fullOptions = `{ - ${optionString.join(';\n')}${presetOptions} - }`; + if(generatorOptions.showTypeMappingExample === true) { + optionString.push(`typeMapping: { + Integer: ({ dependencyManager, constrainedModel, options, partOfProperty }) => { + // Add custom dependency for your type if required. + dependencyManager.addDependency('import kotlinx.datetime.*'); + + //Return the type for the integer model + return 'LocalDate'; + } +}`); } - const generateInstanceCode = - `const generator = new KotlinGenerator(${fullOptions});`.replace( - /^\s*\n/gm, - '' - ); + + const generateInstanceCode = renderGeneratorInstanceCode(optionString, optionStringPresets, 'KotlinGenerator'); return `// Use the following code as starting point // To generate the models exactly as displayed in the playground -import { KotlinGenerator } from '@asyncapi/modelina'; +import { + KotlinGenerator, + IndentationTypes, + FormatHelpers, + kotlinDefaultEnumKeyConstraints, + kotlinDefaultModelNameConstraints, + kotlinDefaultPropertyKeyConstraints +} from '@asyncapi/modelina'; ${generateInstanceCode}`; } diff --git a/modelina-website/src/helpers/GeneratorCode/PhpGenerator.ts b/modelina-website/src/helpers/GeneratorCode/PhpGenerator.ts index 344656a6f8..a91596aa97 100644 --- a/modelina-website/src/helpers/GeneratorCode/PhpGenerator.ts +++ b/modelina-website/src/helpers/GeneratorCode/PhpGenerator.ts @@ -1,38 +1,43 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { ModelinaPhpOptions } from '../../types'; +import { getGeneralGeneratorCode, renderGeneratorInstanceCode } from './GeneralGenerator'; export function getPhpGeneratorCode(generatorOptions: ModelinaPhpOptions) { - const optionString: string[] = []; + const optionString: string[] = getGeneralGeneratorCode(generatorOptions, 'phpDefaultEnumKeyConstraints', 'phpDefaultPropertyKeyConstraints', 'phpDefaultModelNameConstraints'); const optionStringPresets: string[] = []; if (generatorOptions.phpIncludeDescriptions === true) { optionStringPresets.push(`{ - preset: PHP_DESCRIPTION_PRESET, - }`); + preset: PHP_DESCRIPTION_PRESET, + }`); } - const presetOptions = - optionStringPresets.length > 0 - ? `${optionString.length > 0 ? ',' : ''} - presets: [ - ${optionStringPresets.join(', \n')} - ]` - : ''; - let fullOptions = ''; - if (optionStringPresets.length > 0 || optionString.length > 0) { - fullOptions = `{ - ${optionString.join(';\n')}${presetOptions} - }`; + if(generatorOptions.showTypeMappingExample === true) { + optionString.push(`typeMapping: { + Integer: ({ dependencyManager, constrainedModel, options, partOfProperty }) => { + // Add custom dependency for your type if required. + // This support function makes sure that when changing the module system dependencies change accordingly. + dependencyManager.addDependency('use ArrayObject'); + + //Return the type for the integer model + return 'ArrayObject'; + } +}`); } - const generateInstanceCode = - `const generator = new PhpGenerator(${fullOptions});`.replace( - /^\s*\n/gm, - '' - ); + + const generateInstanceCode = renderGeneratorInstanceCode(optionString, optionStringPresets, 'PhpGenerator'); return `// Use the following code as starting point // To generate the models exactly as displayed in the playground -import { PhpGenerator, PHP_DESCRIPTION_PRESET } from '@asyncapi/modelina'; +import { + PhpGenerator, + PHP_DESCRIPTION_PRESET, + IndentationTypes, + FormatHelpers, + phpDefaultEnumKeyConstraints, + phpDefaultPropertyKeyConstraints, + phpDefaultModelNameConstraints +} from '@asyncapi/modelina'; ${generateInstanceCode}`; } diff --git a/modelina-website/src/helpers/GeneratorCode/PythonGenerator.ts b/modelina-website/src/helpers/GeneratorCode/PythonGenerator.ts index 463bca5f41..43a1ed1dea 100644 --- a/modelina-website/src/helpers/GeneratorCode/PythonGenerator.ts +++ b/modelina-website/src/helpers/GeneratorCode/PythonGenerator.ts @@ -1,34 +1,25 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { ModelinaPythonOptions } from '../../types'; +import { getGeneralGeneratorCode, renderGeneratorInstanceCode } from './GeneralGenerator'; export function getPythonGeneratorCode( generatorOptions: ModelinaPythonOptions ) { - const optionString: string[] = []; + const optionString: string[] = getGeneralGeneratorCode(generatorOptions, 'pythonDefaultEnumKeyConstraints', 'pythonDefaultPropertyKeyConstraints', 'pythonDefaultModelNameConstraints'); const optionStringPresets: string[] = []; - const presetOptions = - optionStringPresets.length > 0 - ? `${optionString.length > 0 ? ',' : ''} - presets: [ - ${optionStringPresets.join(', \n')} - ]` - : ''; - let fullOptions = ''; - if (optionStringPresets.length > 0 || optionString.length > 0) { - fullOptions = `{ - ${optionString.join(';\n')}${presetOptions} - }`; - } - const generateInstanceCode = - `const generator = new PythonGenerator(${fullOptions});`.replace( - /^\s*\n/gm, - '' - ); - + const generateInstanceCode = renderGeneratorInstanceCode(optionString, optionStringPresets, 'PythonGenerator'); + return `// Use the following code as starting point // To generate the models exactly as displayed in the playground -import { PythonGenerator } from '@asyncapi/modelina'; +import { + PythonGenerator, + IndentationTypes, + FormatHelpers, + pythonDefaultEnumKeyConstraints, + pythonDefaultModelNameConstraints, + pythonDefaultPropertyKeyConstraints +} from '@asyncapi/modelina'; ${generateInstanceCode}`; } diff --git a/modelina-website/src/helpers/GeneratorCode/RustGenerator.ts b/modelina-website/src/helpers/GeneratorCode/RustGenerator.ts index 5d7c2d915f..88659e4e20 100644 --- a/modelina-website/src/helpers/GeneratorCode/RustGenerator.ts +++ b/modelina-website/src/helpers/GeneratorCode/RustGenerator.ts @@ -1,32 +1,37 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { ModelinaRustOptions } from '../../types'; +import { getGeneralGeneratorCode, renderGeneratorInstanceCode } from './GeneralGenerator'; -export function getRustGeneratorCode(generatorOptions: ModelinaRustOptions) { - const optionString: string[] = []; +export function getRustGeneratorCode( + generatorOptions: ModelinaRustOptions +) { + const optionString: string[] = getGeneralGeneratorCode(generatorOptions, 'rustDefaultEnumKeyConstraints', 'rustDefaultPropertyKeyConstraints', 'rustDefaultModelNameConstraints'); const optionStringPresets: string[] = []; - const presetOptions = - optionStringPresets.length > 0 - ? `${optionString.length > 0 ? ',' : ''} - presets: [ - ${optionStringPresets.join(', \n')} - ]` - : ''; - let fullOptions = ''; - if (optionStringPresets.length > 0 || optionString.length > 0) { - fullOptions = `{ - ${optionString.join(';\n')}${presetOptions} - }`; + if(generatorOptions.showTypeMappingExample === true) { + optionString.push(`typeMapping: { + Integer: ({ dependencyManager, constrainedModel, options, partOfProperty }) => { + // Add custom dependency for your type if required. + dependencyManager.addDependency('mod my;'); + + //Return the type for the integer model + return 'my::IntegerType'; + } +}`); } - const generateInstanceCode = - `const generator = new RustGenerator(${fullOptions});`.replace( - /^\s*\n/gm, - '' - ); + + const generateInstanceCode = renderGeneratorInstanceCode(optionString, optionStringPresets, 'RustGenerator'); return `// Use the following code as starting point // To generate the models exactly as displayed in the playground -import { RustGenerator } from '@asyncapi/modelina'; +import { + RustGenerator, + IndentationTypes, + FormatHelpers, + rustDefaultEnumKeyConstraints, + rustDefaultModelNameConstraints, + rustDefaultPropertyKeyConstraints +} from '@asyncapi/modelina'; ${generateInstanceCode}`; } diff --git a/modelina-website/src/helpers/GeneratorCode/TypeScriptGenerator.ts b/modelina-website/src/helpers/GeneratorCode/TypeScriptGenerator.ts index 2e1a9d5897..0e6c267ff7 100644 --- a/modelina-website/src/helpers/GeneratorCode/TypeScriptGenerator.ts +++ b/modelina-website/src/helpers/GeneratorCode/TypeScriptGenerator.ts @@ -1,16 +1,23 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { ModelinaTypeScriptOptions } from '../../types'; +import { getGeneralGeneratorCode, renderGeneratorInstanceCode } from './GeneralGenerator'; export function getTypeScriptGeneratorCode( generatorOptions: ModelinaTypeScriptOptions ) { - const optionString = []; + const optionString: string[] = getGeneralGeneratorCode(generatorOptions, 'typeScriptDefaultEnumKeyConstraints', 'typeScriptDefaultPropertyKeyConstraints', 'typeScriptDefaultModelNameConstraints'); const optionStringPresets = []; if (generatorOptions.tsModelType) { optionString.push(`modelType: '${generatorOptions.tsModelType}'`); } + if (generatorOptions.tsIncludeDescriptions === true) { + optionStringPresets.push(`{ + preset: TS_DESCRIPTION_PRESET, +}`); + } + if (generatorOptions.tsMarshalling === true || generatorOptions.tsIncludeExampleFunction === true) { let commonOptions: any = {}; @@ -22,52 +29,55 @@ export function getTypeScriptGeneratorCode( commonOptions.example = true; } - optionStringPresets.push(` { - preset: TS_COMMON_PRESET, - options: ${JSON.stringify(commonOptions)} - }`); + optionStringPresets.push(`{ + preset: TS_COMMON_PRESET, + options: ${JSON.stringify(commonOptions)} +}`); } if (generatorOptions.tsEnumType) { - optionString.push(` enumType: '${generatorOptions.tsEnumType}'`); + optionString.push(`enumType: '${generatorOptions.tsEnumType}'`); } if (generatorOptions.tsIncludeDescriptions === true) { - optionStringPresets.push(` { - preset: TS_DESCRIPTION_PRESET, - }`); + optionStringPresets.push(`{ + preset: TS_DESCRIPTION_PRESET, + }`); } if (generatorOptions.tsIncludeJsonBinPack === true) { - optionStringPresets.push(` TS_JSONBINPACK_PRESET`); + optionStringPresets.push(`TS_JSONBINPACK_PRESET`); } if (generatorOptions.tsModuleSystem) { - optionString.push(` moduleSystem: '${generatorOptions.tsModuleSystem}'`); + optionString.push(`moduleSystem: '${generatorOptions.tsModuleSystem}'`); } - const presetOptions = - optionStringPresets.length > 0 - ? `${optionString.length > 0 ? ',' : ''} - presets: [ -${optionStringPresets.join(', \n')} - ]` - : ''; - let fullOptions = ''; - if (optionStringPresets.length > 0 || optionString.length > 0) { - fullOptions = `{ - ${optionString.join(', \n')}${presetOptions} -}`; + if(generatorOptions.showTypeMappingExample === true) { + optionString.push(`typeMapping: { + Integer: ({ dependencyManager, constrainedModel, options, partOfProperty }) => { + // Add custom dependency for your type if required. + // This support function makes sure that when changing the module system dependencies change accordingly. + dependencyManager.addTypeScriptDependency('{ MyIntegerType }', './MyIntegerType'); + + //Return the type for the integer model + return 'MyIntegerType'; + } +}`); } - const generateInstanceCode = - `const generator = new TypeScriptGenerator(${fullOptions});`.replace( - /^\s*\n/gm, - '' - ); + + const generateInstanceCode = renderGeneratorInstanceCode(optionString, optionStringPresets, 'TypeScriptGenerator'); return `// Use the following code as starting point // To generate the models exactly as displayed in the playground -import { TypeScriptGenerator, TS_COMMON_PRESET, TS_JSONBINPACK_PRESET } from '@asyncapi/modelina'; +import { + TS_COMMON_PRESET, + TS_DESCRIPTION_PRESET, + TypeScriptGenerator, + typeScriptDefaultEnumKeyConstraints, + typeScriptDefaultModelNameConstraints, + typeScriptDefaultPropertyKeyConstraints +} from '@asyncapi/modelina'; ${generateInstanceCode}`; } diff --git a/modelina-website/src/helpers/Utils.ts b/modelina-website/src/helpers/Utils.ts new file mode 100644 index 0000000000..757ff5a0d5 --- /dev/null +++ b/modelina-website/src/helpers/Utils.ts @@ -0,0 +1,49 @@ +export enum IndentationTypes { + TABS = 'tabs', + SPACES = 'spaces' +} + +/** + * Ensures indentations are prepended to content. + * @param {string} content to prepend the indentation. + * @param {number} size the number of indendations to use. 1 by default + * @param {IndentationTypes} type the type of indendations to use. SPACES by default. + * @returns {string} + */ +export function indent( + content = '', + size = 1, + type: IndentationTypes = IndentationTypes.SPACES +): string { + if (size < 1) { + return content; + } + + // if the content includes new lines ensure that they have the added indentation as well. + if (content.includes('\n')) { + const newLineArray = content.split('\n'); + return newLineArray.reduce((accumulator, value) => { + const newValue = + value.trim() === '' + ? value + : `${getIndentation(size, type)}${value}`; + return accumulator === '' ? newValue : `${accumulator}\n${newValue}`; + }, ''); + } + return `${getIndentation(size, type)}${content}`; +} + +/** + * Get the indendation string based on how many and which type of indentation are requested. + * @private + * @param {number} size the number of indendations to use + * @param {IndentationTypes} type the type of indendations to use. SPACES by default. + * @returns {string} + */ +function getIndentation( + size = 0, + type: IndentationTypes = IndentationTypes.SPACES +): string { + const whitespaceChar = type === IndentationTypes.SPACES ? ' ' : '\t'; + return Array(size).fill(whitespaceChar).join(''); +} \ No newline at end of file diff --git a/modelina-website/src/pages/api/functions/CSharpGenerator.ts b/modelina-website/src/pages/api/functions/CSharpGenerator.ts index 153a83c7c9..021c2ab2c0 100644 --- a/modelina-website/src/pages/api/functions/CSharpGenerator.ts +++ b/modelina-website/src/pages/api/functions/CSharpGenerator.ts @@ -1,7 +1,8 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { CSharpGenerator, CSharpOptions } from '../../../../../'; -import { convertModelsToProps } from './Helpers'; +import { CSharpGenerator, CSharpOptions, csharpDefaultEnumKeyConstraints, csharpDefaultModelNameConstraints, csharpDefaultPropertyKeyConstraints } from '../../../../../'; +import { applyGeneralOptions, convertModelsToProps } from './Helpers'; import { ModelinaCSharpOptions, ModelProps } from '../../../types'; +import { DeepPartial } from '../../../../../lib/types/utils'; import { CSHARP_COMMON_PRESET, CSHARP_JSON_SERIALIZER_PRESET, CSHARP_NEWTONSOFT_SERIALIZER_PRESET } from '../../../../../'; /** @@ -11,17 +12,21 @@ export async function getCSharpModels( input: any, generatorOptions: ModelinaCSharpOptions ): Promise { - const options: Partial = { + const options: DeepPartial = { presets: [] }; - options.presets = []; + + applyGeneralOptions(generatorOptions, options, csharpDefaultEnumKeyConstraints, csharpDefaultPropertyKeyConstraints, csharpDefaultModelNameConstraints); if (generatorOptions.csharpArrayType) { - options.collectionType = generatorOptions.csharpArrayType as any; + options.collectionType = generatorOptions.csharpArrayType; + } + + if (generatorOptions.csharpAutoImplemented) { options.autoImplementedProperties = generatorOptions.csharpAutoImplemented; } if (generatorOptions.csharpOverwriteHashcode) { - options.presets.push({ + options.presets?.push({ preset: CSHARP_COMMON_PRESET, options: { equal: false, @@ -30,10 +35,19 @@ export async function getCSharpModels( }) } if (generatorOptions.csharpIncludeJson) { - options.presets.push(CSHARP_JSON_SERIALIZER_PRESET) + options.presets?.push(CSHARP_JSON_SERIALIZER_PRESET) } if (generatorOptions.csharpIncludeNewtonsoft) { - options.presets.push(CSHARP_NEWTONSOFT_SERIALIZER_PRESET) + options.presets?.push(CSHARP_NEWTONSOFT_SERIALIZER_PRESET) + } + + if (generatorOptions.showTypeMappingExample) { + options.typeMapping = { + Integer: ({ dependencyManager }) => { + dependencyManager.addDependency('using My.Namespace;'); + return 'MyIntegerType'; + } + } } try { diff --git a/modelina-website/src/pages/api/functions/CplusplusGenerator.ts b/modelina-website/src/pages/api/functions/CplusplusGenerator.ts index a9a53318e5..15df0b1d41 100644 --- a/modelina-website/src/pages/api/functions/CplusplusGenerator.ts +++ b/modelina-website/src/pages/api/functions/CplusplusGenerator.ts @@ -1,7 +1,8 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { CplusplusGenerator, CplusplusOptions } from '../../../../../'; -import { convertModelsToProps } from './Helpers'; +import { CplusplusGenerator, CplusplusOptions, cplusplusDefaultEnumKeyConstraints, cplusplusDefaultModelNameConstraints, cplusplusDefaultPropertyKeyConstraints } from '../../../../../'; +import { applyGeneralOptions, convertModelsToProps } from './Helpers'; import { ModelinaCplusplusOptions, ModelProps } from '../../../types'; +import { DeepPartial } from '../../../../../lib/types/utils'; /** * This is the server side part of the C++ generator, that takes input and generator parameters and generate the models. @@ -10,9 +11,19 @@ export async function getCplusplusModels( input: any, generatorOptions: ModelinaCplusplusOptions ): Promise { - const options: Partial = { + const options: DeepPartial = { presets: [] }; + applyGeneralOptions(generatorOptions, options, cplusplusDefaultEnumKeyConstraints, cplusplusDefaultPropertyKeyConstraints, cplusplusDefaultModelNameConstraints); + + if (generatorOptions.showTypeMappingExample) { + options.typeMapping = { + Integer: ({ dependencyManager }) => { + dependencyManager.addDependency('#include '); + return 'MyIntegerType'; + } + } + } try { const generator = new CplusplusGenerator(options); diff --git a/modelina-website/src/pages/api/functions/DartGenerator.ts b/modelina-website/src/pages/api/functions/DartGenerator.ts index 6766186bc9..a69651034d 100644 --- a/modelina-website/src/pages/api/functions/DartGenerator.ts +++ b/modelina-website/src/pages/api/functions/DartGenerator.ts @@ -1,7 +1,8 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { DartGenerator, DartOptions } from '../../../../..'; -import { convertModelsToProps } from './Helpers'; +import { DartGenerator, DartOptions, dartDefaultEnumKeyConstraints, dartDefaultModelNameConstraints, dartDefaultPropertyKeyConstraints } from '../../../../..'; +import { applyGeneralOptions, convertModelsToProps } from './Helpers'; import { ModelinaDartOptions, ModelProps } from '../../../types'; +import { DeepPartial } from '../../../../../lib/types/utils'; /** * This is the server side part of the Dart generator, that takes input and generator parameters and generate the models. @@ -10,9 +11,19 @@ export async function getDartModels( input: any, generatorOptions: ModelinaDartOptions ): Promise { - const options: Partial = { + const options: DeepPartial = { presets: [] }; + applyGeneralOptions(generatorOptions, options, dartDefaultEnumKeyConstraints, dartDefaultPropertyKeyConstraints, dartDefaultModelNameConstraints); + + if (generatorOptions.showTypeMappingExample) { + options.typeMapping = { + Integer: ({ dependencyManager }) => { + dependencyManager.addDependency(`import 'package:lib/lib.dart' as lib;`); + return 'lib.MyIntegerType'; + } + } + } try { const generator = new DartGenerator(options); diff --git a/modelina-website/src/pages/api/functions/GoGenerator.ts b/modelina-website/src/pages/api/functions/GoGenerator.ts index 0aa5abca16..9746197b34 100644 --- a/modelina-website/src/pages/api/functions/GoGenerator.ts +++ b/modelina-website/src/pages/api/functions/GoGenerator.ts @@ -1,7 +1,8 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { GoGenerator, GoOptions } from '../../../../../'; -import { convertModelsToProps } from './Helpers'; +import { GoGenerator, GoOptions, goDefaultEnumKeyConstraints, goDefaultModelNameConstraints, goDefaultPropertyKeyConstraints } from '../../../../../'; +import { applyGeneralOptions, convertModelsToProps } from './Helpers'; import { ModelinaGoOptions, ModelProps } from '../../../types'; +import { DeepPartial } from '../../../../../lib/types/utils'; /** * This is the server side part of the Go generator, that takes input and generator parameters and generate the models. @@ -10,9 +11,19 @@ export async function getGoModels( input: any, generatorOptions: ModelinaGoOptions ): Promise { - const options: Partial = { + const options: DeepPartial = { presets: [] }; + applyGeneralOptions(generatorOptions, options, goDefaultEnumKeyConstraints, goDefaultPropertyKeyConstraints, goDefaultModelNameConstraints); + + if (generatorOptions.showTypeMappingExample) { + options.typeMapping = { + Integer: ({ dependencyManager }) => { + dependencyManager.addDependency('parent "family/father"'); + return 'int64'; + } + } + } try { const generator = new GoGenerator(options); diff --git a/modelina-website/src/pages/api/functions/Helpers.ts b/modelina-website/src/pages/api/functions/Helpers.ts index fd0017a179..6251c5e9f5 100644 --- a/modelina-website/src/pages/api/functions/Helpers.ts +++ b/modelina-website/src/pages/api/functions/Helpers.ts @@ -1,5 +1,5 @@ -import { OutputModel } from '../../../../../'; -import { ModelProps } from '../../../types'; +import { OutputModel, FormatHelpers, IndentationTypes } from '../../../../../'; +import { ModelinaGeneralOptions, ModelProps } from "@/types"; /** * Converts the output model of Modelina to props @@ -14,3 +14,126 @@ export function convertModelsToProps( }; }); } + +/** + * Function that applies the general options to the generator options, right before the models are generated. + * + * Works for all generators. + */ +export function applyGeneralOptions( + generatorOptions: ModelinaGeneralOptions, + options: any, + enumKeyConstraints: any, + propertyKeyConstraints: any, + modelNameConstraints: any) { + options.constraints = {}; + if (generatorOptions.enumKeyNamingFormat !== 'default') { + switch (generatorOptions.enumKeyNamingFormat) { + case 'camel_case': + options.constraints.enumKey = enumKeyConstraints({ + NAMING_FORMATTER: FormatHelpers.toCamelCase + }); + break; + case 'constant_case': + options.constraints.enumKey = enumKeyConstraints({ + NAMING_FORMATTER: FormatHelpers.toConstantCase + }); + break; + case 'param_case': + options.constraints.enumKey = enumKeyConstraints({ + NAMING_FORMATTER: FormatHelpers.toParamCase + }); + break; + case 'pascal_case': + options.constraints.enumKey = enumKeyConstraints({ + NAMING_FORMATTER: FormatHelpers.toPascalCase + }); + break; + case 'snake_case': + options.constraints.enumKey = enumKeyConstraints({ + NAMING_FORMATTER: FormatHelpers.toSnakeCase + }); + break; + default: + break; + } + } + if (generatorOptions.propertyNamingFormat !== 'default') { + switch (generatorOptions.propertyNamingFormat) { + case 'camel_case': + options.constraints.propertyKey = propertyKeyConstraints({ + NAMING_FORMATTER: FormatHelpers.toCamelCase + }); + break; + case 'constant_case': + options.constraints.propertyKey = propertyKeyConstraints({ + NAMING_FORMATTER: FormatHelpers.toConstantCase + }); + break; + case 'param_case': + options.constraints.propertyKey = propertyKeyConstraints({ + NAMING_FORMATTER: FormatHelpers.toParamCase + }); + break; + case 'pascal_case': + options.constraints.propertyKey = propertyKeyConstraints({ + NAMING_FORMATTER: FormatHelpers.toPascalCase + }); + break; + case 'snake_case': + options.constraints.propertyKey = propertyKeyConstraints({ + NAMING_FORMATTER: FormatHelpers.toSnakeCase + }); + break; + default: + break; + } + } + if (generatorOptions.modelNamingFormat !== 'default') { + switch (generatorOptions.modelNamingFormat) { + case 'camel_case': + options.constraints.modelName = modelNameConstraints({ + NAMING_FORMATTER: FormatHelpers.toCamelCase + }); + break; + case 'constant_case': + options.constraints.modelName = modelNameConstraints({ + NAMING_FORMATTER: FormatHelpers.toConstantCase + }); + break; + case 'param_case': + options.constraints.modelName = modelNameConstraints({ + NAMING_FORMATTER: FormatHelpers.toParamCase + }); + break; + case 'pascal_case': + options.constraints.modelName = modelNameConstraints({ + NAMING_FORMATTER: FormatHelpers.toPascalCase + }); + break; + case 'snake_case': + options.constraints.modelName = modelNameConstraints({ + NAMING_FORMATTER: FormatHelpers.toSnakeCase + }); + break; + default: + break; + } + } + if (generatorOptions.indentationType) { + switch (generatorOptions.indentationType) { + case 'spaces': + options.indentation = { + type: IndentationTypes.SPACES + } + break; + case 'tabs': + options.indentation = { + type: IndentationTypes.TABS + } + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/modelina-website/src/pages/api/functions/JavaGenerator.ts b/modelina-website/src/pages/api/functions/JavaGenerator.ts index 0f96af4271..99bf3963fc 100644 --- a/modelina-website/src/pages/api/functions/JavaGenerator.ts +++ b/modelina-website/src/pages/api/functions/JavaGenerator.ts @@ -1,7 +1,8 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { JavaGenerator, JavaOptions } from '../../../../../'; -import { convertModelsToProps } from './Helpers'; +import { JavaGenerator, JavaOptions, javaDefaultEnumKeyConstraints, javaDefaultModelNameConstraints, javaDefaultPropertyKeyConstraints } from '../../../../../'; +import { applyGeneralOptions, convertModelsToProps } from './Helpers'; import { ModelinaJavaOptions, ModelProps } from '../../../types'; +import { DeepPartial } from '../../../../../lib/types/utils'; /** * This is the server side part of the Java generator, that takes input and generator parameters and generate the models. @@ -10,9 +11,19 @@ export async function getJavaModels( input: any, generatorOptions: ModelinaJavaOptions ): Promise { - const options: Partial = { + const options: DeepPartial = { presets: [] }; + applyGeneralOptions(generatorOptions, options, javaDefaultEnumKeyConstraints, javaDefaultPropertyKeyConstraints, javaDefaultModelNameConstraints); + + if (generatorOptions.showTypeMappingExample) { + options.typeMapping = { + Integer: ({ dependencyManager }) => { + dependencyManager.addDependency('import java.util.ArrayList;'); + return 'long'; + } + } + } try { const generator = new JavaGenerator(options); diff --git a/modelina-website/src/pages/api/functions/JavaScriptGenerator.ts b/modelina-website/src/pages/api/functions/JavaScriptGenerator.ts index 3e76fe255c..d2ecdd510c 100644 --- a/modelina-website/src/pages/api/functions/JavaScriptGenerator.ts +++ b/modelina-website/src/pages/api/functions/JavaScriptGenerator.ts @@ -1,7 +1,8 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { JavaScriptGenerator, JavaScriptOptions } from '../../../../../'; -import { convertModelsToProps } from './Helpers'; +import { JavaScriptGenerator, JavaScriptOptions, javaScriptDefaultEnumKeyConstraints, javaScriptDefaultModelNameConstraints, javaScriptDefaultPropertyKeyConstraints } from '../../../../../'; +import { applyGeneralOptions, convertModelsToProps } from './Helpers'; import { ModelinaJavaScriptOptions, ModelProps } from '../../../types'; +import { DeepPartial } from '../../../../../lib/types/utils'; /** * This is the server side part of the JavaScript generator, that takes input and generator parameters and generate the models. @@ -10,9 +11,10 @@ export async function getJavaScriptModels( input: any, generatorOptions: ModelinaJavaScriptOptions ): Promise { - const options: Partial = { + const options: DeepPartial = { presets: [] }; + applyGeneralOptions(generatorOptions, options, javaScriptDefaultEnumKeyConstraints, javaScriptDefaultPropertyKeyConstraints, javaScriptDefaultModelNameConstraints); try { const generator = new JavaScriptGenerator(options); diff --git a/modelina-website/src/pages/api/functions/KotlinGenerator.ts b/modelina-website/src/pages/api/functions/KotlinGenerator.ts index 9eeb32afac..0f73a785ce 100644 --- a/modelina-website/src/pages/api/functions/KotlinGenerator.ts +++ b/modelina-website/src/pages/api/functions/KotlinGenerator.ts @@ -1,7 +1,8 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { KotlinGenerator, KotlinOptions } from '../../../../../'; -import { convertModelsToProps } from './Helpers'; +import { KotlinGenerator, KotlinOptions, kotlinDefaultEnumKeyConstraints, kotlinDefaultModelNameConstraints, kotlinDefaultPropertyKeyConstraints } from '../../../../../'; +import { applyGeneralOptions, convertModelsToProps } from './Helpers'; import { ModelinaKotlinOptions, ModelProps } from '../../../types'; +import { DeepPartial } from '../../../../../lib/types/utils'; /** * This is the server side part of the Kotlin generator, that takes input and generator parameters and generate the models. @@ -10,9 +11,19 @@ export async function getKotlinModels( input: any, generatorOptions: ModelinaKotlinOptions ): Promise { - const options: Partial = { + const options: DeepPartial = { presets: [] }; + applyGeneralOptions(generatorOptions, options, kotlinDefaultEnumKeyConstraints, kotlinDefaultPropertyKeyConstraints, kotlinDefaultModelNameConstraints); + + if (generatorOptions.showTypeMappingExample) { + options.typeMapping = { + Integer: ({ dependencyManager }) => { + dependencyManager.addDependency('import kotlinx.datetime.*'); + return 'LocalDate'; + } + } + } try { const generator = new KotlinGenerator(options); diff --git a/modelina-website/src/pages/api/functions/PhpGenerator.ts b/modelina-website/src/pages/api/functions/PhpGenerator.ts index 6ea758ca46..1f2ccaa90c 100644 --- a/modelina-website/src/pages/api/functions/PhpGenerator.ts +++ b/modelina-website/src/pages/api/functions/PhpGenerator.ts @@ -3,10 +3,14 @@ import { InputProcessor, PHP_DESCRIPTION_PRESET, PhpGenerator, - PhpOptions + PhpOptions, + phpDefaultEnumKeyConstraints, + phpDefaultModelNameConstraints, + phpDefaultPropertyKeyConstraints } from '../../../../../'; -import { convertModelsToProps } from './Helpers'; +import { applyGeneralOptions, convertModelsToProps } from './Helpers'; import { ModelinaPhpOptions, ModelProps } from '../../../types'; +import { DeepPartial } from '../../../../../lib/types/utils'; /** * This is the server side part of the PHP generator, that takes input and generator parameters and generate the models. @@ -15,15 +19,27 @@ export async function getPhpModels( input: any, generatorOptions: ModelinaPhpOptions ): Promise { - const options: Partial = { + const options: DeepPartial = { presets: [] }; + + applyGeneralOptions(generatorOptions, options, phpDefaultEnumKeyConstraints, phpDefaultPropertyKeyConstraints, phpDefaultModelNameConstraints); + if (generatorOptions.phpIncludeDescriptions === true) { options.presets?.push({ preset: PHP_DESCRIPTION_PRESET, options: {} }); } + + if (generatorOptions.showTypeMappingExample === true) { + options.typeMapping = { + Integer: ({ dependencyManager }) => { + dependencyManager.addDependency('use ArrayObject'); + return 'ArrayObject'; + } + } + } try { const processedInput = await InputProcessor.processor.process(input); const generator = new PhpGenerator(options); diff --git a/modelina-website/src/pages/api/functions/PythonGenerator.ts b/modelina-website/src/pages/api/functions/PythonGenerator.ts index 3a11aeb40a..319f50f73e 100644 --- a/modelina-website/src/pages/api/functions/PythonGenerator.ts +++ b/modelina-website/src/pages/api/functions/PythonGenerator.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { PythonGenerator, PythonOptions } from '../../../../../'; -import { convertModelsToProps } from './Helpers'; +import { PythonGenerator, PythonOptions, pythonDefaultEnumKeyConstraints, pythonDefaultModelNameConstraints, pythonDefaultPropertyKeyConstraints } from '../../../../../'; +import { applyGeneralOptions, convertModelsToProps } from './Helpers'; import { ModelinaPythonOptions, ModelProps } from '../../../types'; /** @@ -13,6 +13,7 @@ export async function getPythonModels( const options: Partial = { presets: [] }; + applyGeneralOptions(generatorOptions, options, pythonDefaultEnumKeyConstraints, pythonDefaultPropertyKeyConstraints, pythonDefaultModelNameConstraints); try { const generator = new PythonGenerator(options); diff --git a/modelina-website/src/pages/api/functions/RustGenerator.ts b/modelina-website/src/pages/api/functions/RustGenerator.ts index c32f638b76..0a20b17180 100644 --- a/modelina-website/src/pages/api/functions/RustGenerator.ts +++ b/modelina-website/src/pages/api/functions/RustGenerator.ts @@ -1,7 +1,8 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import { RustGenerator, RustOptions } from '../../../../../'; -import { convertModelsToProps } from './Helpers'; +import { RustGenerator, RustOptions, rustDefaultEnumKeyConstraints, rustDefaultModelNameConstraints, rustDefaultPropertyKeyConstraints } from '../../../../../'; +import { applyGeneralOptions, convertModelsToProps } from './Helpers'; import { ModelinaRustOptions, ModelProps } from '../../../types'; +import { DeepPartial } from '../../../../../lib/types/utils'; /** * This is the server side part of the Rust generator, that takes input and generator parameters and generate the models. @@ -10,9 +11,19 @@ export async function getRustModels( input: any, generatorOptions: ModelinaRustOptions ): Promise { - const options: Partial = { + const options: DeepPartial = { presets: [] }; + applyGeneralOptions(generatorOptions, options, rustDefaultEnumKeyConstraints, rustDefaultPropertyKeyConstraints, rustDefaultModelNameConstraints); + + if (generatorOptions.showTypeMappingExample) { + options.typeMapping = { + Integer: ({ dependencyManager }) => { + dependencyManager.addDependency('mod my;'); + return 'my::IntegerType'; + } + } + } try { const generator = new RustGenerator(options); @@ -23,4 +34,4 @@ export async function getRustModels( console.error(e); return e.message; } -} +} \ No newline at end of file diff --git a/modelina-website/src/pages/api/functions/TypeScriptGenerator.ts b/modelina-website/src/pages/api/functions/TypeScriptGenerator.ts index 202f9cee15..79251726e2 100644 --- a/modelina-website/src/pages/api/functions/TypeScriptGenerator.ts +++ b/modelina-website/src/pages/api/functions/TypeScriptGenerator.ts @@ -5,10 +5,14 @@ import { TS_DESCRIPTION_PRESET, TS_JSONBINPACK_PRESET, TypeScriptGenerator, - TypeScriptOptions + TypeScriptOptions, + typeScriptDefaultEnumKeyConstraints, + typeScriptDefaultModelNameConstraints, + typeScriptDefaultPropertyKeyConstraints } from '../../../../../'; -import { convertModelsToProps } from './Helpers'; +import { applyGeneralOptions, convertModelsToProps } from './Helpers'; import { ModelinaTypeScriptOptions, ModelProps } from '../../../types'; +import { DeepPartial } from '../../../../../lib/types/utils'; /** * This is the server side part of the TypeScript generator, that takes input and generator parameters and generate the models. @@ -17,9 +21,11 @@ export async function getTypeScriptModels( input: any, generatorOptions: ModelinaTypeScriptOptions ): Promise { - const options: Partial = { + const options: DeepPartial = { presets: [] }; + applyGeneralOptions(generatorOptions, options, typeScriptDefaultEnumKeyConstraints, typeScriptDefaultPropertyKeyConstraints, typeScriptDefaultModelNameConstraints); + if (generatorOptions.tsModelType) { options.modelType = generatorOptions.tsModelType as any; } @@ -60,6 +66,15 @@ export async function getTypeScriptModels( options.enumType = generatorOptions.tsEnumType as any; } + if (generatorOptions.showTypeMappingExample) { + options.typeMapping = { + Integer: ({ dependencyManager }) => { + dependencyManager.addTypeScriptDependency('{ MyIntegerType }', './MyIntegerType'); + return 'MyIntegerType'; + } + } + } + try { const processedInput = await InputProcessor.processor.process(input); const generator = new TypeScriptGenerator(options); diff --git a/modelina-website/src/pages/api/generate.ts b/modelina-website/src/pages/api/generate.ts index 8ed4cd88f4..0a257539e8 100644 --- a/modelina-website/src/pages/api/generate.ts +++ b/modelina-website/src/pages/api/generate.ts @@ -54,6 +54,7 @@ export async function generateNewCode(message: GenerateMessage): Promise Date: Wed, 31 May 2023 10:28:09 +0200 Subject: [PATCH 24/79] chore(website): fix relative reference in description of examples (#1348) --- modelina-website/scripts/build-examples.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modelina-website/scripts/build-examples.js b/modelina-website/scripts/build-examples.js index 123e7d67c5..e3fc4cb289 100644 --- a/modelina-website/scripts/build-examples.js +++ b/modelina-website/scripts/build-examples.js @@ -59,6 +59,8 @@ async function getDescription(exampleDirPath){ let description = await readFile(path.resolve(exampleDirPath, './README.md'), "utf-8"); const runExampleStart = description.search('## How to run this example'); description = description.slice(0, runExampleStart); + // Replace all local references to examples with queries + description = description.replace(/\(..\/(.*?)(\/)?\)/g, '(?selectedExample=$1)'); return description; } @@ -97,8 +99,9 @@ async function start() { await writeFile(outputFile, JSON.stringify(templateConfig, null, 4)); let mainReadme = await readFile(path.resolve(__dirname, '../../examples/README.md'), 'utf-8'); + // Replace all local references to examples with queries - mainReadme = mainReadme.replace(/\(.\/(.*?)\)/g, '(?selectedExample=$1)'); + mainReadme = mainReadme.replace(/\(.\/(.*?)(\/)?\)/g, '(?selectedExample=$1)'); mainReadme = mainReadme.replace('', ''); mainReadme = mainReadme.replace('', ''); mainReadme = mainReadme.replace('', ''); From 3e9a52799c76d82c56ea51d7280205ece9a53d2a Mon Sep 17 00:00:00 2001 From: Jonas Lagoni Date: Wed, 31 May 2023 10:30:44 +0200 Subject: [PATCH 25/79] chore(website): fix react prop warning (#1349) --- modelina-website/src/components/CodeBlock.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modelina-website/src/components/CodeBlock.tsx b/modelina-website/src/components/CodeBlock.tsx index 8e55b8729e..c1b717b739 100644 --- a/modelina-website/src/components/CodeBlock.tsx +++ b/modelina-website/src/components/CodeBlock.tsx @@ -222,7 +222,7 @@ export default function CodeBlock({ style={theme} showLineNumbers={showLineNumbers} startingLineNumber={startingLineNumber} - lineNumberContainerProps={{ + linenumbercontainerprops={{ className: 'pl-2 float-left left-0 sticky bg-code-editor-dark', style: {} }} From 7567927d9d2bf7e707b2adf6ee3bda7f730a80bb Mon Sep 17 00:00:00 2001 From: Jonas Lagoni Date: Wed, 31 May 2023 10:31:08 +0200 Subject: [PATCH 26/79] chore(website): change edit link to descriptions (#1350) --- modelina-website/src/components/examples/Examples.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modelina-website/src/components/examples/Examples.tsx b/modelina-website/src/components/examples/Examples.tsx index 20f4b5c631..b5e4759188 100644 --- a/modelina-website/src/components/examples/Examples.tsx +++ b/modelina-website/src/components/examples/Examples.tsx @@ -169,7 +169,7 @@ class Examples extends React.Component< />
{example.description} - Edit Description + Edit Description
@@ -208,7 +208,7 @@ class Examples extends React.Component<
From 4aca998647c4b1325e6fd4fd28009726e8b408b1 Mon Sep 17 00:00:00 2001 From: Rohith Boppey <73538974+RohithBoppey@users.noreply.github.com> Date: Wed, 31 May 2023 14:39:30 +0530 Subject: [PATCH 27/79] chore(website): added overwriting equal options in CSharp Language (#1339) --- .../src/components/playground/Playground.tsx | 5 ++++ .../options/CSharpGeneratorOptions.tsx | 23 ++++++++++++++++++- .../helpers/GeneratorCode/CSharpGenerator.ts | 10 ++++++++ .../pages/api/functions/CSharpGenerator.ts | 10 ++++++++ modelina-website/src/types/index.ts | 2 ++ 5 files changed, 49 insertions(+), 1 deletion(-) diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index 23bafcdea5..27d1a304fa 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -90,6 +90,7 @@ class Playground extends React.Component< phpIncludeDescriptions: false, csharpOverwriteHashcode: false, csharpIncludeJson: false, + csharpOverwriteEqual: false, csharpIncludeNewtonsoft: false, }; hasLoadedQuery: boolean = false; @@ -261,6 +262,10 @@ class Playground extends React.Component< this.config.csharpIncludeJson = query.csharpIncludeJson === 'true'; } + if (query.csharpOverwriteEqual !== undefined) { + this.config.csharpOverwriteEqual = + query.csharpOverwriteEqual === 'true'; + } if (query.csharpIncludeNewtonsoft !== undefined) { this.config.csharpIncludeNewtonsoft = query.csharpIncludeNewtonsoft === 'true'; diff --git a/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx b/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx index 0b8ea46d03..19718f80c0 100644 --- a/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx @@ -23,6 +23,7 @@ class CSharpGeneratorOptions extends React.Component< this.onChangeAutoImplementProperties = this.onChangeAutoImplementProperties.bind(this); this.onChangeOverwriteHashCodeSupport = this.onChangeOverwriteHashCodeSupport.bind(this); this.onChangeIncludeJson = this.onChangeIncludeJson.bind(this); + this.onChangeOverwriteEqualSupport = this.onChangeOverwriteEqualSupport.bind(this); this.onChangeIncludeNewtonsoft = this.onChangeIncludeNewtonsoft.bind(this); } @@ -50,6 +51,12 @@ class CSharpGeneratorOptions extends React.Component< } } + onChangeOverwriteEqualSupport(event: any) { + if (this.props.setNewConfig) { + this.props.setNewConfig('csharpOverwriteEqual', event.target.checked); + } + } + onChangeIncludeNewtonsoft(event: any) { if (this.props.setNewConfig) { this.props.setNewConfig('csharpIncludeNewtonsoft', event.target.checked); @@ -95,7 +102,7 @@ class CSharpGeneratorOptions extends React.Component<
  • +
  • + +
  • + Deploys by Netlify
    From ed471262e97a56985c06a545dd0c2fdf69f1d1f8 Mon Sep 17 00:00:00 2001 From: Ashish Padhy <100484401+Shurtu-gal@users.noreply.github.com> Date: Mon, 5 Jun 2023 18:57:59 +0530 Subject: [PATCH 40/79] chore(website): add nullable option to C# (#1377) --- .../src/components/playground/Playground.tsx | 4 ++++ .../options/CSharpGeneratorOptions.tsx | 21 +++++++++++++++++++ .../helpers/GeneratorCode/CSharpGenerator.ts | 4 ++++ .../pages/api/functions/CSharpGenerator.ts | 4 ++++ modelina-website/src/types/index.ts | 2 ++ 5 files changed, 35 insertions(+) diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index e00e8eea43..0dc804d37d 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -92,6 +92,7 @@ class Playground extends React.Component< csharpOverwriteEqual: false, csharpIncludeNewtonsoft: false, csharpNamespace: 'asyncapi.models', + csharpNullable: false, phpIncludeDescriptions: false, phpNamespace: 'AsyncAPI/Models', cplusplusNamespace: 'AsyncapiModels', @@ -279,6 +280,9 @@ class Playground extends React.Component< if (query.csharpNamespace !== undefined) { this.config.csharpNamespace = query.csharpNamespace; } + if (query.csharpNullable !== undefined) { + this.config.csharpNullable = query.csharpNullable === 'true'; + } if(query.cplusplusNamespace !== undefined) { this.config.cplusplusNamespace = query.cplusplusNamespace; } diff --git a/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx b/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx index 5871ff5b78..0619151b2a 100644 --- a/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/CSharpGeneratorOptions.tsx @@ -28,6 +28,7 @@ class CSharpGeneratorOptions extends React.Component< this.onChangeIncludeJson = this.onChangeIncludeJson.bind(this); this.onChangeOverwriteEqualSupport = this.onChangeOverwriteEqualSupport.bind(this); this.onChangeIncludeNewtonsoft = this.onChangeIncludeNewtonsoft.bind(this); + this.onChangeNullable = this.onChangeNullable.bind(this); this.onChangeNamespace = this.onChangeNamespace.bind(this); this.debouncedSetNewConfig = this.debouncedSetNewConfig.bind(this); } @@ -68,6 +69,12 @@ class CSharpGeneratorOptions extends React.Component< } } + onChangeNullable(event: any) { + if (this.props.setNewConfig) { + this.props.setNewConfig('csharpNullable', event.target.checked); + } + } + componentDidMount() { this.setState({ ...this.state, namespace: this.context?.csharpNamespace }); } @@ -187,6 +194,20 @@ class CSharpGeneratorOptions extends React.Component< /> +
  • + +
  • ); } diff --git a/modelina-website/src/helpers/GeneratorCode/CSharpGenerator.ts b/modelina-website/src/helpers/GeneratorCode/CSharpGenerator.ts index a41202b166..ddfce658da 100644 --- a/modelina-website/src/helpers/GeneratorCode/CSharpGenerator.ts +++ b/modelina-website/src/helpers/GeneratorCode/CSharpGenerator.ts @@ -22,6 +22,10 @@ export function getCSharpGeneratorCode( optionString.push(`namespace: '${generatorOptions.csharpNamespace}'`); } + if (generatorOptions.csharpNullable) { + optionString.push(`nullable: ${generatorOptions.csharpNullable}`); + } + if(generatorOptions.showTypeMappingExample === true) { optionString.push(`typeMapping: { Integer: ({ dependencyManager, constrainedModel, options, partOfProperty }) => { diff --git a/modelina-website/src/pages/api/functions/CSharpGenerator.ts b/modelina-website/src/pages/api/functions/CSharpGenerator.ts index 3ecba3b1f6..f96427eed0 100644 --- a/modelina-website/src/pages/api/functions/CSharpGenerator.ts +++ b/modelina-website/src/pages/api/functions/CSharpGenerator.ts @@ -51,6 +51,10 @@ export async function getCSharpModels( options.presets?.push(CSHARP_NEWTONSOFT_SERIALIZER_PRESET) } + if (generatorOptions.csharpNullable) { + options.handleNullable = generatorOptions.csharpNullable; + } + if (generatorOptions.showTypeMappingExample) { options.typeMapping = { Integer: ({ dependencyManager }) => { diff --git a/modelina-website/src/types/index.ts b/modelina-website/src/types/index.ts index 11496ee4ba..67c46180d1 100644 --- a/modelina-website/src/types/index.ts +++ b/modelina-website/src/types/index.ts @@ -37,6 +37,7 @@ export interface ModelinaCSharpOptions extends ModelinaGeneralOptions { csharpOverwriteEqual: boolean; csharpIncludeNewtonsoft: boolean; csharpNamespace?: string; + csharpNullable: boolean; } export interface ModelinaKotlinOptions extends ModelinaGeneralOptions {} export interface ModelinaRustOptions extends ModelinaGeneralOptions {} @@ -101,6 +102,7 @@ export interface ModelinaCSharpQueryOptions { csharpOverwriteEqual?: string; csharpIncludeNewtonsoft?: string; csharpNamespace?: string; + csharpNullable?: string; } export interface ModelinaKotlinQueryOptions {} export interface ModelinaRustQueryOptions {} From 4f6ab9c8dfb6fb8d190cca31687740f328c325ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20C=C3=B4t=C3=A9?= Date: Mon, 5 Jun 2023 12:28:55 -0400 Subject: [PATCH 41/79] fix: inverted condition for csharp generator handle-nullable (#1378) --- .../__snapshots__/index.spec.ts.snap | 4 ++-- .../csharp/renderers/ClassRenderer.ts | 2 +- .../__snapshots__/CSharpGenerator.spec.ts.snap | 18 +++++++++--------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/csharp-generate-handle-nullable/__snapshots__/index.spec.ts.snap b/examples/csharp-generate-handle-nullable/__snapshots__/index.spec.ts.snap index eb49cb4b64..7b3e7a01da 100644 --- a/examples/csharp-generate-handle-nullable/__snapshots__/index.spec.ts.snap +++ b/examples/csharp-generate-handle-nullable/__snapshots__/index.spec.ts.snap @@ -4,8 +4,8 @@ exports[`Should be able to render a C# class with null warning removed with hand Array [ "public class Root { - public string? Email { get; set; } = null!; - public string Name { get; set; } + public string? Email { get; set; } + public string Name { get; set; } = null!; }", ] `; diff --git a/src/generators/csharp/renderers/ClassRenderer.ts b/src/generators/csharp/renderers/ClassRenderer.ts index 7fad829f6b..79d462752a 100644 --- a/src/generators/csharp/renderers/ClassRenderer.ts +++ b/src/generators/csharp/renderers/ClassRenderer.ts @@ -101,7 +101,7 @@ export const CSHARP_DEFAULT_CLASS_PRESET: CsharpClassPreset = { }, async property({ renderer, property, options }) { let nullablePropertyEnding = ''; - if (options?.handleNullable && !property.required) { + if (options?.handleNullable && property.required) { nullablePropertyEnding = ' = null!'; } diff --git a/test/generators/csharp/__snapshots__/CSharpGenerator.spec.ts.snap b/test/generators/csharp/__snapshots__/CSharpGenerator.spec.ts.snap index bcd5635d49..de78559769 100644 --- a/test/generators/csharp/__snapshots__/CSharpGenerator.spec.ts.snap +++ b/test/generators/csharp/__snapshots__/CSharpGenerator.spec.ts.snap @@ -300,15 +300,15 @@ exports[`CSharpGenerator should render models and their dependencies 2`] = ` exports[`CSharpGenerator should render null-forgiving operator if handleNullable is chosen 1`] = ` "public class Address { - private string streetName; - private string city; - private string state; - private double houseNumber; - private bool? marriage = null!; - private dynamic? members = null!; - private dynamic[]? tupleType = null!; - private dynamic[] arrayType; - private Dictionary? additionalProperties = null!; + private string streetName = null!; + private string city = null!; + private string state = null!; + private double houseNumber = null!; + private bool? marriage; + private dynamic? members; + private dynamic[]? tupleType; + private dynamic[] arrayType = null!; + private Dictionary? additionalProperties; public string StreetName { From a8c0d5b5bb4f2b47a8a218846931fc03c87f4cd9 Mon Sep 17 00:00:00 2001 From: asyncapi-bot Date: Mon, 5 Jun 2023 18:53:05 +0200 Subject: [PATCH 42/79] chore(release): v1.8.1 (#1379) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d6df4ab879..c0e455be4a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@asyncapi/modelina", - "version": "1.8.0", + "version": "1.8.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@asyncapi/modelina", - "version": "1.8.0", + "version": "1.8.1", "license": "Apache-2.0", "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.9", diff --git a/package.json b/package.json index 5bf4300acc..6f18afb717 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@asyncapi/modelina", - "version": "1.8.0", + "version": "1.8.1", "description": "Library for generating data models based on inputs such as AsyncAPI, OpenAPI, or JSON Schema documents", "license": "Apache-2.0", "homepage": "https://www.modelina.org", From 1c9e647c5e3b9a3bf4482971456c29e8e65980ca Mon Sep 17 00:00:00 2001 From: Zbigniew Malcherczyk Date: Tue, 6 Jun 2023 10:33:06 +0200 Subject: [PATCH 43/79] test: add runtime testing for PHP (#1370) feat: php generator - Runtime Testing Co-authored-by: Jonas Lagoni --- .github/workflows/runtime-php-testing.yml | 49 +++++++++++++++++++ package.json | 2 + test/runtime/runtime-php.spec.ts | 12 +++++ test/runtime/runtime-php.ts | 20 ++++++++ test/runtime/runtime-php/.gitignore | 4 ++ test/runtime/runtime-php/composer.json | 22 +++++++++ test/runtime/runtime-php/phpunit.xml | 24 +++++++++ test/runtime/runtime-php/src/.gitkeep | 0 .../runtime/runtime-php/tests/AddressTest.php | 16 ++++++ .../runtime-php/tests/NestedObjectTest.php | 16 ++++++ 10 files changed, 165 insertions(+) create mode 100644 .github/workflows/runtime-php-testing.yml create mode 100644 test/runtime/runtime-php.spec.ts create mode 100644 test/runtime/runtime-php.ts create mode 100644 test/runtime/runtime-php/.gitignore create mode 100644 test/runtime/runtime-php/composer.json create mode 100644 test/runtime/runtime-php/phpunit.xml create mode 100644 test/runtime/runtime-php/src/.gitkeep create mode 100644 test/runtime/runtime-php/tests/AddressTest.php create mode 100644 test/runtime/runtime-php/tests/NestedObjectTest.php diff --git a/.github/workflows/runtime-php-testing.yml b/.github/workflows/runtime-php-testing.yml new file mode 100644 index 0000000000..0a90f66d42 --- /dev/null +++ b/.github/workflows/runtime-php-testing.yml @@ -0,0 +1,49 @@ +name: Runtime testing PHP models +on: + push: + pull_request: + types: [opened, reopened, synchronize, ready_for_review] + paths: + - 'src/generators/php/**' + - 'test/runtime/runtime-php/**' + - 'test/runtime/**php**' + +jobs: + runtime-php-test: + name: Runtime testing PHP ${{ matrix.php }} Models + if: "github.event.pull_request.draft == false &&!((github.actor == 'asyncapi-bot' && startsWith(github.event.pull_request.title, 'ci: update global workflows')) || (github.actor == 'asyncapi-bot' && startsWith(github.event.pull_request.title, 'chore(release):')) || (github.actor == 'allcontributors' && startsWith(github.event.pull_request.title, 'docs: add')))" + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: + - 8.1 + - 8.2 + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 14 + + - name: Build library + run: npm install && npm run build:prod + + - name: Setup PHP + uses: shivammathur/setup-php@2.25.2 + with: + php-version: ${{ matrix.php }} + + - name: Generate Models + run: npm run generate:runtime:php + + - name: Install PHP Dependencies + uses: ramsey/composer-install@v2 + with: + working-directory: test/runtime/runtime-php + + - name: Run runtime tests + run: composer test + working-directory: test/runtime/runtime-php diff --git a/package.json b/package.json index 6f18afb717..3a38b1f983 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,8 @@ "generate:runtime:java": "cross-env CI=true ts-node ./test/runtime/runtime-java.ts", "test:runtime:rust": "cross-env CI=true jest ./test/runtime/runtime-rust.spec.ts", "generate:runtime:rust": "cross-env CI=true ts-node ./test/runtime/runtime-rust.ts", + "test:runtime:php": "cross-env CI=true jest ./test/runtime/runtime-php.spec.ts", + "generate:runtime:php": "cross-env CI=true ts-node ./test/runtime/runtime-php.ts", "test:watch": "jest --watch", "docs": "npm run docs:markdown", "docs:markdown": "jsdoc2md lib/cjs/index.js -f lib/cjs/**/*.js > API.md", diff --git a/test/runtime/runtime-php.spec.ts b/test/runtime/runtime-php.spec.ts new file mode 100644 index 0000000000..514416038f --- /dev/null +++ b/test/runtime/runtime-php.spec.ts @@ -0,0 +1,12 @@ +import { execCommand } from '../blackbox/utils/Utils'; +import path from 'path'; + +jest.setTimeout(50000); + +test('PHP runtime testing', async () => { + const compileCommand = `cd ${path.resolve( + __dirname, + './runtime-php' + )} && composer install --no-interaction --quiet && composer test`; + await execCommand(compileCommand); +}); diff --git a/test/runtime/runtime-php.ts b/test/runtime/runtime-php.ts new file mode 100644 index 0000000000..5f70b60872 --- /dev/null +++ b/test/runtime/runtime-php.ts @@ -0,0 +1,20 @@ +import { PHP_DEFAULT_PRESET, PhpFileGenerator } from '../../src'; +import path from 'path'; +import input from './generic-input.json'; + +const generator = new PhpFileGenerator({ + presets: [PHP_DEFAULT_PRESET] +}); + +generator.generateToFiles( + input, + path.resolve( + // eslint-disable-next-line no-undef + __dirname, + './runtime-php/src/' + ), + { + namespace: 'AsyncApi\\Models', + declareStrictTypes: true + } +); diff --git a/test/runtime/runtime-php/.gitignore b/test/runtime/runtime-php/.gitignore new file mode 100644 index 0000000000..97e4b23b66 --- /dev/null +++ b/test/runtime/runtime-php/.gitignore @@ -0,0 +1,4 @@ +src/*.php +vendor/ +.phpunit.result.cache +composer.lock diff --git a/test/runtime/runtime-php/composer.json b/test/runtime/runtime-php/composer.json new file mode 100644 index 0000000000..fd7f098870 --- /dev/null +++ b/test/runtime/runtime-php/composer.json @@ -0,0 +1,22 @@ +{ + "name": "ferror/runtime-php", + "autoload": { + "psr-4": { + "AsyncApi\\Models\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "AsyncApi\\Models\\": "tests/" + } + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10" + }, + "scripts": { + "test": "vendor/bin/phpunit" + } +} diff --git a/test/runtime/runtime-php/phpunit.xml b/test/runtime/runtime-php/phpunit.xml new file mode 100644 index 0000000000..b1178a70b8 --- /dev/null +++ b/test/runtime/runtime-php/phpunit.xml @@ -0,0 +1,24 @@ + + + + + tests + + + + + + src + + + diff --git a/test/runtime/runtime-php/src/.gitkeep b/test/runtime/runtime-php/src/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/runtime/runtime-php/tests/AddressTest.php b/test/runtime/runtime-php/tests/AddressTest.php new file mode 100644 index 0000000000..66c366d4a4 --- /dev/null +++ b/test/runtime/runtime-php/tests/AddressTest.php @@ -0,0 +1,16 @@ +assertInstanceOf(Address::class, $address); + } +} diff --git a/test/runtime/runtime-php/tests/NestedObjectTest.php b/test/runtime/runtime-php/tests/NestedObjectTest.php new file mode 100644 index 0000000000..0da4786e73 --- /dev/null +++ b/test/runtime/runtime-php/tests/NestedObjectTest.php @@ -0,0 +1,16 @@ +assertInstanceOf(NestedObject::class, $address); + } +} From 3fa51d5c9b7f64d23ab4220977f8df9c527c916d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20C=C3=B4t=C3=A9?= Date: Tue, 6 Jun 2023 14:31:22 -0400 Subject: [PATCH 44/79] fix: bug when generating null-forgiving for primitives and enums (#1381) --- .../__snapshots__/index.spec.ts.snap | 3 ++ .../csharp-generate-handle-nullable/index.ts | 19 +++++++++- src/generators/csharp/Constants.ts | 37 +++++++++++++++++++ .../csharp/renderers/ClassRenderer.ts | 8 +++- .../generators/csharp/CSharpGenerator.spec.ts | 21 ++++++++++- .../CSharpGenerator.spec.ts.snap | 16 +++++++- 6 files changed, 99 insertions(+), 5 deletions(-) diff --git a/examples/csharp-generate-handle-nullable/__snapshots__/index.spec.ts.snap b/examples/csharp-generate-handle-nullable/__snapshots__/index.spec.ts.snap index 7b3e7a01da..fbe40d9bd5 100644 --- a/examples/csharp-generate-handle-nullable/__snapshots__/index.spec.ts.snap +++ b/examples/csharp-generate-handle-nullable/__snapshots__/index.spec.ts.snap @@ -6,6 +6,9 @@ Array [ { public string? Email { get; set; } public string Name { get; set; } = null!; + public int Age { get; set; } + public dynamic[]? NullableFoos { get; set; } + public dynamic[] MandatoryFoos { get; set; } = null!; }", ] `; diff --git a/examples/csharp-generate-handle-nullable/index.ts b/examples/csharp-generate-handle-nullable/index.ts index dbab3bf03c..ecaa345125 100644 --- a/examples/csharp-generate-handle-nullable/index.ts +++ b/examples/csharp-generate-handle-nullable/index.ts @@ -8,7 +8,7 @@ const jsonSchemaDraft7 = { $schema: 'http://json-schema.org/draft-07/schema#', type: 'object', additionalProperties: false, - required: ['name'], + required: ['name', 'age', 'mandatoryFoos'], properties: { email: { type: 'string', @@ -16,6 +16,23 @@ const jsonSchemaDraft7 = { }, name: { type: 'string' + }, + age: { + type: 'integer' + }, + nullableFoos: { + type: 'array', + items: { + type: 'object', + name: 'Foo' + } + }, + mandatoryFoos: { + type: 'array', + items: { + type: 'object', + name: 'Foo' + } } } }; diff --git a/src/generators/csharp/Constants.ts b/src/generators/csharp/Constants.ts index 10579f62ac..87298be0a9 100644 --- a/src/generators/csharp/Constants.ts +++ b/src/generators/csharp/Constants.ts @@ -1,4 +1,9 @@ import { checkForReservedKeyword } from '../../helpers'; +import { + ConstrainedObjectPropertyModel, + ConstrainedEnumModel, + ConstrainedReferenceModel +} from '../../models'; export const RESERVED_CSHARP_KEYWORDS = [ 'abstract', @@ -91,3 +96,35 @@ export function isReservedCSharpKeyword( forceLowerCase ); } + +const PRIMITIVES = [ + 'bool', + 'byte', + 'sbyte', + 'char', + 'decimal', + 'double', + 'float', + 'int', + 'uint', + 'long', + 'ulong', + 'short', + 'ushort' +]; +export function isPrimitive(property: ConstrainedObjectPropertyModel): boolean { + return PRIMITIVES.includes(property.property.type); +} + +export function isEnum(property: ConstrainedObjectPropertyModel): boolean { + if ( + property.property && + property.property instanceof ConstrainedReferenceModel && + property.property.ref !== undefined && + property.property.ref instanceof ConstrainedEnumModel + ) { + return true; + } + + return false; +} diff --git a/src/generators/csharp/renderers/ClassRenderer.ts b/src/generators/csharp/renderers/ClassRenderer.ts index 79d462752a..4c81091afa 100644 --- a/src/generators/csharp/renderers/ClassRenderer.ts +++ b/src/generators/csharp/renderers/ClassRenderer.ts @@ -7,6 +7,7 @@ import { import { pascalCase } from 'change-case'; import { CsharpClassPreset } from '../CSharpPreset'; import { CSharpOptions } from '../CSharpGenerator'; +import { isPrimitive, isEnum } from '../Constants'; /** * Renderer for CSharp's `struct` type @@ -101,7 +102,12 @@ export const CSHARP_DEFAULT_CLASS_PRESET: CsharpClassPreset = { }, async property({ renderer, property, options }) { let nullablePropertyEnding = ''; - if (options?.handleNullable && property.required) { + if ( + options?.handleNullable && + property.required && + !isPrimitive(property) && + !isEnum(property) + ) { nullablePropertyEnding = ' = null!'; } diff --git a/test/generators/csharp/CSharpGenerator.spec.ts b/test/generators/csharp/CSharpGenerator.spec.ts index 9714c996ce..6bf12515ae 100644 --- a/test/generators/csharp/CSharpGenerator.spec.ts +++ b/test/generators/csharp/CSharpGenerator.spec.ts @@ -60,6 +60,16 @@ describe('CSharpGenerator', () => { type: 'boolean', description: 'Status if marriage live in given house' }, + house_type: { + type: 'string', + enum: ['apartment', 'house', 'condo'], + description: 'Type of house' + }, + terrace_type: { + type: 'string', + enum: ['wood', 'concrete', 'brick'], + description: 'Type of terrace' + }, members: { oneOf: [{ type: 'string' }, { type: 'number' }, { type: 'boolean' }] }, @@ -69,7 +79,14 @@ describe('CSharpGenerator', () => { }, array_type: { type: 'array', items: { type: 'string' } } }, - required: ['street_name', 'city', 'state', 'house_number', 'array_type'], + required: [ + 'street_name', + 'city', + 'state', + 'house_number', + 'array_type', + 'house_type' + ], additionalProperties: { type: 'string' }, @@ -82,7 +99,7 @@ describe('CSharpGenerator', () => { generator.options.handleNullable = true; const models = await generator.generate(doc); - expect(models).toHaveLength(1); + expect(models).toHaveLength(3); expect(models[0].result).toMatchSnapshot(); expect(models[0].dependencies).toEqual([ 'using System.Collections.Generic;' diff --git a/test/generators/csharp/__snapshots__/CSharpGenerator.spec.ts.snap b/test/generators/csharp/__snapshots__/CSharpGenerator.spec.ts.snap index de78559769..ab60c963de 100644 --- a/test/generators/csharp/__snapshots__/CSharpGenerator.spec.ts.snap +++ b/test/generators/csharp/__snapshots__/CSharpGenerator.spec.ts.snap @@ -303,8 +303,10 @@ exports[`CSharpGenerator should render null-forgiving operator if handleNullable private string streetName = null!; private string city = null!; private string state = null!; - private double houseNumber = null!; + private double houseNumber; private bool? marriage; + private HouseType houseType; + private TerraceType? terraceType; private dynamic? members; private dynamic[]? tupleType; private dynamic[] arrayType = null!; @@ -340,6 +342,18 @@ exports[`CSharpGenerator should render null-forgiving operator if handleNullable set { marriage = value; } } + public HouseType HouseType + { + get { return houseType; } + set { houseType = value; } + } + + public TerraceType? TerraceType + { + get { return terraceType; } + set { terraceType = value; } + } + public dynamic? Members { get { return members; } From 1fd54fc579798a4e80d2d7d67d287342fa8e8cc9 Mon Sep 17 00:00:00 2001 From: asyncapi-bot Date: Tue, 6 Jun 2023 20:54:49 +0200 Subject: [PATCH 45/79] chore(release): v1.8.2 (#1382) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index c0e455be4a..b6df5d8da3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@asyncapi/modelina", - "version": "1.8.1", + "version": "1.8.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@asyncapi/modelina", - "version": "1.8.1", + "version": "1.8.2", "license": "Apache-2.0", "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.9", diff --git a/package.json b/package.json index 3a38b1f983..f16bac09dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@asyncapi/modelina", - "version": "1.8.1", + "version": "1.8.2", "description": "Library for generating data models based on inputs such as AsyncAPI, OpenAPI, or JSON Schema documents", "license": "Apache-2.0", "homepage": "https://www.modelina.org", From a47b4507f50c6565cc4540a2c4df08c4ee723468 Mon Sep 17 00:00:00 2001 From: "Sumant.xD" <65810424+SumantxD@users.noreply.github.com> Date: Wed, 7 Jun 2023 17:48:26 +0530 Subject: [PATCH 46/79] test: add runtime testing for kotlin (#1357) Co-authored-by: Jonas Lagoni --- .github/workflows/runtime-kotlin-testing.yml | 33 ++++ package-lock.json | 22 ++- package.json | 2 + test/runtime/runtime-kotlin.spec.ts | 19 ++ test/runtime/runtime-kotlin.ts | 17 ++ test/runtime/runtime-kotlin/.gitignore | 25 +++ test/runtime/runtime-kotlin/README.md | 8 + test/runtime/runtime-kotlin/build.gradle | 13 ++ .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 55618 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + test/runtime/runtime-kotlin/gradlew | 172 ++++++++++++++++++ test/runtime/runtime-kotlin/gradlew.bat | 84 +++++++++ test/runtime/runtime-kotlin/settings.gradle | 18 ++ .../com/mycompany/app/generic/AddressTest.kt | 45 +++++ 14 files changed, 457 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/runtime-kotlin-testing.yml create mode 100644 test/runtime/runtime-kotlin.spec.ts create mode 100644 test/runtime/runtime-kotlin.ts create mode 100644 test/runtime/runtime-kotlin/.gitignore create mode 100644 test/runtime/runtime-kotlin/README.md create mode 100644 test/runtime/runtime-kotlin/build.gradle create mode 100644 test/runtime/runtime-kotlin/gradle/wrapper/gradle-wrapper.jar create mode 100644 test/runtime/runtime-kotlin/gradle/wrapper/gradle-wrapper.properties create mode 100755 test/runtime/runtime-kotlin/gradlew create mode 100644 test/runtime/runtime-kotlin/gradlew.bat create mode 100644 test/runtime/runtime-kotlin/settings.gradle create mode 100644 test/runtime/runtime-kotlin/src/test/kotlin/com/mycompany/app/generic/AddressTest.kt diff --git a/.github/workflows/runtime-kotlin-testing.yml b/.github/workflows/runtime-kotlin-testing.yml new file mode 100644 index 0000000000..a7dfac7512 --- /dev/null +++ b/.github/workflows/runtime-kotlin-testing.yml @@ -0,0 +1,33 @@ +name: Runtime testing Kotlin models + +on: + push: + pull_request: + types: [opened, reopened, synchronize, ready_for_review] + paths: + - 'src/generators/kotlin/**' + - 'test/runtime/runtime-kotlin/**' + - 'test/runtime/**kotlin**' + +jobs: + test: + name: Runtime testing Kotlin Models + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + - name: Setup Node.js + uses: actions/setup-node@v1 + with: + node-version: 14 + - name: Build library + run: npm install && npm run build:prod + - name: Setup Java + uses: actions/setup-java@v2 + with: + distribution: 'adopt' + java-version: '11' + - name: Generate Kotlin models + run: npm run generate:runtime:kotlin + - name: Run runtime tests + run: npm run test:runtime:kotlin diff --git a/package-lock.json b/package-lock.json index b6df5d8da3..d9158e1cde 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2925,9 +2925,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "16.10.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.9.tgz", - "integrity": "sha512-H9ReOt+yqIJPCutkTYjFjlyK6WEMQYT9hLZMlWtOjFQY2ItppsWZ6RJf8Aw+jz5qTYceuHvFgPIaKOHtLAEWBw==" + "version": "20.2.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", + "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==" }, "node_modules/@types/prettier": { "version": "2.4.1", @@ -12819,6 +12819,11 @@ "typescript-json-schema": "bin/typescript-json-schema" } }, + "node_modules/typescript-json-schema/node_modules/@types/node": { + "version": "16.18.34", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.34.tgz", + "integrity": "sha512-VmVm7gXwhkUimRfBwVI1CHhwp86jDWR04B5FGebMMyxV90SlCmFujwUHrxTD4oO+SOYU86SoxvhgeRQJY7iXFg==" + }, "node_modules/typescript-json-schema/node_modules/yargs": { "version": "17.3.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", @@ -15609,9 +15614,9 @@ "dev": true }, "@types/node": { - "version": "16.10.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.9.tgz", - "integrity": "sha512-H9ReOt+yqIJPCutkTYjFjlyK6WEMQYT9hLZMlWtOjFQY2ItppsWZ6RJf8Aw+jz5qTYceuHvFgPIaKOHtLAEWBw==" + "version": "20.2.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", + "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==" }, "@types/prettier": { "version": "2.4.1", @@ -23083,6 +23088,11 @@ "yargs": "^17.1.1" }, "dependencies": { + "@types/node": { + "version": "16.18.34", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.34.tgz", + "integrity": "sha512-VmVm7gXwhkUimRfBwVI1CHhwp86jDWR04B5FGebMMyxV90SlCmFujwUHrxTD4oO+SOYU86SoxvhgeRQJY7iXFg==" + }, "yargs": { "version": "17.3.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", diff --git a/package.json b/package.json index f16bac09dd..3246511220 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,8 @@ "test:blackbox:java": "cross-env CI=true jest ./test/blackbox/blackbox-java.spec.ts", "test:runtime:java": "cross-env CI=true jest ./test/runtime/runtime-java.spec.ts", "generate:runtime:java": "cross-env CI=true ts-node ./test/runtime/runtime-java.ts", + "test:runtime:kotlin": "cross-env CI=true jest ./test/runtime/runtime-kotlin.spec.ts", + "generate:runtime:kotlin": "cross-env CI=true ts-node ./test/runtime/runtime-kotlin.ts", "test:runtime:rust": "cross-env CI=true jest ./test/runtime/runtime-rust.spec.ts", "generate:runtime:rust": "cross-env CI=true ts-node ./test/runtime/runtime-rust.ts", "test:runtime:php": "cross-env CI=true jest ./test/runtime/runtime-php.spec.ts", diff --git a/test/runtime/runtime-kotlin.spec.ts b/test/runtime/runtime-kotlin.spec.ts new file mode 100644 index 0000000000..927c03e014 --- /dev/null +++ b/test/runtime/runtime-kotlin.spec.ts @@ -0,0 +1,19 @@ +import { execCommand } from '../blackbox/utils/Utils'; +import path from 'path'; + +jest.setTimeout(50000); + +test('Kotlin runtime testing', async () => { + //The 'build' command here + const buildCommand = `cd ${path.resolve( + __dirname, + './runtime-kotlin' + )} && ./gradlew build`; + await execCommand(buildCommand); + //The 'test' command here + const testCommand = `cd ${path.resolve( + __dirname, + './runtime-kotlin' + )} && ./gradlew test`; + await execCommand(testCommand); +}); diff --git a/test/runtime/runtime-kotlin.ts b/test/runtime/runtime-kotlin.ts new file mode 100644 index 0000000000..0045c71b26 --- /dev/null +++ b/test/runtime/runtime-kotlin.ts @@ -0,0 +1,17 @@ +import { KOTLIN_DEFAULT_PRESET, KotlinFileGenerator } from '../../'; +import path from 'path'; +import input from './generic-input.json'; + +const generator = new KotlinFileGenerator({ + presets: [KOTLIN_DEFAULT_PRESET] +}); + +generator.generateToFiles( + input, + path.resolve( + // eslint-disable-next-line no-undef + __dirname, + './runtime-kotlin/src/main/kotlin/com/mycompany/app/generic' + ), + { packageName: 'com.mycompany.app.generic' } +); diff --git a/test/runtime/runtime-kotlin/.gitignore b/test/runtime/runtime-kotlin/.gitignore new file mode 100644 index 0000000000..0bab4ea098 --- /dev/null +++ b/test/runtime/runtime-kotlin/.gitignore @@ -0,0 +1,25 @@ +# Gradle-specific files +.gradle +**/build/ +!src/**/build/ + +# Generated Src files +src/main/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache + +# Eclipse Gradle plugin generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath \ No newline at end of file diff --git a/test/runtime/runtime-kotlin/README.md b/test/runtime/runtime-kotlin/README.md new file mode 100644 index 0000000000..5d744d7566 --- /dev/null +++ b/test/runtime/runtime-kotlin/README.md @@ -0,0 +1,8 @@ +# Modelina Kotlin Runtime project + +This is the Modelina Kotlin runtime project that is used to test the Kotlin-generated code from Modelina at runtime to ensure that everything works as expected. + +Here is how it works: +- The models are first generated during the build phase of the project, by running the root npm script `npm run generate:runtime:kotlin`. These models are pre-defined with the [generic input](../generic-input.json). +- The tests are manually added and changed. +- When the project is tested, it tests the generated models at runtime for semantic errors. \ No newline at end of file diff --git a/test/runtime/runtime-kotlin/build.gradle b/test/runtime/runtime-kotlin/build.gradle new file mode 100644 index 0000000000..b26d378623 --- /dev/null +++ b/test/runtime/runtime-kotlin/build.gradle @@ -0,0 +1,13 @@ +plugins { + id("org.jetbrains.kotlin.jvm") version "1.8.10" +} + +repositories { + mavenCentral() +} + +dependencies { + testImplementation("org.jetbrains.kotlin:kotlin-test-junit5") + testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.1") + implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' +} \ No newline at end of file diff --git a/test/runtime/runtime-kotlin/gradle/wrapper/gradle-wrapper.jar b/test/runtime/runtime-kotlin/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..58499e4f0f165e3675625ddb3bbc176da697d2e6 GIT binary patch literal 55618 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�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%0AFe;)Grk!CPA88c9MU{Dk7_ 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 F{|{XF1uy^r literal 0 HcmV?d00001 diff --git a/test/runtime/runtime-kotlin/gradle/wrapper/gradle-wrapper.properties b/test/runtime/runtime-kotlin/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..45a4d68f8c --- /dev/null +++ b/test/runtime/runtime-kotlin/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-bin.zip +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/test/runtime/runtime-kotlin/gradlew b/test/runtime/runtime-kotlin/gradlew new file mode 100755 index 0000000000..9d9cdba713 --- /dev/null +++ b/test/runtime/runtime-kotlin/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS --illegal-access=permit $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/test/runtime/runtime-kotlin/gradlew.bat b/test/runtime/runtime-kotlin/gradlew.bat new file mode 100644 index 0000000000..e95643d6a2 --- /dev/null +++ b/test/runtime/runtime-kotlin/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/test/runtime/runtime-kotlin/settings.gradle b/test/runtime/runtime-kotlin/settings.gradle new file mode 100644 index 0000000000..c8a7c12c52 --- /dev/null +++ b/test/runtime/runtime-kotlin/settings.gradle @@ -0,0 +1,18 @@ +/* + * This settings file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * In a single project build this file can be empty or even removed. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user guide at https://docs.gradle.org/4.4.1/userguide/multi_project_builds.html + */ + +/* +// To declare projects as part of a multi-project build use the 'include' method +include 'shared' +include 'api' +include 'services:webservice' +*/ + +rootProject.name = 'runtime-kotlin' diff --git a/test/runtime/runtime-kotlin/src/test/kotlin/com/mycompany/app/generic/AddressTest.kt b/test/runtime/runtime-kotlin/src/test/kotlin/com/mycompany/app/generic/AddressTest.kt new file mode 100644 index 0000000000..64096933c5 --- /dev/null +++ b/test/runtime/runtime-kotlin/src/test/kotlin/com/mycompany/app/generic/AddressTest.kt @@ -0,0 +1,45 @@ +package com.mycompany.app.generic + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import org.hamcrest.CoreMatchers.containsString +import org.hamcrest.CoreMatchers.not +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.TestInstance + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class AddressTest { + private lateinit var address: Address + + @BeforeAll + fun setup() { + address = Address( + streetName = "Test address 2", + houseNumber = 2, + marriage = true, + members = 2, + arrayType = listOf(2, "test"), + nestedObject = Address.NestedObject(test = "test") + ) + } + + @Test + fun shouldBeAbleToSerializeModel() { + val objectMapper: ObjectMapper = jacksonObjectMapper() + val json = objectMapper.writeValueAsString(address) + assertTrue(json.isNotEmpty()) + } + + @Test + fun shouldNotContainAdditionalPropertiesWhenSerialized() { + /** + * additionalProperties should be unwrapped when serialized + */ + val objectMapper: ObjectMapper = jacksonObjectMapper() + val json = objectMapper.writeValueAsString(address) + assertThat(json, not(containsString("additionalProperties"))) + } +} \ No newline at end of file From 8b5701e965fc9ee3e6da5b8cc935e5fa04a52ffe Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 14:32:34 +0200 Subject: [PATCH 47/79] docs: add SumantxD as a contributor for test, infra, and code (#1383) * update README.md * update .all-contributorsrc --------- Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 11 +++++++++++ README.md | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 03b8ddc822..a5d1f24000 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -635,6 +635,17 @@ "example", "doc" ] + }, + { + "login": "SumantxD", + "name": "Sumant.xD", + "avatar_url": "https://avatars.githubusercontent.com/u/65810424?v=4", + "profile": "https://github.com/SumantxD", + "contributions": [ + "test", + "infra", + "code" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index ff6b4b87c7..692f68c8e9 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![Discussions](https://img.shields.io/github/discussions/asyncapi/modelina)](https://github.com/asyncapi/modelina/discussions) [![Website](https://img.shields.io/website?label=website&url=https%3A%2F%2Fwww.modelina.org)](https://www.modelina.org) [![Playground](https://img.shields.io/website?label=playground&url=https%3A%2F%2Fwww.modelina.org%2Fplayground)](https://www.modelina.org/playground) -[![All Contributors](https://img.shields.io/badge/all_contributors-57-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-58-orange.svg?style=flat-square)](#contributors-) Your one-stop tool for generating accurate and well-tested models for representing the message payloads. Use it as a tool in your development workflow, or a library in a larger integrations, entirely in your control. @@ -399,6 +399,7 @@ Thanks go out to these wonderful people ([emoji key](https://allcontributors.org Jean-François Côté
    Jean-François Côté

    💻 ⚠️ 💡 📖 + Sumant.xD
    Sumant.xD

    ⚠️ 🚇 💻 From 8921f2be4d1aef081911ad6ba7b2ff028ac38b64 Mon Sep 17 00:00:00 2001 From: asyncapi-bot Date: Wed, 7 Jun 2023 16:05:16 +0200 Subject: [PATCH 48/79] fix: update @asyncapi/openapi-schema-parser to 3.0.2 version (#1386) --- package-lock.json | 46 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index d9158e1cde..bcdc724d28 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@apidevtools/json-schema-ref-parser": "^9.0.9", "@apidevtools/swagger-parser": "^10.0.3", "@asyncapi/avro-schema-parser": "^3.0.0", - "@asyncapi/openapi-schema-parser": "^3.0.1", + "@asyncapi/openapi-schema-parser": "^3.0.2", "@asyncapi/parser": "^2.0.1", "@asyncapi/raml-dt-schema-parser": "^4.0.1", "@swc/core": "^1.3.5", @@ -101,11 +101,11 @@ } }, "node_modules/@asyncapi/openapi-schema-parser": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@asyncapi/openapi-schema-parser/-/openapi-schema-parser-3.0.1.tgz", - "integrity": "sha512-Ps1KAinQHF6YzJJwm0pJNeVnfZC6nFE76dYn5ZzE6l/mUNYtedoiqbCdF+NYA8nDTsXg3087c/drQZuEd/6BgQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@asyncapi/openapi-schema-parser/-/openapi-schema-parser-3.0.2.tgz", + "integrity": "sha512-+VD3Ro/Z5u83mB9nNN8oLHEJnfDascHhZwaqzTYeVbBhwwwOkp2QI8ozbphPqmtcfbMBH64pPGscSAWSwrnSVA==", "dependencies": { - "@asyncapi/parser": "^2.0.1", + "@asyncapi/parser": "^2.0.2", "@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0", "ajv": "^8.11.0", "ajv-errors": "^3.0.0", @@ -113,11 +113,11 @@ } }, "node_modules/@asyncapi/parser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@asyncapi/parser/-/parser-2.0.1.tgz", - "integrity": "sha512-T6Z8PPD+U3XPL05sjT0yLHtDyoqA16pj1j7xNbvpt8SCFzdzw4QMsbvJFAKaXk1/bztzlMq+oWVmeiGazt5WGA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@asyncapi/parser/-/parser-2.0.2.tgz", + "integrity": "sha512-VYQSa/nYt6IYQMijr84tavfKn4qQheKDLzGM/rY/PUyikn7G8PM+lC6QmtNg84dHMq/Kahxe+yc9B3TfIXDJ2w==", "dependencies": { - "@asyncapi/specs": "^5.0.1", + "@asyncapi/specs": "^5.1.0", "@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0", "@stoplight/json-ref-resolver": "^3.1.5", "@stoplight/spectral-core": "^1.16.1", @@ -137,9 +137,9 @@ } }, "node_modules/@asyncapi/parser/node_modules/@asyncapi/specs": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-5.0.1.tgz", - "integrity": "sha512-hWIko4JDZtBaRPO3OiDBCctNIOug+dux+p6TWmsxcgHBX4ziMmkBUfPZp6cMZtzEq/S9Nw7rKct1lPhZGfJHyg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-5.1.0.tgz", + "integrity": "sha512-yffhETqehkim43luMnPKOwzY0D0YtU4bKpORIXIaid6p5Y5kDLrMGJaEPkNieQp03HMjhjFrnUPtT8kvqe0+aQ==", "dependencies": { "@types/json-schema": "^7.0.11" } @@ -13546,11 +13546,11 @@ } }, "@asyncapi/openapi-schema-parser": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@asyncapi/openapi-schema-parser/-/openapi-schema-parser-3.0.1.tgz", - "integrity": "sha512-Ps1KAinQHF6YzJJwm0pJNeVnfZC6nFE76dYn5ZzE6l/mUNYtedoiqbCdF+NYA8nDTsXg3087c/drQZuEd/6BgQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@asyncapi/openapi-schema-parser/-/openapi-schema-parser-3.0.2.tgz", + "integrity": "sha512-+VD3Ro/Z5u83mB9nNN8oLHEJnfDascHhZwaqzTYeVbBhwwwOkp2QI8ozbphPqmtcfbMBH64pPGscSAWSwrnSVA==", "requires": { - "@asyncapi/parser": "^2.0.1", + "@asyncapi/parser": "^2.0.2", "@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0", "ajv": "^8.11.0", "ajv-errors": "^3.0.0", @@ -13558,11 +13558,11 @@ } }, "@asyncapi/parser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@asyncapi/parser/-/parser-2.0.1.tgz", - "integrity": "sha512-T6Z8PPD+U3XPL05sjT0yLHtDyoqA16pj1j7xNbvpt8SCFzdzw4QMsbvJFAKaXk1/bztzlMq+oWVmeiGazt5WGA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@asyncapi/parser/-/parser-2.0.2.tgz", + "integrity": "sha512-VYQSa/nYt6IYQMijr84tavfKn4qQheKDLzGM/rY/PUyikn7G8PM+lC6QmtNg84dHMq/Kahxe+yc9B3TfIXDJ2w==", "requires": { - "@asyncapi/specs": "^5.0.1", + "@asyncapi/specs": "^5.1.0", "@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0", "@stoplight/json-ref-resolver": "^3.1.5", "@stoplight/spectral-core": "^1.16.1", @@ -13582,9 +13582,9 @@ }, "dependencies": { "@asyncapi/specs": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-5.0.1.tgz", - "integrity": "sha512-hWIko4JDZtBaRPO3OiDBCctNIOug+dux+p6TWmsxcgHBX4ziMmkBUfPZp6cMZtzEq/S9Nw7rKct1lPhZGfJHyg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@asyncapi/specs/-/specs-5.1.0.tgz", + "integrity": "sha512-yffhETqehkim43luMnPKOwzY0D0YtU4bKpORIXIaid6p5Y5kDLrMGJaEPkNieQp03HMjhjFrnUPtT8kvqe0+aQ==", "requires": { "@types/json-schema": "^7.0.11" } diff --git a/package.json b/package.json index 3246511220..52d2ddf4ae 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "@apidevtools/json-schema-ref-parser": "^9.0.9", "@apidevtools/swagger-parser": "^10.0.3", "@asyncapi/avro-schema-parser": "^3.0.0", - "@asyncapi/openapi-schema-parser": "^3.0.1", + "@asyncapi/openapi-schema-parser": "^3.0.2", "@asyncapi/parser": "^2.0.1", "@asyncapi/raml-dt-schema-parser": "^4.0.1", "@swc/core": "^1.3.5", From ebb6f4cbba944dd0e1596052e28c40a6da9d10d9 Mon Sep 17 00:00:00 2001 From: asyncapi-bot Date: Wed, 7 Jun 2023 16:32:30 +0200 Subject: [PATCH 49/79] chore(release): v1.8.3 (#1388) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index bcdc724d28..33c0fa2f74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@asyncapi/modelina", - "version": "1.8.2", + "version": "1.8.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@asyncapi/modelina", - "version": "1.8.2", + "version": "1.8.3", "license": "Apache-2.0", "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.9", diff --git a/package.json b/package.json index 52d2ddf4ae..3b17e07505 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@asyncapi/modelina", - "version": "1.8.2", + "version": "1.8.3", "description": "Library for generating data models based on inputs such as AsyncAPI, OpenAPI, or JSON Schema documents", "license": "Apache-2.0", "homepage": "https://www.modelina.org", From ba96502648ed6af1b7e6dacf28b13e75113eea95 Mon Sep 17 00:00:00 2001 From: asyncapi-bot Date: Wed, 7 Jun 2023 17:07:36 +0200 Subject: [PATCH 50/79] fix: update @asyncapi/raml-dt-schema-parser to 4.0.2 version (#1387) Co-authored-by: asyncapi-bot Co-authored-by: asyncapi-bot-eve --- package-lock.json | 18 +++++++++--------- package.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 33c0fa2f74..17ea15a879 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@asyncapi/avro-schema-parser": "^3.0.0", "@asyncapi/openapi-schema-parser": "^3.0.2", "@asyncapi/parser": "^2.0.1", - "@asyncapi/raml-dt-schema-parser": "^4.0.1", + "@asyncapi/raml-dt-schema-parser": "^4.0.2", "@swc/core": "^1.3.5", "@swc/jest": "^0.2.23", "alterschema": "^1.1.2", @@ -201,11 +201,11 @@ } }, "node_modules/@asyncapi/raml-dt-schema-parser": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@asyncapi/raml-dt-schema-parser/-/raml-dt-schema-parser-4.0.1.tgz", - "integrity": "sha512-Cf4fzskfVFaESIdMInN5V0ZukSaOG7wzSuFcZiPhni5/m0G8H2+k/ABblHFClsjonLzo1Bhp5JKguW9dbC5oHw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@asyncapi/raml-dt-schema-parser/-/raml-dt-schema-parser-4.0.2.tgz", + "integrity": "sha512-9XiHDTipurmui0BryZ3iGkccw1Qp8OV0GQhjn4H2dhoLf6KNTfp4uYhpBfo3NOP2wRLzDyE9aaRsOnBTRzKRgQ==", "dependencies": { - "@asyncapi/parser": "^2.0.1", + "@asyncapi/parser": "^2.0.2", "js-yaml": "^4.1.0", "ramldt2jsonschema": "^1.2.3", "webapi-parser": "^0.5.0" @@ -13642,11 +13642,11 @@ } }, "@asyncapi/raml-dt-schema-parser": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@asyncapi/raml-dt-schema-parser/-/raml-dt-schema-parser-4.0.1.tgz", - "integrity": "sha512-Cf4fzskfVFaESIdMInN5V0ZukSaOG7wzSuFcZiPhni5/m0G8H2+k/ABblHFClsjonLzo1Bhp5JKguW9dbC5oHw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@asyncapi/raml-dt-schema-parser/-/raml-dt-schema-parser-4.0.2.tgz", + "integrity": "sha512-9XiHDTipurmui0BryZ3iGkccw1Qp8OV0GQhjn4H2dhoLf6KNTfp4uYhpBfo3NOP2wRLzDyE9aaRsOnBTRzKRgQ==", "requires": { - "@asyncapi/parser": "^2.0.1", + "@asyncapi/parser": "^2.0.2", "js-yaml": "^4.1.0", "ramldt2jsonschema": "^1.2.3", "webapi-parser": "^0.5.0" diff --git a/package.json b/package.json index 3b17e07505..f54ec9b1fd 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@asyncapi/avro-schema-parser": "^3.0.0", "@asyncapi/openapi-schema-parser": "^3.0.2", "@asyncapi/parser": "^2.0.1", - "@asyncapi/raml-dt-schema-parser": "^4.0.1", + "@asyncapi/raml-dt-schema-parser": "^4.0.2", "@swc/core": "^1.3.5", "@swc/jest": "^0.2.23", "alterschema": "^1.1.2", From a6423ed0304743ee5a600e78facaa0881a3bfac3 Mon Sep 17 00:00:00 2001 From: asyncapi-bot Date: Wed, 7 Jun 2023 17:31:59 +0200 Subject: [PATCH 51/79] chore(release): v1.8.4 (#1389) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 17ea15a879..2bc57b2b79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@asyncapi/modelina", - "version": "1.8.3", + "version": "1.8.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@asyncapi/modelina", - "version": "1.8.3", + "version": "1.8.4", "license": "Apache-2.0", "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.9", diff --git a/package.json b/package.json index f54ec9b1fd..f72d35e3c2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@asyncapi/modelina", - "version": "1.8.3", + "version": "1.8.4", "description": "Library for generating data models based on inputs such as AsyncAPI, OpenAPI, or JSON Schema documents", "license": "Apache-2.0", "homepage": "https://www.modelina.org", From b20c8a46ae880dc7183d7cfa8a3e35feb56b092b Mon Sep 17 00:00:00 2001 From: Rishi <52498617+kaushik-rishi@users.noreply.github.com> Date: Thu, 8 Jun 2023 01:10:45 +0530 Subject: [PATCH 52/79] chore(website): add packageName option for Kotlin, Java, Go (#1380) * chore(website): add packageName option for Kotlin, Java, Go, Python * revert python packagename option * add default options for python generator Co-authored-by: Jonas Lagoni --------- Co-authored-by: Jonas Lagoni --- .../src/components/playground/Playground.tsx | 12 ++++++ .../playground/options/GoGeneratorOptions.tsx | 38 +++++++++++++++++-- .../options/JavaGeneratorOptions.tsx | 37 ++++++++++++++++-- .../options/KotlinGeneratorOptions.tsx | 37 ++++++++++++++++-- .../options/PythonGeneratorOptions.tsx | 2 +- .../src/pages/api/functions/GoGenerator.ts | 2 +- .../src/pages/api/functions/JavaGenerator.ts | 2 +- .../pages/api/functions/KotlinGenerator.ts | 2 +- .../pages/api/functions/PythonGenerator.ts | 4 +- modelina-website/src/types/index.ts | 24 +++++++++--- 10 files changed, 135 insertions(+), 25 deletions(-) diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index 0dc804d37d..02ec813452 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -96,6 +96,9 @@ class Playground extends React.Component< phpIncludeDescriptions: false, phpNamespace: 'AsyncAPI/Models', cplusplusNamespace: 'AsyncapiModels', + javaPackageName: 'asyncapi.models', + goPackageName: 'asyncapi.models', + kotlinPackageName: 'asyncapi.models' }; hasLoadedQuery: boolean = false; constructor(props: ModelinaPlaygroundProps) { @@ -286,6 +289,15 @@ class Playground extends React.Component< if(query.cplusplusNamespace !== undefined) { this.config.cplusplusNamespace = query.cplusplusNamespace; } + if (query.javaPackageName !== undefined) { + this.config.javaPackageName = query.javaPackageName; + } + if(query.goPackageName !== undefined) { + this.config.goPackageName = query.goPackageName; + } + if (query.kotlinPackageName !== undefined) { + this.config.kotlinPackageName = query.kotlinPackageName; + } if (this.props.router.isReady && !this.hasLoadedQuery) { this.hasLoadedQuery = true; this.generateNewCode(this.state.input); diff --git a/modelina-website/src/components/playground/options/GoGeneratorOptions.tsx b/modelina-website/src/components/playground/options/GoGeneratorOptions.tsx index 487c803f03..2302020f1a 100644 --- a/modelina-website/src/components/playground/options/GoGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/GoGeneratorOptions.tsx @@ -1,11 +1,14 @@ import React from 'react'; +import { debounce } from 'lodash'; import { PlaygroundGoConfigContext } from '@/components/contexts/PlaygroundConfigContext'; interface GoGeneratorOptionsProps { setNewConfig?: (queryKey: string, queryValue: string) => void; } -interface GoGeneratorState {} +interface GoGeneratorState { + packageName?: string; +} export const defaultState: GoGeneratorState = {}; @@ -18,17 +21,44 @@ class GoGeneratorOptions extends React.Component< constructor(props: any) { super(props); this.state = defaultState; + this.debouncedSetNewConfig = this.debouncedSetNewConfig.bind(this); + this.onChangePackageName = this.onChangePackageName.bind(this); + } + + debouncedSetNewConfig = debounce(this.props.setNewConfig as (queryKey: string, queryValue: string) => void, 500); + + componentDidMount(): void { + this.setState({ ...this.state, packageName: this.context?.goPackageName }); } + onChangePackageName(event: any) { + this.setState({ ...this.state, packageName: event.target.value }); + if (this.props.setNewConfig) { + this.debouncedSetNewConfig('goPackageName', event.target.value); + } + } + + render() { return (

      Go Specific options

      - - Currently no options are available - +
    • + +
    ); } diff --git a/modelina-website/src/components/playground/options/JavaGeneratorOptions.tsx b/modelina-website/src/components/playground/options/JavaGeneratorOptions.tsx index 1d5a2a2f31..6220f604c6 100644 --- a/modelina-website/src/components/playground/options/JavaGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/JavaGeneratorOptions.tsx @@ -1,11 +1,14 @@ import React from 'react'; +import { debounce } from 'lodash'; import { PlaygroundJavaConfigContext } from '@/components/contexts/PlaygroundConfigContext'; interface JavaGeneratorOptionsProps { setNewConfig?: (queryKey: string, queryValue: string) => void; } -interface JavaGeneratorState {} +interface JavaGeneratorState { + packageName?: string; +} export const defaultState: JavaGeneratorState = {}; @@ -18,6 +21,21 @@ class JavaGeneratorOptions extends React.Component< constructor(props: any) { super(props); this.state = defaultState; + this.debouncedSetNewConfig = this.debouncedSetNewConfig.bind(this); + this.onChangePackageName = this.onChangePackageName.bind(this); + } + + debouncedSetNewConfig = debounce(this.props.setNewConfig as (queryKey: string, queryValue: string) => void, 500); + + componentDidMount(): void { + this.setState({ ...this.state, packageName: this.context?.javaPackageName }); + } + + onChangePackageName(event: any) { + this.setState({ ...this.state, packageName: event.target.value }); + if (this.props.setNewConfig) { + this.debouncedSetNewConfig('javaPackageName', event.target.value); + } } render() { @@ -26,9 +44,20 @@ class JavaGeneratorOptions extends React.Component<

    Java Specific options

    - - Currently no options are available - +
  • + +
  • ); } diff --git a/modelina-website/src/components/playground/options/KotlinGeneratorOptions.tsx b/modelina-website/src/components/playground/options/KotlinGeneratorOptions.tsx index 6c91a142ff..9d19984a8b 100644 --- a/modelina-website/src/components/playground/options/KotlinGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/KotlinGeneratorOptions.tsx @@ -1,11 +1,14 @@ import React from 'react'; +import { debounce } from 'lodash'; import { PlaygroundKotlinConfigContext } from '@/components/contexts/PlaygroundConfigContext'; interface KotlinGeneratorOptionsProps { setNewConfig?: (queryKey: string, queryValue: string) => void; } -interface KotlinGeneratorState {} +interface KotlinGeneratorState { + packageName?: string; +} export const defaultState: KotlinGeneratorState = {}; @@ -18,6 +21,21 @@ class KotlinGeneratorOptions extends React.Component< constructor(props: any) { super(props); this.state = defaultState; + this.debouncedSetNewConfig = this.debouncedSetNewConfig.bind(this); + this.onChangePackageName = this.onChangePackageName.bind(this); + } + + debouncedSetNewConfig = debounce(this.props.setNewConfig as (queryKey: string, queryValue: string) => void, 500); + + componentDidMount(): void { + this.setState({ ...this.state, packageName: this.context?.kotlinPackageName }); + } + + onChangePackageName(event: any) { + this.setState({ ...this.state, packageName: event.target.value }); + if (this.props.setNewConfig) { + this.debouncedSetNewConfig('kotlinPackageName', event.target.value); + } } render() { @@ -26,9 +44,20 @@ class KotlinGeneratorOptions extends React.Component<

    Kotlin Specific options

    - - Currently no options are available - +
  • + +
  • ); } diff --git a/modelina-website/src/components/playground/options/PythonGeneratorOptions.tsx b/modelina-website/src/components/playground/options/PythonGeneratorOptions.tsx index 5a6c2f5270..680adf0313 100644 --- a/modelina-website/src/components/playground/options/PythonGeneratorOptions.tsx +++ b/modelina-website/src/components/playground/options/PythonGeneratorOptions.tsx @@ -33,4 +33,4 @@ class PythonGeneratorOptions extends React.Component< ); } } -export default PythonGeneratorOptions; +export default PythonGeneratorOptions; \ No newline at end of file diff --git a/modelina-website/src/pages/api/functions/GoGenerator.ts b/modelina-website/src/pages/api/functions/GoGenerator.ts index 9746197b34..feb33127b5 100644 --- a/modelina-website/src/pages/api/functions/GoGenerator.ts +++ b/modelina-website/src/pages/api/functions/GoGenerator.ts @@ -28,7 +28,7 @@ export async function getGoModels( try { const generator = new GoGenerator(options); const generatedModels = await generator.generateCompleteModels(input, { - packageName: 'asyncapi.models' + packageName: generatorOptions.goPackageName || 'asyncapi.models' }); return convertModelsToProps(generatedModels); } catch (e : any) { diff --git a/modelina-website/src/pages/api/functions/JavaGenerator.ts b/modelina-website/src/pages/api/functions/JavaGenerator.ts index 99bf3963fc..4f664b7f31 100644 --- a/modelina-website/src/pages/api/functions/JavaGenerator.ts +++ b/modelina-website/src/pages/api/functions/JavaGenerator.ts @@ -28,7 +28,7 @@ export async function getJavaModels( try { const generator = new JavaGenerator(options); const generatedModels = await generator.generateCompleteModels(input, { - packageName: 'asyncapi.models' + packageName: generatorOptions.javaPackageName || 'asyncapi.models' }); return convertModelsToProps(generatedModels); } catch (e : any) { diff --git a/modelina-website/src/pages/api/functions/KotlinGenerator.ts b/modelina-website/src/pages/api/functions/KotlinGenerator.ts index 0f73a785ce..638deddcdd 100644 --- a/modelina-website/src/pages/api/functions/KotlinGenerator.ts +++ b/modelina-website/src/pages/api/functions/KotlinGenerator.ts @@ -28,7 +28,7 @@ export async function getKotlinModels( try { const generator = new KotlinGenerator(options); const generatedModels = await generator.generateCompleteModels(input, { - packageName: 'asyncapi.models' + packageName: generatorOptions.kotlinPackageName || 'asyncapi.models' }); return convertModelsToProps(generatedModels); } catch (e) { diff --git a/modelina-website/src/pages/api/functions/PythonGenerator.ts b/modelina-website/src/pages/api/functions/PythonGenerator.ts index 319f50f73e..d219ac360c 100644 --- a/modelina-website/src/pages/api/functions/PythonGenerator.ts +++ b/modelina-website/src/pages/api/functions/PythonGenerator.ts @@ -17,9 +17,7 @@ export async function getPythonModels( try { const generator = new PythonGenerator(options); - const generatedModels = await generator.generateCompleteModels(input, { - packageName: 'asyncapi.models' - }); + const generatedModels = await generator.generateCompleteModels(input, {}); return convertModelsToProps(generatedModels); } catch (e : any) { console.error('Could not generate models'); diff --git a/modelina-website/src/types/index.ts b/modelina-website/src/types/index.ts index 67c46180d1..2763a3bf23 100644 --- a/modelina-website/src/types/index.ts +++ b/modelina-website/src/types/index.ts @@ -19,11 +19,15 @@ export interface ModelinaTypeScriptOptions extends ModelinaGeneralOptions { tsIncludeExampleFunction: boolean; } -export interface ModelinaJavaOptions extends ModelinaGeneralOptions {} +export interface ModelinaJavaOptions extends ModelinaGeneralOptions { + javaPackageName?: string; +} export interface ModelinaCplusplusOptions extends ModelinaGeneralOptions { cplusplusNamespace?: string; } -export interface ModelinaGoOptions extends ModelinaGeneralOptions {} +export interface ModelinaGoOptions extends ModelinaGeneralOptions { + goPackageName?: string; +} export interface ModelinaJavaScriptOptions extends ModelinaGeneralOptions {} export interface ModelinaPhpOptions extends ModelinaGeneralOptions { phpIncludeDescriptions: boolean; @@ -39,7 +43,9 @@ export interface ModelinaCSharpOptions extends ModelinaGeneralOptions { csharpNamespace?: string; csharpNullable: boolean; } -export interface ModelinaKotlinOptions extends ModelinaGeneralOptions {} +export interface ModelinaKotlinOptions extends ModelinaGeneralOptions { + kotlinPackageName?: string; +} export interface ModelinaRustOptions extends ModelinaGeneralOptions {} export interface ModelinaPythonOptions extends ModelinaGeneralOptions {} export interface ModelinaDartOptions extends ModelinaGeneralOptions {} @@ -91,8 +97,12 @@ export interface ModelinaGeneralQueryOptions { enumKeyNamingFormat?: string; } -export interface ModelinaJavaQueryOptions {} -export interface ModelinaGoQueryOptions {} +export interface ModelinaJavaQueryOptions { + javaPackageName?: string; +} +export interface ModelinaGoQueryOptions { + goPackageName?: string; +} export interface ModelinaJavaScriptQueryOptions {} export interface ModelinaCSharpQueryOptions { csharpArrayType?: string; @@ -104,7 +114,9 @@ export interface ModelinaCSharpQueryOptions { csharpNamespace?: string; csharpNullable?: string; } -export interface ModelinaKotlinQueryOptions {} +export interface ModelinaKotlinQueryOptions { + kotlinPackageName?: string; +} export interface ModelinaRustQueryOptions {} export interface ModelinaPythonQueryOptions {} export interface ModelinaCplusplusQueryOptions { From a32704360d7ea209d987160060711e2f2fcb122d Mon Sep 17 00:00:00 2001 From: "Sumant.xD" <65810424+SumantxD@users.noreply.github.com> Date: Thu, 8 Jun 2023 04:31:15 +0530 Subject: [PATCH 53/79] chore(website): add description for options in playground (#1366) --- modelina-website/src/components/InfoModal.tsx | 61 +++++++++++++++++++ .../src/components/playground/Playground.tsx | 2 +- .../playground/options/GeneralOptions.tsx | 20 +++++- 3 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 modelina-website/src/components/InfoModal.tsx diff --git a/modelina-website/src/components/InfoModal.tsx b/modelina-website/src/components/InfoModal.tsx new file mode 100644 index 0000000000..f47b17b1b9 --- /dev/null +++ b/modelina-website/src/components/InfoModal.tsx @@ -0,0 +1,61 @@ +import React, { useState, useEffect } from 'react'; + +interface InfoModalProps { + text: string; + children: React.ReactNode; +} + +export default function InfoModal(props: InfoModalProps){ + + const [showModal, setShowModal] = useState(false); + + const onOpenModal = () => { + setShowModal(true) + document.body.style.overflowY = 'hidden' + }; + + const onCloseModal = () => { + setShowModal(false) + document.body.style.overflowY = 'scroll' + }; + + const MyModal = () => { + return ( + <> +
    +
    +
    +

    {props.text}

    +
    + {props.children} +
    +
    +
    + + ) + } + + return( + <> + + {showModal && } + + ) + +} \ No newline at end of file diff --git a/modelina-website/src/components/playground/Playground.tsx b/modelina-website/src/components/playground/Playground.tsx index 02ec813452..6c240d4f81 100644 --- a/modelina-website/src/components/playground/Playground.tsx +++ b/modelina-website/src/components/playground/Playground.tsx @@ -318,7 +318,7 @@ class Playground extends React.Component< ); } return ( -
    +
    Modelina Playground diff --git a/modelina-website/src/components/playground/options/GeneralOptions.tsx b/modelina-website/src/components/playground/options/GeneralOptions.tsx index c8ddcb181b..cf8655ad9d 100644 --- a/modelina-website/src/components/playground/options/GeneralOptions.tsx +++ b/modelina-website/src/components/playground/options/GeneralOptions.tsx @@ -1,7 +1,9 @@ +"use client" import React from 'react'; import Select from '../../Select'; import { modelinaLanguageOptions } from '@/types'; import { PlaygroundGeneralConfigContext } from '@/components/contexts/PlaygroundConfigContext'; +import InfoModal from '@/components/InfoModal'; interface WithRouterProps { setNewConfig?: (queryKey: string, queryValue: string) => void; @@ -64,15 +66,26 @@ class GeneralOptions extends React.Component< } } + + + render() { return (

      General options

      -
    • -
    • + +

      + The provided option allows you to change the type of output you want to generate. + However, please be aware that certain outputs may not be supported within the playground + environment. To obtain an updated list of supported outputs, kindly refer to {' '} + the main readme file. +

      +
      + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    ); } diff --git a/modelina-website/src/helpers/GeneratorCode/JavaGenerator.ts b/modelina-website/src/helpers/GeneratorCode/JavaGenerator.ts index 495eec1b80..5eed6fa5de 100644 --- a/modelina-website/src/helpers/GeneratorCode/JavaGenerator.ts +++ b/modelina-website/src/helpers/GeneratorCode/JavaGenerator.ts @@ -8,7 +8,7 @@ export function getJavaGeneratorCode( const optionString: string[] = getGeneralGeneratorCode(generatorOptions, 'javaDefaultEnumKeyConstraints', 'javaDefaultPropertyKeyConstraints', 'javaDefaultModelNameConstraints'); const optionStringPresets: string[] = []; - if(generatorOptions.showTypeMappingExample === true) { + if (generatorOptions.showTypeMappingExample === true) { optionString.push(`typeMapping: { Integer: ({ dependencyManager, constrainedModel, options, partOfProperty }) => { // Add custom dependency for your type if required. @@ -20,6 +20,70 @@ export function getJavaGeneratorCode( }`); } + if (generatorOptions.javaIncludeJackson) { + optionStringPresets.push(`JAVA_JACKSON_PRESET`) + } + + if (generatorOptions.javaIncludeMarshaling) { + optionStringPresets.push(`{ + preset: JAVA_COMMON_PRESET, + options: { + equal: false, + hashCode: false, + classToString: false, + marshalling: true + } +}`); + } + + if (generatorOptions.javaArrayType) { + optionString.push(`collectionType: '${generatorOptions.javaArrayType}'`); + } + + if (generatorOptions.javaOverwriteHashcode) { + optionStringPresets.push(`{ + preset: JAVA_COMMON_PRESET, + options: { + equal: false, + hashCode: true, + classToString: false, + marshalling: false + } +}`); + } + + if (generatorOptions.javaOverwriteEqual) { + optionStringPresets.push(`{ + preset: JAVA_COMMON_PRESET, + options: { + equal: true, + hashCode: false, + classToString: false, + marshalling: false + } +}`); + } + + if (generatorOptions.javaOverwriteToString) { + optionStringPresets.push(`{ + preset: JAVA_COMMON_PRESET, + options: { + equal: false, + hashCode: false, + classToString: true, + marshalling: false + } +}`); + } + + if (generatorOptions.javaJavaDocs) { + optionStringPresets.push(`JAVA_DESCRIPTION_PRESET`) + } + + if (generatorOptions.javaJavaxAnnotation) { + optionStringPresets.push(`JAVA_CONSTRAINTS_PRESET`) + } + const generateInstanceCode = renderGeneratorInstanceCode(optionString, optionStringPresets, 'JavaGenerator'); return `// Use the following code as starting point diff --git a/modelina-website/src/pages/api/functions/JavaGenerator.ts b/modelina-website/src/pages/api/functions/JavaGenerator.ts index 4f664b7f31..fc5dd7e901 100644 --- a/modelina-website/src/pages/api/functions/JavaGenerator.ts +++ b/modelina-website/src/pages/api/functions/JavaGenerator.ts @@ -3,6 +3,7 @@ import { JavaGenerator, JavaOptions, javaDefaultEnumKeyConstraints, javaDefaultM import { applyGeneralOptions, convertModelsToProps } from './Helpers'; import { ModelinaJavaOptions, ModelProps } from '../../../types'; import { DeepPartial } from '../../../../../lib/types/utils'; +import { JAVA_JACKSON_PRESET, JAVA_COMMON_PRESET, JAVA_DESCRIPTION_PRESET, JAVA_CONSTRAINTS_PRESET } from '../../../../../'; /** * This is the server side part of the Java generator, that takes input and generator parameters and generate the models. @@ -16,6 +17,72 @@ export async function getJavaModels( }; applyGeneralOptions(generatorOptions, options, javaDefaultEnumKeyConstraints, javaDefaultPropertyKeyConstraints, javaDefaultModelNameConstraints); + if (generatorOptions.javaIncludeJackson) { + options.presets?.push(JAVA_JACKSON_PRESET) + } + + if (generatorOptions.javaIncludeMarshaling) { + options.presets?.push({ + preset: JAVA_COMMON_PRESET, + options: { + equal: false, + hashCode: false, + classToString: false, + marshalling: true + } + }) + } + + if (generatorOptions.javaArrayType) { + options.collectionType = generatorOptions.javaArrayType; + } + + if (generatorOptions.javaOverwriteHashcode) { + options.presets?.push( + { + preset: JAVA_COMMON_PRESET, + options: { + equal: false, + hashCode: true, + classToString: false, + marshalling: false + } + } + ) + } + + if (generatorOptions.javaOverwriteEqual) { + options.presets?.push({ + preset: JAVA_COMMON_PRESET, + options: { + equal: true, + hashCode: false, + classToString: false, + marshalling: false + } + }) + } + + if(generatorOptions.javaOverwriteToString){ + options.presets?.push({ + preset: JAVA_COMMON_PRESET, + options: { + equal: false, + hashCode: false, + classToString: true, + marshalling: false + } + }) + } + + if (generatorOptions.javaJavaDocs) { + options.presets?.push(JAVA_DESCRIPTION_PRESET) + } + + if (generatorOptions.javaJavaxAnnotation) { + options.presets?.push(JAVA_CONSTRAINTS_PRESET) + } + if (generatorOptions.showTypeMappingExample) { options.typeMapping = { Integer: ({ dependencyManager }) => { diff --git a/modelina-website/src/types/index.ts b/modelina-website/src/types/index.ts index 2763a3bf23..87e63f3e49 100644 --- a/modelina-website/src/types/index.ts +++ b/modelina-website/src/types/index.ts @@ -21,6 +21,14 @@ export interface ModelinaTypeScriptOptions extends ModelinaGeneralOptions { export interface ModelinaJavaOptions extends ModelinaGeneralOptions { javaPackageName?: string; + javaIncludeJackson: boolean; + javaIncludeMarshaling: boolean; + javaArrayType: 'List' | 'Array' | undefined; + javaOverwriteHashcode: boolean; + javaOverwriteEqual: boolean; + javaOverwriteToString: boolean; + javaJavaDocs: boolean; + javaJavaxAnnotation: boolean; } export interface ModelinaCplusplusOptions extends ModelinaGeneralOptions { cplusplusNamespace?: string; @@ -99,6 +107,14 @@ export interface ModelinaGeneralQueryOptions { export interface ModelinaJavaQueryOptions { javaPackageName?: string; + javaIncludeJackson?: string; + javaIncludeMarshaling?: string; + javaArrayType?: string; + javaOverwriteHashcode?:string; + javaOverwriteEqual?: string; + javaOverwriteToString?: string; + javaJavaDocs?: string; + javaJavaxAnnotation?: string; } export interface ModelinaGoQueryOptions { goPackageName?: string; From abb54faf748683f8a342c46118a3b3af570ecf74 Mon Sep 17 00:00:00 2001 From: "Sumant.xD" <65810424+SumantxD@users.noreply.github.com> Date: Tue, 13 Jun 2023 23:11:36 +0530 Subject: [PATCH 60/79] chore(website): add info for general options (#1398) --- modelina-website/src/components/InfoModal.tsx | 2 +- .../playground/options/GeneralOptions.tsx | 83 ++++++++++++++++--- 2 files changed, 74 insertions(+), 11 deletions(-) diff --git a/modelina-website/src/components/InfoModal.tsx b/modelina-website/src/components/InfoModal.tsx index 8a2fb15135..7b93ff2109 100644 --- a/modelina-website/src/components/InfoModal.tsx +++ b/modelina-website/src/components/InfoModal.tsx @@ -23,7 +23,7 @@ export default function InfoModal(props: InfoModalProps){ return ( <>
    -
    +

    {props.text}

    diff --git a/modelina-website/src/components/playground/options/GeneralOptions.tsx b/modelina-website/src/components/playground/options/GeneralOptions.tsx index cf8655ad9d..852ad9b1c3 100644 --- a/modelina-website/src/components/playground/options/GeneralOptions.tsx +++ b/modelina-website/src/components/playground/options/GeneralOptions.tsx @@ -97,8 +97,15 @@ class GeneralOptions extends React.Component< -
  • -
  • + +

    + In code generation, a common task is to map the data types from the input model to the output. In Modelina you can do this through type mapping. +

    + This option includes a simple example type mapping, that maps integers to a custom type. +

    +
    +
  • -
  • -
  • + +

    + The indentation type option allows you to choose between using tabs or spaces for indentation in the generated code. +

    +
    +
  • -
  • -
  • + +

    + This option allows you to customize the naming style for properties in your code. There are no limitations to how you can format it, but for this simple example it provides the following options: +

    + Default: This option refers to the default naming format for properties, which may vary depending on the programming language or coding convention being used. +

    + Snake case: Property names are written in lowercase letters, and words are separated by underscores. (e.g: property_name) +

    + Pascal case: Property names start with an uppercase letter, and subsequent words are also capitalized. (e.g: PropertyName) +

    + Camel case: Property names start with a lowercase letter, and subsequent words are capitalized. (e.g: propertyName) +

    + Param case: Property names use hyphens to separate words, and all letters are in lowercase. (e.g: property-name) +

    + Constant case: Property names are written in uppercase letters, and words are separated by underscores. (e.g: PROPERTY_NAME) +

    +
    +
  • -
  • -
  • + +

    + This option allows you to customize the naming style for model names. There are no limitations to how you can format it, but for this simple example it provides the following options: +

    + Default: This option refers to the default naming format for models, which may vary depending on the programming language or coding convention being used. +

    + Snake case: Model names are written in lowercase letters, and words are separated by underscores. (e.g: model_name) +

    + Pascal case: Model names start with an uppercase letter, and subsequent words are also capitalized. (e.g: ModelName) +

    + Camel case: Model names start with a lowercase letter, and subsequent words are capitalized. (e.g: modelName) +

    + Param case: Model names use hyphens to separate words, and all letters are in lowercase. (e.g: model-name) +

    + Constant case: Model names are written in uppercase letters, and words are separated by underscores. (e.g: MODEL_NAME) +

    +
    +
  • -
  • -
  • + +

    + This option allows you to customize the naming style for enum keys. There are no limitations to how you can format it, but for this simple example it provides the following options: +

    + Default: This option refers to the default naming format for enum keys, which may vary depending on the programming language or coding convention being used. +

    + Snake case: Enum key names are written in lowercase letters, and words are separated by underscores. (e.g: enum_key) +

    + Pascal case: Enum key names start with an uppercase letter, and subsequent words are also capitalized. (e.g: EnumKey) +

    + Camel case: Enum key names start with a lowercase letter, and subsequent words are capitalized. (e.g: enumKey) +

    + Param case: Enum key names use hyphens to separate words, and all letters are in lowercase. (e.g: enum-key) +

    + Constant case: Enum key names are written in uppercase letters, and words are separated by underscores. (e.g: ENUM_KEY) +

    +
    +
  • -
  • + +

    + In C++, a namespace is a feature that allows you to organize your code into logical groups or containers. It helps in avoiding naming conflicts between different parts of your code and provides a way to encapsulate related code. +

    +
    +
  • -
  • + +

    + In Go, a package name is used to organize code into logical groups or containers. It serves as a namespace for the code elements within it and helps in avoiding naming conflicts. +

    +
    +
  • -
  • + +

    + In Kotlin, a package name is used to organize classes, functions, and other code elements into logical groups or containers. It helps in avoiding naming conflicts and provides a way to structure your code. +

    +
    +
  • -
  • + +

    + In PHP namespaces are used to organize code into logical groups. It helps to avoid naming conflicts and allows to use the same class names in different namespaces. +

    +
    +
  • -
  • -
  • + +

    + It indicates whether the descriptions should be included in the generated code. +

    + The default value is false. +

    +
    +
  • -
  • + +

    + In C#, a namespace is used to organize code into logical groups + and avoid naming conflicts. It provides a way to uniquely identify + classes, structs, interfaces, and other types within a project. By + specifying a namespace for the generated C# data models, you can + control their visibility and easily reference them in other parts + of your code. +

    +
    +
  • -
  • -
  • + +

    + In C#, arrays are used to store collections of elements of the + same type. The C# array type option + determines how arrays are represented in the generated C# data + models. If you choose the array type, the models will use the C# array syntax, + such as int[] or string[]. +
    +
    + Alternatively, if you choose the List type, the + models will use the List<T> class from the + System.Collections.Generic namespace, providing additional + functionality and flexibility for working with collections. +

    +
    +
  • -
  • -
  • + +

    + Auto-implemented properties in C# allow you to define properties + without explicitly writing the backing field. The compiler + automatically generates the backing field and the get/set methods + for you. When the Include auto-implemented properties option is + enabled, the generated C# data models will use this simplified + syntax for property declarations, reducing the amount of + boilerplate code you need to write. +

    +
    +
  • -
  • -
  • + +

    + In C#, the GetHashCode() method is used to generate a hash code + for an object. This method is often overridden when you need to + define custom equality comparisons or store objects in hash-based + data structures. By enabling the Include Overwrite HashCode Support option, the + generated C# data models will include support for overwriting the + GetHashCode() method, allowing you to customize the hash code + calculation based on the model's properties. +

    +
    +
  • -
  • -
  • + +

    + The Equals() method in C# is used to compare two objects for + equality. By default, it performs reference equality comparison. + However, in certain cases, you may want to override this method to + provide custom equality logic based on specific properties or + criteria. Enabling the Include Overwrite Equal Support option in the + generated C# data models includes support for overwriting the + Equals() method, allowing you to define your own equality + comparisons. +

    +
    +
  • -
  • -
  • + +

    + In C#, JSON serialization is the process of converting an object + to its JSON representation and vice versa. Enabling the Include JSON serialization option in the + generated C# data models includes the necessary attributes and + code to facilitate JSON serialization, making it easy to serialize + the models to JSON format or deserialize JSON data into instances + of the models. +

    +
    +
  • -
  • -
  • + +

    + Newtonsoft.Json (Json.NET) is a popular third-party JSON + serialization library for C#. It provides advanced features and + customization options for working with JSON data. When the Include Newtonsoft serialization option is + enabled in the generated C# data models, the necessary attributes + and code are included to support serialization and deserialization + using the Json.NET library. +

    +
    +
  • -
  • -
  • + +

    + In C#, the nullable feature allows you to explicitly indicate + whether a value type (such as int, bool, etc.) or a reference type + (such as a class) can accept null values. By enabling the Nullable option in the generated C# data models, + you allow properties to be nullable, meaning they can have a null + value in addition to their normal value range. This provides + flexibility when dealing with optional or unknown data values. +

    +
    +
  • -
  • + +

    + In Java, a package name is a way to organize and group related classes and interfaces. It is a naming convention that helps prevent naming conflicts and provides a hierarchical structure to the Java codebase. +

    + A package name is written as series of identifiers separated by dots ('.'). Each identifier represents a level in the package hierarchy. For example, a package name could be 'com.example.myapp'. +

    +
    +
  • -
  • -
  • + +

    + When you enable the "Include Jackson serialization" option, it means that the code generator will include the necessary annotations from the Jackson library in the generated code. These annotations are used to configure and control how Java objects are serialized to JSON and deserialized from JSON. +

    + Annotations in Java are represented by the @ symbol followed by the annotation name. +

    +
    +
  • -
  • -
  • + +

    + This option indicates whether the marshal and unmarshal functions would be included in the generated code or not +

    + the defalult value is false +

    + marshal - this function takes an instance of the class and return a JSON object. +

    + unmarshal - this function takes a JSON object and returns an instanve of the class. +

    +
    +
  • -
  • -
  • + +

    + This option allows you to switch between rendering collections as List type or Array. +

    + The default value is Array. +

    +
    +
  • -
  • -
  • + +

    + In Java, the "hashCode()" method is used to generate a unique numeric value (hash code) for an object. The default implementation of hashCode() in the Object class generates hash codes based on the memory address of the object, which may not be suitable for all classes. +

    + When you enable the "Include Overwrite HashCode Support" option, it means that the code generator will automatically generate a customized implementation of the hashCode() method for the class you are working with. Instead of using the default implementation. +

    +
    +
  • -
  • -
  • + +

    + In Java, the "equals()" method is used to determine if two objects are equal based on their content rather than their memory addresses. The default implementation of equals() in the Object class performs a reference equality check, meaning it only returns true if the compared objects are the same instance in memory. +

    + When you enable the "Include Overwrite Equal Support" option, it means that the code generator will automatically generate a customized implementation of the equals() method for the class you are working with. Instead of using the default implementation. +

    +
    +
  • -
  • -
  • + +

    + In Java, the "toString()" method is a built-in method defined in the Object class and inherited by all other classes. Its purpose is to provide a string representation of an object. By default, the toString() method in the Object class returns a string that includes the class name, an "@" symbol, and the hexadecimal representation of the object's hash code. +

    + When you enable the "Include Overwrite toString Support" option, it means that the code generator will automatically generate a customized implementation of the toString() method for the class you are working with. Instead of using the default implementation. +

    +
    +
  • -
  • -
  • + +

    + Enabling this option will include the description of the properties as comments in the generated code. +

    + The default value if false. +

    +
    +
  • -
  • -
  • + +

    + By using the 'javax.validation.constraints' annotations, you can ensure that the data in your Java object adheres to specific rules and constraints. This helps in validating user input, ensuring data integrity, and facilitating error handling and validation reporting. +

    +
    +