Skip to content

Commit

Permalink
refactor: Migrate the openapi-generator from oclif to yargs (#1661)
Browse files Browse the repository at this point in the history
* Add yargs options

* Fix types

* Fix typo bug in parseGeneratorOptions

* Fix config handling

* Remove oclif and cli-ux

* Improve types

* Replace parsedGeneratorOptions

* Fix tests

* Fix tests

* Revert change to cli option 'include'

* Apply coerce if not using argv

* Differentiate between GeneratorOpts and ParsedOpts

* Fix tests (hopefully)

* Revert change to options in generate-test-services

* Debug integration tests

* Add shebang

* Fix tests

* Fix typos

* Fix integration tests

* Fix tests

* Use stricter version for @SAP packages

* Generate readme

* Add note to changelog

* Use node 14 instead of 12 in GHActions

* Revert node14 to node12

* Move index.ts to cli.ts

* Rename flags.ts to options.ts
# Conflicts:
#	yarn.lock
  • Loading branch information
Florian Richter committed Oct 18, 2021
1 parent a0f64a0 commit 59be990
Show file tree
Hide file tree
Showing 25 changed files with 1,112 additions and 1,422 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -42,6 +42,7 @@ Blog: TBD<br>
## Improvements

- [generator] Include and exclude options added to the `transpileDirectory()` method
- [openapi-generator] Replace `oclif` library with `yargs`. This is a refactoring without functional changes.

## Fixed Issues

Expand Down
46 changes: 23 additions & 23 deletions STYLEGUIDE.md
Expand Up @@ -7,7 +7,7 @@ Those that are checked by lint are marked by the following symbol: ✓.
#### Table of Contents

- [Naming](#naming)
- [Use kebap case for file names](#use-kebap-case-for-file-names)
- [Use kebab case for file names](#use-kebab-case-for-file-names)
- [Use camel case for variable names ✓](#use-camel-case-for-variable-names-)
- [Use pascal case for classes ✓](#use-pascal-case-for-classes-)
- [Use pascal case for interface names and don't prefix them](#use-pascal-case-for-interface-names-and-dont-prefix-them)
Expand Down Expand Up @@ -45,9 +45,9 @@ Those that are checked by lint are marked by the following symbol: ✓.

## Naming

### Use kebap case for file names
### Use kebab case for file names

Use kebap case for all file names and directories, except for generated files and markdown files, that are not in the knowledge base.
Use kebab case for all file names and directories, except for generated files and markdown files, that are not in the knowledge base.

❌ Examples of **incorrect** code:

Expand All @@ -65,7 +65,7 @@ some_dir / some_class.ts;
✅ Examples of **correct** code:

```ts
/* Use kebap case */
/* Use kebab case */
some-dir/some-class.ts

/* Exceptions apply for generated files and some markdown files */
Expand Down Expand Up @@ -122,7 +122,7 @@ class FooBar {
### Use pascal case for interface names and don't prefix them

Pascal case is common in most JavaScript/TypeScript projects for interfaces.
Don't prefix interfaces with the hungarian notation 'I' (or other prefixes).
Don't prefix interfaces with the Hungarian notation 'I' (or other prefixes).
If you have a class with the same name as an interface, consider a more general name for the interface or a more specific name for the class - if they are different things it should be possible to name them differently.

❌ Examples of **incorrect** code:
Expand Down Expand Up @@ -200,7 +200,7 @@ function parseJson() { ... }

Every function should do something and that action should be described with a verb.
The verb should fit the return type and value.
An exception to this can be methods, that operate on an instance directly, e. g. `instance.toString()`, `instance.asObject()`.
An exception to this can be methods, that operate on an instance directly, e.g. `instance.toString()`, `instance.asObject()`.

❌ Examples of **incorrect** code:

Expand Down Expand Up @@ -253,7 +253,7 @@ class FooBar {

### Use single quotes ✓

Use single quotes, unless not possible otherwise, e. g. when your string contains single quotes.
Use single quotes, unless not possible otherwise, e.g. when your string contains single quotes.

❌ Examples of **incorrect** code:

Expand Down Expand Up @@ -301,7 +301,7 @@ const foo = `foo ${fn(bar + 'bar')}`;
### Use `.forEach` and other array functions rather than `for`
Use the functional language concepts of JavaScript in favor of the imperative ones, when possible.
Use the correct function for your use case (e. g. `.map`, `.reduce`, `.filter`, `.find`, `.some`, `.every`).
Use the correct function for your use case (e.g. `.map`, `.reduce`, `.filter`, `.find`, `.some`, `.every`).
In some cases it makes sense to resort to the imperative `for`, for example, when performance is of the essence, if you have to iterate over every n-th element or if you want to execute asynchronous actions sequentially.
Be aware of the effects of asynchronicity.
The callback passed to `.forEach` is invoked for every item of a list sequentially.
Expand Down Expand Up @@ -395,7 +395,7 @@ function foo(obj: SomeType | undefined) {
### Use `null` for intentional explicit absence of values or if it is part of an external API
If a value can both be non-existent and intentionally absent and those states are semantically different it may make sense to allow the usage of `null`.
Those cases should however be rather rare and are more common when calling external APIs, e. g. through HTTP requests.
Those cases should however be rather rare and are more common when calling external APIs, e.g. through HTTP requests.
Consider whether there is a better API design that might avoid this.
❌ Examples of **incorrect** code:
Expand Down Expand Up @@ -425,45 +425,45 @@ function foo(obj: SomeType | null | undefined) {
### Use truthy/falsy checks where possible
In most cases it is possible to check for truthiness/falsiness instead of explicitly comparing values.
This should be used when possible, but carefully considered in cases where falsy values are valid and therefore semantically truthy values, e. g. 0, ''.
This should be used when possible, but carefully considered in cases where falsy values are valid and therefore semantically truthy values, e.g. 0, ''.
Therefore, when checking for existence of primitives, don't use truthy/falsy checks.
Of course, more fine granular checks should be applied if semantically needed.
❌ Examples of **incorrect** code:
```ts
/* Don't use explicit comparison with `undefined` for objects */
if(obj !== undefined) { ... }
if (obj !== undefined) { ... }

/* Don't use truthy/falsy checks for existence of primitives */
function checkIfExist(obj: string | number) {
if(obj) { ... }
if (obj) { ... }
}

/* Don't use explicit comparison for array length (or other numbers)*/
if(arr.length !== 0) { ... }
if (arr.length !== 0) { ... }

/* Don't use explicit comparison for booleans */
if(isFoo !== false) { ... }
if (isFoo !== false) { ... }

/* Don't use explicit comparison when checking for empty string */
if(someString !== '') { ... }
if (someString !== '') { ... }
```
✅ Examples of **correct** code:
```ts
/* Use truthy/falsy check for objects */
if(obj) { ... }
if (obj) { ... }

/* Use truthy/falsy check for array length (or other numbers)*/
if(arr.length) { ... }
if (arr.length) { ... }

/* Use truthy/falsy for booleans */
if(!isFoo) { ... }
if (!isFoo) { ... }

/* Use truthy/falsy check when checking for empty string */
if(someString) { ... }
if (someString) { ... }
```
## White space
Expand All @@ -483,7 +483,7 @@ arr.forEach(item => {

/* Don't use tabs */
arr.forEach(item => {
const property = item.property;
const property = item.property;
});
```
Expand Down Expand Up @@ -556,7 +556,7 @@ There should be no empty lines in between, except if it is part of the descripti
### Use `@deprecated` tag for deprecation
When deprecating public API, this is done through the TypeDoc comments.
The first line of the comment should start with `@deprecated` followed by a note mentioning since which version this is deprecated (e. g. `Since v1.0.0.`) and a note of what to use instead (or alternatively that it won't be replaced).
The first line of the comment should start with `@deprecated` followed by a note mentioning since which version this is deprecated (e.g. `Since v1.0.0.`) and a note of what to use instead (or alternatively that it won't be replaced).
❌ Examples of **incorrect** code:
Expand Down Expand Up @@ -616,7 +616,7 @@ The description should end with a full stop.
*/
```
### Use @returns if a function has a return value ✓
### Use `@returns` if a function has a return value ✓
Functions that return something should have an `@returns` statement in the documentation, followed by a description of the return value.
The description should end with a full stop.
Expand Down Expand Up @@ -827,7 +827,7 @@ arr.forEach(item => {
### Use function declarations to reference functions by name
Arrow functions require less boilerplate code than function declarations, especially if the function returns something directly, e. g. in one-liners.
Arrow functions require less boilerplate code than function declarations, especially if the function returns something directly, e.g. in one-liners.
For more complex functions, there is no significant difference.
Arrow functions cannot be named and therefore have to be assigned to variables - much like function expressions.
Function declarations are visually easier to differentiate from other variables than functions assigned to variables.
Expand Down
6 changes: 3 additions & 3 deletions knowledge-base/adr/0027-versioning-strategy.md
Expand Up @@ -23,14 +23,14 @@ We will keep this approach because:
- It is very simple to have a fixed version for all packages.
No need to monitor which packages have been changes to which extent.
- It is easy to use/install the SDK, because all SDK parts have the same version.
- It is done the same way by other monorepos like [nest](https://github.com/nestjs/nest) or [anguar](https://github.com/angular/angular).
- It is done the same way by other monorepos like [nest](https://github.com/nestjs/nest) or [angular](https://github.com/angular/angular).

The drawback of having new version without changes is taken into account for the simplicity.

## Decision Clients

For the clients the situation is much less coupled than for core.
Some services will update every two weeks (workflow) other every year (S/4 OnPremise).
Some services will update every two weeks (workflow) other every year (SAP S/4HANA OnPremise).
We will do versioning in the following way:

- Major versions of clients aligns with major version of core.
Expand All @@ -40,7 +40,7 @@ We will do versioning in the following way:
- Pipeline runs every two weeks and publishes only the changed clients with increased minor version.
- Errors on the client layer are rare and in such a case we trigger a bump of all affected clients.

This approach challenges the current release practice to a higer degree of automation.
This approach challenges the current release practice to a higher degree of automation.

## Consequences

Expand Down
2 changes: 1 addition & 1 deletion packages/generator/package.json
Expand Up @@ -38,7 +38,7 @@
"@sap-cloud-sdk/core": "^1.50.0",
"@sap-cloud-sdk/generator-common": "^1.50.0",
"@sap-cloud-sdk/util": "^1.50.0",
"@sap/edm-converters": "^1.0.21",
"@sap/edm-converters": "~1.0.21",
"@types/fs-extra": "^9.0.1",
"@types/glob": "^7.1.2",
"execa": "^5.0.0",
Expand Down
145 changes: 75 additions & 70 deletions packages/openapi-generator/README.md
Expand Up @@ -14,87 +14,92 @@ This generator is based on the [OpenAPI Tools generator](https://openapi-generat
$ npm install @sap-cloud-sdk/openapi-generator
```

## Usage (CLI)
To run the CLI locally, compile and link the package.

<!-- prettier-ignore-start -->
<!-- commands -->
* [`generate-openapi-client --input <input> --outputDir <outputDirectory>`](#generate-openapi-client---input-input---outputdir-outputdirectory)
```bash
$ yarn install

## `generate-openapi-client --input <input> --outputDir <outputDirectory>`
$ yarn compile

Generate OpenAPI client(s), that use the connectivity features of the SAP Cloud SDK for JavaScript/TypeScript.
$ npm link

$ openapi-generator help
```
USAGE
$ generate-openapi-client --input <input> --outputDir <outputDirectory>
OPTIONS
-c, --config=<path/to/config.json>
Set the path to a file containing the options for generation instead of setting the options on the command line.
When combining the `config` option with other options on the command line, the command line options take precedence.
If a directory is passed, a `config.json` file is read from this directory.
-i, --input=<path/to/input>
(required) Specify the path to the directory or file containing the OpenAPI service definition(s) to generate
clients for. Accepts Swagger and OpenAPI definitions as YAML and JSON files. Throws an error if the path does not
exist.
-o, --outputDir=<path/to/output>
(required) Specify the path to the directory to generate the client(s) in. Each client is generated into a
subdirectory within the given output directory. Creates the directory if it does not exist. Customize subdirectory
naming through `--optionsPerService`.
-t, --transpile
Transpile the generated TypeScript code. When enabled a default `tsconfig.json` will be generated and used. It emits
`.js`, `.js.map`, `.d.ts` and `.d.ts.map` files. To configure transpilation set `--tsconfig`.
--clearOutputDir
Remove all files in the output directory before generation. Be cautious when using this option, as it really removes
EVERYTHING in the output directory.
--include=<glob/to/include>
Include files matching the given glob into the root of each generated client directory.
--optionsPerService=<path/to/options-per-service.json>
Set the path to a file containing the options per service. The configuration allows to set a `directoryName` and
`packageName` for every service, identified by the path to the original file. It also makes sure that names do not
change between generator runs. If a directory is passed, a `options-per-service.json` file is read/created in this
directory.

--overwrite
Allow to overwrite files, that already exist. This is useful, when running the generation regularly.
--packageJson
When enabled, a `package.json`, that specifies dependencies and scripts for transpilation and documentation
generation is generated.
--skipValidation
By default, the generation fails, when there are duplicate or invalid names for operations and/or path parameters
after transforming them to camel case. Set this to true to enable unique and valid name generation. The names will
then be generated by appending numbers and prepending prefixes.
--tsConfig=<path/to/tsconfig.json>
Replace the default `tsconfig.json` by passing a path to a custom config. By default, a `tsconfig.json` is only
generated, when transpilation is enabled (`--transpile`). If a directory is passed, a `tsconfig.json` file is read
from this directory.
--verbose
Turn on verbose logging.
EXAMPLES
## Usage (CLI)

// generate TypeScript clients from OpenAPI definitions in a directory
$ openapi-generator --input ./my-specs --outputDir ./clients
Generate OpenAPI client(s), that use the connectivity features of the SAP Cloud SDK for JavaScript/TypeScript.

// generate a JavaScript client from a OpenAPI definition file
$ openapi-generator --input ./my-spec.yaml --outputDir ./client --transpile
<!-- commands -->
<!-- This block is inserted by generate-readme.ts. Do not adjust it manually. -->
```
Usage: openapi-generator --input <input> --outputDir <outputDirectory>
Options:
--help Show help [boolean]
--version Show version number [boolean]
-i, --input Specify the path to the directory or file containing
the OpenAPI service definition(s) to generate clients
for. Accepts Swagger and OpenAPI definitions as YAML
and JSON files. Throws an error if the path does not
exist. [string] [required]
-o, --outputDir Specify the path to the directory to generate the
client(s) in. Each client is generated into a
subdirectory within the given output directory.
Creates the directory if it does not exist. Customize
subdirectory naming through `--optionsPerService`.
[string] [required]
-t, --transpile Transpile the generated TypeScript code. When enabled
a default `tsconfig.json` will be generated and used.
It emits `.js`, `.js.map`, `.d.ts` and `.d.ts.map`
files. To configure transpilation set `--tsconfig`.
[boolean] [default: false]
--include Include files matching the given glob into the root
of each generated client directory. [string]
--overwrite Allow to overwrite files, that already exist. This is
useful, when running the generation regularly.
[boolean] [default: false]
--clearOutputDir Remove all files in the output directory before
generation. Be cautious when using this option, as it
really removes EVERYTHING in the output directory.
[boolean] [default: false]
--skipValidation By default, the generation fails, when there are
duplicate or invalid names for operations and/or path
parameters after transforming them to camel case. Set
this to true to enable unique and valid name
generation. The names will then be generated by
appending numbers and prepending prefixes.
[boolean] [default: false]
--tsConfig Replace the default `tsconfig.json` by passing a path
to a custom config. By default, a `tsconfig.json` is
only generated, when transpilation is enabled
(`--transpile`). If a directory is passed, a
`tsconfig.json` file is read from this directory.
[string]
--packageJson When enabled, a `package.json`, that specifies
dependencies and scripts for transpilation and
documentation generation is generated.
[boolean] [default: false]
-v, --verbose Turn on verbose logging. [boolean] [default: false]
--optionsPerService Set the path to a file containing the options per
service. The configuration allows to set a
`directoryName` and `packageName` for every service,
identified by the path to the original file. It also
makes sure that names do not change between generator
runs. If a directory is passed, a
`options-per-service.json` file is read/created in
this directory. [string]
-c, --config Set the path to a file containing the options for
generation instead of setting the options on the
command line. When combining the `config` option with
other options on the command line, the command line
options take precedence. If a directory is passed, a
`config.json` file is read from this directory.
[string]
```

_See code: [dist/cli/index.ts](https://github.com/SAP/cloud-sdk-js/blob/v1.50.0/dist/cli/index.ts)_
<!-- commandsstop -->
<!-- prettier-ignore-end -->

## Usage (programatically)
## Usage (programmatically)

```ts
import { generate } from '@sap-cloud-sdk/openapi-generator';
Expand Down
16 changes: 0 additions & 16 deletions packages/openapi-generator/bin/run

This file was deleted.

3 changes: 0 additions & 3 deletions packages/openapi-generator/bin/run.cmd

This file was deleted.

0 comments on commit 59be990

Please sign in to comment.