@team-supercharge/oasg
v14.1.0
Published
Node-based tool to lint OpenAPI documents and generate clients, servers and documentation from them
Downloads
436
Maintainers
Keywords
Readme
OASg - Open Api Spec generator
Design APIs in OpenAPI 3.0 format, lint them, and generate client/server packages.
Getting Started
Required tools
For using the tool you need wget
, jq
and java
pre-installed. The required dependencies and OASg itself is preinstalled in a Docker image distributed in the registry.gitlab.com/team-supercharge/oasg
registry with every new release of the project.
Initialize API repo
Create a new repository for your API service, and add a package.json
like the following example and run npm install
.
{
"name": "@example/api",
"private": true,
"version": "0.0.0",
"description": "API client generator service for Example",
"scripts": {},
"repository": {
"type": "git",
"url": "[email protected]:misc/oasg-example.git"
},
"dependencies": {
"@team-supercharge/oasg": <insert-latest-version>
}
}
Create config.json
In your API service repository, create a config.json
file, for which the structure needs to be the following:
{
"sources": [
{ source-item }
],
"targets": [
{ target-item }
],
}
For detailed configuration instructions please refer to the Configuration section below.
Configure Linter
Create a .spectral.js
file in the repo's root directory with the following minimal content:
import oasgRuleset from '@team-supercharge/oasg/ruleset';
export default {
extends: oasgRuleset
};
The file is used for configuring Spectral on a per-project basis and will enable usage of the base OASg ruleset and enables to add project-specific rules as well. For detailed instructions on how to use custom rules refer to the Linter rules section below.
⚠️ The YAML ruleset format is highly discouraged to be used, as it won't work seamlessly when being used with Docker.
Use with Docker
Each release of OASg is also distributed as a Docker image with the respective version of the NPM package preinstalled. You can use the registry.gitlab.com/team-supercharge/oasg
image and simply run the oasg
command in the running container.
Full example with GitLab CI:
swaggerlint:
image: registry.gitlab.com/team-supercharge/oasg:<version>
stage: check
script:
- oasg lint
If no other dependency is needed for the API project being built, there is no need to run any
npm install
ornpm ci
commands before invokingoasg
Usage
lint
Lints the API specification file of the specified target using Spectral. If no target specified, all targets will be linted.
$ npx oasg lint [source]
serve
Bundles the specified source and serves with Swagger UI, hooked up internally with a local proxy server to circumvent CORS limitations.
$ npx oasg serve [source]
proxy
Fires up a Prism validation proxy server which can be used to interactively debug and validate that a remote server's responses are in line with the defined source specification.
$ npx oasg proxy [source] --server
or
$ npx oasg proxy [source] -s
generate
Generates the API client package of the specified target. If no target specified, all targets will be generated.
$ npx oasg generate [target]
publish
Publishes the generated API client package of the specified target. If no target specified, all targets will be published.
$ npx oasg publish [target]
Linter Rules
OASg makes use of the awesome Spectral project to provide linting capabilities and comes with a set of more strict default rules we call the OASg Ruleset which is defined in the file ruleset/ruleset.js and exported as @team-supercharge/oasg/ruleset
for the outside world.
The project's .spectral.js
file in the API repository should be always configured to extend the default OASg Ruleset using the methods described in the Configure linter section.
Rules defined in the ruleset can be split into two categories:
- default rules - rules that are enabled by default, can be disabled with the
rule-name: off
syntax - opt-in rules - rules that need to be explicitly enabled with the
rule-name: true
syntax
You can further customize the ruleset in .spectral.js
according to the documentation using the rules:
property.
An example configuration can be found here:
import oasgRuleset from '@team-supercharge/oasg/ruleset';
import { truthy } from '@stoplight/spectral-functions';
export default {
extends: oasgRuleset,
rules: {
'oasg-object-names-pascal-case': false, // disables a default rule - don't do this in general :)
'oasg-object-names-api-model-suffix': true, // enables a non-default rule
'oasg-path-casing-kebab': false, // switches a default rule to another one
'oasg-path-casing-pascal': true,
'my-rule-name': { // adds a fully custom rule which applies to only your project
description: 'Tags must have a description.',
given: '$.tags[*]',
severity: 'error',
then: {
field: 'description',
function: truthy
}
}
extends: '@team-supercharge/oasg/ruleset'
rules:
oasg-object-names-pascal-case: off # disables a default rule - don't do this in general :)
oasg-object-names-api-model-suffix: true # enables a non-default rule
oasg-path-casing-kebab: off # switches a default rule to another one
oasg-path-casing-pascal: true
my-rule-name: # adds a fully custom rule which applies to only your project
description: Tags must have a description.
given: $.tags[*]
severity: error
then:
field: description
function: truthy
Custom Rules
The following rules are defined in the custom OASg Ruleset.
⚠️ From the rules in the same group only one can be enabled at a time as they are colliding with eachother. Please turn off the default one and enable the other if you intend to change the default behaviour.
| Group | Rule | Default | Description |
|-|-|-|-|
| | oasg-object-names-pascal-case
| Y | Every object defined in the spec (schemas, requests, responses) shoud be PascalCased
, as they are most likely to be converted into classes / enums / objects during code generation |
| | oasg-object-names-api-model-suffix
| | makes sure every schema, request, response has the ApiModel
suffix (used to avoid naming collision) |
| | oasg-operation-ids-camel-case
| Y | The operationId
properties for paths should be camelCased
, as they are converted to class methods during code generation |
| path casing | oasg-path-casing-kebab
| Y | enforces kebab-casing
for path segments |
| path casing | oasg-path-casing-snake
| | enforces snake_casing
for path segments |
| path casing | oasg-path-casing-camel
| | enforces camelCasing
for path segments |
| path casing | oasg-path-casing-pascal
| | enforces PascalCasing
for path segments |
| property casing | oasg-property-casing-kebab
| | enforces kebab-casing
for property names |
| property casing | oasg-property-casing-snake
| | enforces snake_casing
for property names |
| property casing | oasg-property-casing-camel
| Y | enforces camelCasing
for property names |
| property casing | oasg-property-casing-pascal
| | enforces PascalCasing
for property names |
Custom Functions
Custom functions in project configuration can be only used with using the JavaScript Ruleset Format supported by Spectral. The functions can be imported from @team-supercharge/oasg/functions
.
schemaEnumeration
The function enables to verify a value against a set of enumeration values defined in a schema.
Function parameters:
schema
- Name of the schema to be validated against, must containenum
definitionfile
- (optional) YAML file withcomponents.schemas
defined, otherwise the currently linted documenet is used
Example usage in a custom project ruleset:
import oasgRuleset from '@team-supercharge/oasg/ruleset';
import { schemaEnumeration } from '@team-supercharge/oasg/functions'
export default {
extends: oasgRuleset,
rules: {
'empire-valid-permissions': {
recommended: true,
type: 'style',
severity: 'error',
message: '{{error}}',
description: 'Property x-permissions should use values from the Permission enum',
given: '$.paths.*.*.x-permissions[*]',
then: {
function: schemaEnumeration,
functionOptions: {
file: './api/common.yaml',
schema: 'Permission'
}
}
},
}
};
Template Customization
Using the comming templateDir
config parameter there is a possibility to customize the templates used during generation.
OASg offers two levels of customization:
The "OASg level" customizations can be placed for every target in OASg's source code itself in the targets/{targetId}/templates
directory. This level can be useful for:
- adding common functionality which are to be used across every project using OASg
- fixing bugs/problems in output of the specific version of OpenAPI Generator
The "project level" customization can be configured using the templateDir
parameter for any Target
- if you specify a directory there, the contents of it will be copied over the templates from the previous level
⚠️ At any level if you want to introduce a customized template, always make sure you start from the right version:
- for OASG level customizations always theck the version field in
DEFAULT_GENERATOR_MAPPING
for your selected Target and copy the original template from the right tag!- for project level customizations check first if the selected template is already customized on OASG level, in that case copy the template from the OASg source code
Configuration
Source
The OASg tool distinguish 2 kinds of source types.
Common source parameters
|Parameter| Description| Required | Default |
|-|-|-|-|
| id | Unique identifier | Y | - |
| type | Source type: simple
/ merged
| N | simple
|
| bundle | Bundle specification into a single file | N | true
|
| sortSchemas | Sort components.schemas
alphabetically | N | true
|
| decorators | Array of files for decorator functions | N | []
|
| cleanup | Cleans specification from unused paths, tags and schemas | N | true
|
| overrides | Override properties of the OpenApi file | N | - |
The source specification is by default bundled into a single file (resolving external dependencies) using the @redocly/cli package's bundle
command.
⚠️ It is higly recommended to keep
bundle
on if you plan to use theopenapi
target type, as external refs won't be part of the target artifact.
Decorator files must export a decorate(document)
function which transforms the parsed OpenAPI document and returns it at the end of the function.
Full example with decorators:
{
"id": "platform-api",
"type": "merged",
"inputs": [
"api/*.openapi.yaml"
],
"bundle": false,
"sortSchemas": false,
"decorators": ["decorators/one", "decorators/two"],
"cleanup": false
}
// decorators/one.js
function decorate(document) {
document.info.title = 'My Custom Decorated Title';
return document;
}
exports.decorate = decorate;
After the decorators have run, the specification is by default cleaned up (can be turned off by setting the "cleanup": false
option):
paths
with no methods in them are removedtags
with no endpoints using them are removedcomponents
that are unused are removed (only ifbundle
option is also enabled)
Source Types
Simple
A single file can be used as an input.
{
"id": "source-simple",
"type": "simple",
"input": "api/swagger1.yaml",
}
|Parameter| Description| Required | Default |
|-|-|-|-|
| input | Path of the OpenApi specification file | N | api/openapi.yaml
|
Merged
More files are merged into a single OpenApi specification file and used as an input. The files are merged in the order they are defined in the inputs
array. Take care during naming of the schemas, as they are merged into a single namespace.
Glob patterns are supported.
{
"id": "source-merged",
"type": "merged",
"inputs": [
"api/swagger1.yaml",
"api/swagger/*.yaml"
]
}
|Parameter| Description| Required | Default | |-|-|-|-| | inputs | Array of paths of specification files or globs | Y | - |
Overrides
The following sections can be overridden: info
, externalDocs
, license
and contact
.
It does not override but replace the values of the OpenApi Specification with the corresponding values of the config.json
.
You can check here which values are required.
"overrides": {
"info": {
"title": "Overridden Frontend API",
"description": "Overridden Frontend Merged API Description",
"termsOfService": "Overridden Terms Of Service",
"version": "1.0.2"
},
"externalDocs": {
"description": "Overridden externalDocs",
"url": "https://supercharge.io"
},
"license": {
"name": "Overridden License"
},
"contact": {
"name": "Overridden Contact",
"url": "https://supercharge.io",
"email": "[email protected]"
}
}
Target
Common target parameters
|Parameter| Description| Required | Default | |-|-|-|-| | id | Unique identifier | Y | - | | type | Platform identifier | Y | - | | generatorId | Code generator identifier: it defines the specific type of generator | N | default | | source | Identifier of the source object | N | default | | generator | OpenApi Generator: it can be a released version or a http(s) URL | N | 4.3.1 | | templateDir | Path for customized OpenAPI Generator templates | N | - |
Target Types
angular
{
"id": "client-angular",
"type": "angular",
"source": "source-simple",
"packageName": "@project/oasg-example-angular",
"repository": "https://gitlab.supercharge.io/api/v4/projects/1226/packages/npm/"
}
|Parameter| Description| Required | Default | |-|-|-|-| | packageName | Name of the generated NPM package | Y | - | | repository | URL of the NPM package registry | Y | - |
Known issue: breaking dependencies
The Angular target has a known issue related to dependency versioning. The generated Angular project's package.json
currently defines multiple dependencies with flexible versions (e.g., using ^
or ~
in version constraints). This flexibility allows newer versions of dependencies (not to mention the transitive dependencies), to be pulled in, which can occasionally lead to breaking changes.
A notable instance of this issue occurred with Angular version 12, which introduced changes that broke the build of generated projects. To address this specific case, we implemented a temporary fix in the targets/angular/generate.sh
script. This script now manually installs problematic dependencies with fixed, validated versions.
Long-Term Solution
We are actively discussing a long-term solution to this issue. Potential approaches include implementing dependency version locking mechanisms (package-lock.json
) per Angular versions.
The temporary fix may not cover all future breaking changes from other dependencies. Projects using different versions of Angular may encounter issues if the fix does not align with their specific requirements.
We welcome feedback and contributions to help address this issue.
react
{
"id": "client-react",
"type": "react",
"source": "source-merged",
"packageName": "@project/oasg-example-react-native",
"repository": "https://gitlab.supercharge.io/api/v4/projects/1226/packages/npm/"
}
|Parameter| Description| Required | Default | |-|-|-|-| | packageName | Name of the generated NPM package | Y | - | | repository | URL of the NPM package registry | Y | - |
stubby
When using Stubby, you must use the Supercharge's fork of the OpenApi Generator!
{
"id": "client-stubby",
"type": "stubby",
"source": "source-merged",
"generateWithDocker": "true",
"repository": "registry.supercharge.io/misc/oasg-example"
}
|Parameter| Description| Required | Default | |-|-|-|-| | repository | URL of the Docker registry | N | - | | generateWithDocker | Generate with docker | Y | - |
spring
Generates and published a Kotlin server side SDK using the JavaSpring
OpenAPI Generator.
{
"id": "project-server",
"source": "source-merged",
"type": "spring",
"artifactId": "project-api",
"groupId": "com.project.api",
"basePackage": "com.project.api",
"mavenRepoUrl": "https://your-private-repo-url.com",
"generatorCustomArgs": "--model-name-suffix=Dto"
}
|Parameter| Description| Required | Default |
|-|-|-|-|
| artifactId | Maven artifact identifier | Y | - |
| groupId | Maven group identifier | Y | - |
| basePackage | Name of the base Java package, model and api packages will be added under this one | Y | - |
| mavenRepoUrl | URL of the Maven repository to publish the artifacts to | Y | - |
| generatorCustomArgs | Pass-through OpenAPI Generator parameters, e.g.: --model-name-suffix=Dto
| N | - |
spring-kotlin
Generates and published a Kotlin server side SDK using the kotlin-spring
OpenAPI Generator.
{
"id": "project-server",
"source": "source-merged",
"type": "spring-kotlin",
"artifactId": "project-api",
"groupId": "com.project.api",
"basePackage": "com.project.api",
"mavenRepoUrl": "https://your-private-repo-url.com",
"generatorCustomArgs": "--model-name-suffix=Dto"
}
|Parameter| Description| Required | Default |
|-|-|-|-|
| artifactId | Maven artifact identifier | Y | - |
| groupId | Maven group identifier | Y | - |
| basePackage | Name of the base Java package, model and api packages will be added under this one | Y | - |
| mavenRepoUrl | URL of the Maven repository to publish the artifacts to | Y | - |
| generatorCustomArgs | Pass-through OpenAPI Generator parameters, e.g.: --model-name-suffix=Dto
| N | - |
feign
Generates and published a Kotlin server side SDK using the JavaSpring
OpenAPI Generator with the spring-cloud
library.
{
"id": "project-client",
"source": "source-merged",
"type": "feign",
"artifactId": "project-client",
"groupId": "com.project.client",
"basePackage": "com.project.client",
"mavenRepoUrl": "https://your-private-repo-url.com",
"generatorCustomArgs": "--model-name-suffix=Dto"
}
|Parameter| Description| Required | Default |
|-|-|-|-|
| artifactId | Maven artifact identifier | Y | - |
| groupId | Maven group identifier | Y | - |
| basePackage | Name of the base Java package, model and api packages will be added under this one | Y | - |
| mavenRepoUrl | URL of the Maven repository to publish the artifacts to | Y | - |
| generatorCustomArgs | Pass-through OpenAPI Generator parameters, e.g.: --model-name-suffix=Dto
| N | - |
feign-kotlin
TBD
android
{
"id": "client-android",
"type": "android",
"source": "source-merged",
"packageName": "io.supercharge.oasg.example",
"groupId": "io.supercharge.oasg.example",
"artifactId": "client",
"generatorCustomArgs": "--model-name-suffix=ApiModel",
"formatter": "0.39.0",
"formatterCustomArgs": "--disabled_rules=no-wildcard-imports,max-line-length",
"repository": "https://gitlab.supercharge.io/api/v4/projects/1226/packages/maven"
}
|Parameter| Description| Required | Default |
|-|-|-|-|
| packageName | Java package name of the generated client | Y | - |
| groupId | Generated artifact package's organization | Y | - |
| artifactId | Generated artifact id | Y | - |
| generatorCustomArgs | Custom arguments of the generator | N | - |
| formatter | ktlint
: it can be a released version or a http(s) url | N | 0.39.0 |
| formatterCustomArgs | Custom arguments of the ktlint
formatter | N | --disabled_rules=no-wildcard-imports,max-line-length |
| repository | URL of the Maven Repository | N | - |
ios
{
"id": "client-ios",
"type": "ios",
"generatorId": "swift5",
"source": "source-merged",
"projectName": "OASgExample",
"repository": "[email protected]:example/openapi-generator-source.git",
"interfaceType": "Combine",
"generatorCustomArgs": "--model-name-suffix=ApiModel"
}
|Parameter| Description| Required | Default |
|-|-|-|-|
| projectName | Name of the project | Y | - |
| repository | URL of the generated client api code repository | Y | - |
| interfaceType | Response type of the generated client: Combine
/ Result
/ RxSwift
/ AsyncAwait
/ PromiseKit
| Y | - |
| generatorCustomArgs | Custom arguments of the generator | N | - |
flutter
{
"id": "client-flutter",
"type": "flutter",
"source": "source-merged",
"packageName": "OASgExample",
"repository": "[email protected]:example/openapi-generator-source.git",
"generatorCustomArgs": "--model-name-suffix=ApiModel"
}
|Parameter| Description| Required | Default | |-|-|-|-| | packageName | Name of the package | Y | - | | repository | URL of the generated client api code repository | Y | - | | generatorCustomArgs | Custom arguments of the generator | N | - |
kmp
{
"id": "client-kmp",
"type": "kmp",
"source": "source-merged",
"packageName": "io.supercharge.oasg.example",
"groupId": "io.supercharge.oasg.example",
"artifactId": "client",
"generatorCustomArgs": "--model-name-suffix=ApiModel",
"formatter": "1.0.0",
"formatterCustomArgs": "--disabled_rules=no-wildcard-imports,max-line-length,enum-entry-name-case",
"repository": "https://gitlab.supercharge.io/api/v4/projects/1226/packages/maven"
}
|Parameter| Description| Required | Default |
|-|-|-|-|
| packageName | Kotlin package name of the generated client | Y | - |
| groupId | Generated artifact package's organization | Y | - |
| artifactId | Generated artifact id | Y | - |
| generatorCustomArgs | Custom arguments of the generator | N | - |
| formatter | ktlint
: it can be a released version or a http(s) url | N | 1.0.0 |
| formatterCustomArgs | Custom arguments of the ktlint
formatter | N | --disabled_rules=no-wildcard-imports,max-line-length,enum-entry-name-case |
| repository | URL of the Maven Repository | N | - |
python
{
"id": "client-python",
"type": "python",
"source": "source-merged",
"packageName": "oasg_example",
"repositoryUrl": "https://gitlab.supercharge.io/api/v4/projects/1226/packages/pypi"
}
|Parameter| Description| Required | Default | |-|-|-|-| | packageName | Package nem for the project (convention: snake_case) | Y | - | | repositoryUrl | URL of the PyPI repository | Y | - |
Publishing the PyPI packages is done with Twine. For authentication againts the PiPI repository you need to set the TWINE_USERNAME
and TWINE_PASSWORD
environment variables.
python-fastapi
{
"id": "server-python",
"type": "python-fastapi",
"source": "source-merged",
"packageName": "oasg_example",
"repositoryUrl": "https://gitlab.supercharge.io/api/v4/projects/1226/packages/pypi"
}
|Parameter| Description| Required | Default | |-|-|-|-| | packageName | Package nem for the project (convention: snake_case) | Y | - | | repositoryUrl | URL of the PyPI repository | Y | - |
Building the distribution package requires Flit.
Publishing the PyPI packages is done with Twine. For authentication againts the PiPI repository you need to set the TWINE_USERNAME
and TWINE_PASSWORD
environment variables.
python-fastapi-raw-request
{
"id": "server-python",
"type": "python-fastapi-raw-request",
"source": "source-merged",
"packageName": "oasg_example",
"repositoryUrl": "https://gitlab.supercharge.io/api/v4/projects/1226/packages/pypi"
}
|Parameter| Description| Required | Default | |-|-|-|-| | packageName | Package nem for the project (convention: snake_case) | Y | - | | repositoryUrl | URL of the PyPI repository | Y | - |
Building the distribution package requires Flit.
Publishing the PyPI packages is done with Twine. For authentication againts the PiPI repository you need to set the TWINE_USERNAME
and TWINE_PASSWORD
environment variables.
contract-testing
{
"id": "example-project-contract-testing",
"source": "example-project-api",
"type": "contract-testing",
"packageName": "@example-project/api-test",
"repository": "https://gitlab.supercharge.io/api/v4/projects/1377/packages/npm/"
}
|Parameter| Description| Required | Default | |-|-|-|-| | packageName | Package nem for the project | Y | - | | repositoryUrl | URL of the PyPI repository | Y | - |
Client usage:
# install test dependencies
npm install --save-dev [email protected] [email protected] [email protected] [email protected] [email protected] @types/[email protected] @types/[email protected]
add tsconfig for tests (tsconfig.api-tests.json):
{
"compilerOptions": {
"resolveJsonModule": true,
"esModuleInterop": true,
"module": "commonjs"
}
}
Generated package contains 2 main thing:
- generated http requests
- schema validator with request and response models
Known issues:
- openapi-typescript-validator-ext-ref is a fork, should use the main package after external ref support PR is merged: https://github.com/Q42/openapi-typescript-validator/issues/11
- Currently external $refs are resolved by copying its value to the main document -> no schema validators are generated for imported common open api schema definitions
- there are some monkey patch (contract-testing/monkey-patch.sh) for
typescript-node
andopenapi-typescript-validator
which could be fixed in original package
Example test
// auth.test.ts
import { describe, it } from 'mocha';
import { expect } from 'chai';
import { AuthApi, SLATypeEnumApiModel, example-projectErrorTypeEnumApiModel, UserTypeEnumApiModel, schemaValidator } from '@example-project/api-test'; // <---- generated models, validators are accessible through `schemaValidator` object
export const authApi = new AuthApi('https://backend.example.com/api');
describe('Auth', function () {
it('login', async () => {
const loginResponse = (
await authApi.loginStart({
contractNumber: '',
userType: UserTypeEnumApiModel.Personal,
birthDate: '',
})
).body;
// schema validation
schemaValidator.StartLoginResponseApiModelDecoder.decode(loginResponse);
// property value validation
expect(loginResponse.slaType).to.be.equal(SLATypeEnumApiModel.SmsOtp);
expect(loginResponse.secondaryAuthenticationMethod).to.be.equal(SLATypeEnumApiModel.ZipCode);
});
});
# package.json scripts
"scripts": {
"api-test:all": "TS_NODE_PROJECT=tsconfig.api-tests.json mocha --timeout 10000 --reporter spec -r ts-node/register ./api-tests/tests/*.ts",
"api-test:all:html": "TS_NODE_PROJECT=tsconfig.api-tests.json mocha --timeout 10000 --reporter spec --reporter mocha-simple-html-reporter --reporter-options output=./api-tests/report/contract-test-report-$(date +%F_%H-%M).html -r ts-node/register ./api-tests/tests/*.ts",
"api-test:feature": "TS_NODE_PROJECT=tsconfig.api-tests.json mocha --timeout 10000 -r ts-node/register",
}
nestjs
{
"id": "server-nestjs",
"type": "nestjs",
"source": "source-simple",
"packageName": "@project/oasg-example-nestjs",
"repository": "https://gitlab.supercharge.io/api/v4/projects/1226/packages/npm/"
}
|Parameter| Description| Required | Default | |-|-|-|-| | packageName | Name of the generated NPM package | Y | - | | repository | URL of the NPM package registry | Y | - |
Known limitations:
- array of enums in query/header/path/form parameters are not validated (stay as string)
- no multidimensional array validation in DTOs
Validation availability: List is not comprehensive, missing items are definitely not currently supported
| Validation | DTO | Query | Header | Path | | ---------------------------------------- | --- | ----- | ------ | ---- | | Common | | | | | | IsOptional (!required) | ✅ | ✅ | ✅ | ✅ | | IsDefined (required) | ✅ | ✅ | ✅ | ✅ | | Types | | | | | | IsBoolean | ✅ | ✅ | ✅ | ✅ | | IsDate (isDate, isDateTime) | ❌ | ❌ | ❌ | ❌ | | IsString | ✅ | ✅ | ✅ | ✅ | | IsNumber (isNumber, isFloat, isDouble) | ✅ | ✅ | ✅ | ✅ | | IsInt (isInt, isLong) | ✅ | ✅ | ✅ | ✅ | | IsInt (isShort, isUnboundedInteger) | ❌ | ❌ | ❌ | ❌ | | IsEnum | ✅ | ✅ | ✅ | ✅ | | IsArray | ✅ | ✅ | ✅ | ✅ | | String | | | | | | MinLength | ❌ | ❌ | ❌ | ❌ | | MaxLength | ❌ | ❌ | ❌ | ❌ | | Matches (pattern) | ✅ | ✅ | ✅ | ✅ | | IsUUID (isUuid) | ❌ | ❌ | ❌ | ❌ | | IsDataURI (isUri) | ❌ | ❌ | ❌ | ❌ | | IsEmail (isEmail) | ❌ | ❌ | ❌ | ❌ | | Number | | | | | | Min | ❌ | ❌ | ❌ | ❌ | | Max | ❌ | ❌ | ❌ | ❌ | | IsDivisibleBy (multipleOf) | ❌ | ❌ | ❌ | ❌ | | IsDecimal (isDecimal) | ❌ | ❌ | ❌ | ❌ | | Array | | | | | | multidimensional array | ❌ | ❌ | ❌ | ❌ | | enum arrays | ✅ | ❌ | ❌ | ❌ |
openapi
{
"id": "api-docs",
"type": "openapi",
"source": "source-simple",
}
|Parameter| Description| Required | Default |
|-|-|-|-|
| fileName | Name of the generated file | N | openapi.yaml
|
dotnet
{
"id": "dotnet",
"type": "dotnet",
"source": "source-merged",
"sourceUrl": "https://api.nuget.org/v3/index.json",
"apiKey": "apiKey",
"packageName": "packageName",
"generatorCustomArgs": "--global-property=supportingFiles,modelDocs --additional-properties=nullableReferenceTypes=false"
}
|Parameter| Description| Required | Default | |-|-|-|-| | sourceUrl | Url to where the package will be published | Y | - | | apiKey | Apikey of nuget source | Y | - | | packageName | Name of the generated package | Y | - | | generatorCustomArgs | Custom arguments of the generator (--global-property, --additional-properties) | N | - |
Migration Guide
This section covers the breaking changes and their migrations across major version upgrades.
From 13.x.x
to 14.0.0
Several dependencies have been upgraded, and OASg now uses node
version 20.15.0 and npm
version 10 by default. If your project still uses node@18
, you should upgrade first.
From 12.x.x
to 13.0.1
❗ Due to version
13.0.0
has been published before erroneously (then unpublished) to the NPM registry, this version of the artifact won't be available either as an NPM package or a Docker base image. Please use the13.0.1
patch version instead.
Schema naming updates in angular
, python
, android
,ios
, nestjs
, react
targets
With the update to OpenAPI Generator 7.0.0 the same breaking changes appear as in other targets before:
- Inline Schema Naming in
spring-kotlin
,spring
andfeign
- Skip Reusing Schemas in
spring-kotlin
,spring
andfeign
and more:
ARRAY_ITEM_SUFFIX
andMAP_ITEM_SUFFIX
variables has been set to empty strings- generated inline classes won't have the default
...Inner
suffix from now on
- generated inline classes won't have the default
Breaking in angular
target
- the default
ngVersion
parameter is set to16.0.0
if you wish to specify another version, use e.g"generatorCustomArgs": "-p ngVersion=12"
in yourconfig.json
Breaking in react-native
target
- as both technologies used the same
typescript-fetch
-based generator, with this version the previousreact-native
target has been renamed to a more genericreact
name- if at the future the best practices would change between the web-based React and React Native mobile projects, the
react-native
target will be reintroduced
- if at the future the best practices would change between the web-based React and React Native mobile projects, the
- enum key with multiple segments will contain underscores e.g. the enum key generated from the
value_one
value was used to beVALUEONE
, this will becomeVALUE_ONE
after the update
From 11.x.x
to 12.0.0
The following options from the openapi
target type has been moved to the Source configuration.
bundle
sortSchemas
decorators
cleanup
Please update your config.json
accordingly: move these properties - if they exist - to the respective source
configuration.
⚠️ As the
bundle
,sortSchemas
andcleanup
flags are enabled by default, even without using custom decorators some normalization steps are applied to the source specification before generating the targets. If this causes any problems in your project (although highly unlikely it will) consider disable these flags.
From 10.x.x
to 11.0.0
Linting
The linter configuration previously stored in .spectral.yaml
needs to be updated to the JS format:
- rename the file to
.spectral.js
(don't forget to updatespectral.rulesetFile
in.vscode/settings.json
if used!) - follow the instructions for extending the base OASg ruleset in JS
- migrate project-specific custom rules and functions to JS format
The typical minimal configuration from this in YAML
extends: '@team-supercharge/oasg/rules/default.yaml'
must become this in JS (if no custom rules or functions are used):
import oasgRuleset from '@team-supercharge/oasg/ruleset';
export default {
extends: oasgRuleset
}
From 9.x.x
to 10.0.0
Changed configuration in android
projectName
parameter was removed (it was actually unused)groupId
andartifactId
parameter were added
From 8.x.x
to 9.0.0
Skip Reusing Schemas in spring-kotlin
, spring
and feign
The newer versions of OpenAPI Generator adds the flag to skip the automatic inline schema reusing logic (see example what this means below).
From OASg 9.0.0 the default and recommended behaviour is to skip schema reusing for the targets above. If you wish to resume schema reusing for compatibility reasons, add --inline-schema-name-defaults SKIP_SCHEMA_REUSE=false
to generatorCustomArgs
in the project's config.json
Take the following schema:
schemas:
Message:
type: object
properties: # messages have a topic and text
topic:
type: object
properties: # topics have id and name
id:
type: string
name:
type: string
text:
type: string
User:
type: object
properties: # users have a company, and firstName and lastName
company:
type: object
properties: # copmanies have id and name
id:
type: string
name:
type: string
firstName:
type: string
lastName:
type: string
Previously the following DTO objects were generated from this schema:
Message(MessageTopic topic, String text)
MessageTopic(String id, String name)
User(MessageTopic company, String firstName, String lastName)
Previously the generator reused internal schemas which had the exact same fields, ending up with a MessageTopic
object for the users' Company, just because both had id
and name
string properties.
With defining SKIP_SCHEMA_REUSE=true
the output will be more verbose, but schema names won't get mixed up:
Message(MessageTopic topic, String text)
MessageTopic(String id, String name)
User(UserCompany company, String firstName, String lastName)
UserCompany(String id, String name)
From 7.x.x
to 8.0.0
Linting
If you plan to use the OASg base image with the preinstalled oasg
binary without installing npm dependencies on CI, make sure you update your .spectral.yaml
from the previously recommended syntax which picked up the rules directly from the file system:
extends: node_modules/@team-supercharge/oasg/rules/default.yaml
to use the syntax which picks up rules from the npm package wherever it's installed:
extends: '@team-supercharge/oasg/rules/default.yaml'
Spring Boot 3 support in spring-kotlin
, spring
and feign
Spring Boot 3 version is the default for these generators. To generate Spring Boot 2 libraries, add -puseSpringBoot3=false
to generatorCustomArgs
in the projects config.json
From OASg 8.0.0 the recommended way is to use the base image matching OASg version from the registry.gitlab.com/team-supercharge/oasg
registry. The images use JDK 17 by default. If the generated API must support Java 11, then add the following snippet to the build job:
before_script:
- update-java-alternatives -s temurin-11-jdk-amd64
Inline Schema Naming in spring-kotlin
, spring
and feign
Generating names of inline schemas works differently in the updated openapi-generator version 6.3.0
which is now used in the targets above. If you used inline and/or nested schemas the generated artifact might break you project and you need to rename your schemas.
Take the following schema:
schemas:
Message:
type: object
properties: # messages have topics and a text
topic:
type: object
properties: # topics have id and array of tags
id:
type: string
tags:
type: array
items:
type: object
properties: # tags have a name
name:
type: string
text:
type: string
Previously the following DTO objects were generated from this schema:
Message(MessageTopic topic, String text)
MessageTopic(String id, List<MessageTags> tags)
MessageTags(String name)
With the updated (correct) schema naming convention the result will be the following:
Message(MessageTopic topic, String text)
MessageTopic(String id, List<MessageTopicTags> tags)
MessageTopicTags(String name)
From 6.x.x
to 7.0.0
Only effects the stubby
target. Whether a Docker image is needed to be generated from the output, it needs to be explicitly configured using the new generateWithDocker
parameter.
From 4.x.x
to 5.0.0
If you used the -t <template directory>
flag in your generatorCustomArgs
for any target, please refer to the newly introduced Template Customization section for the correct way of doing it.
For older Angular versions it was necessary to install the [email protected]
package with fixed version. For newer version of Angular this workaround was actually making the generator to fail, so it got removed. If you want to use OASg 5.0.0 with an older Angular version please consider updating it, or patching the previous fix.
From 3.x.x
to 4.0.0
Starting from version 4.0.0
OASg became open-source. Thus future packages are (only) available from the official npmjs.org registry without any authenticaiton.
Please take the following steps:
- update the package reference from
@misc/oasg
to@team-supercharge/oasg
in your project'spackage.json
- bump the version used form
3.x.x
to4.0.0
to find the valid package - remove any additional authentication steps for the
@misc
Supercharge-specific namespace (if no other package is used from it) - run
npm i
to update yourpackage-lock.json
From 2.x.x
to 3.0.0
Follow the steps:
- locate
.spectral.yaml
in your root project folder => it is a symlink insidenode_modules/@misc/oasg...
- delete the symlink and set up the new linting process according to the Configure linter section
- create file
.spectral.yaml
in project root - use the
extends
syntax to refer to the default configuration
- create file
Your project can break for two reasons:
- newer version of Spectral enforces some new rules that were not previously enforced (e.g example types should match the type of the property)
- starting from 3.0.0 and the linter configuration above OASg enforces new Custom rules as well - if you cannot update your project consider turning off the new rules
Roadmap
- ~~implement lint command with spectral modules for validation & linting~~
- ~~serve command (local express server to circumvent CORS) with swagger-ui-express~~
- add
-w --watch
flag to lint and serve commands for local development - ~~research multi-file specs (domain models), theoretically should work~~
- ~~implement default GitLab CI jobs~~
- ~~add merger functionality~~
- ~~add forked openapi-generator somehow~~
- ~~add editorconfig~~
- ~~disallow special characters in source/target IDs (only allow letters, numbers, underscore, dash)~~
- ~~check for dependencies on startup (java, wget, jq)~~
- handle API versioning in OpenAPI files:
- use bumpFiles functionality in standard-version
- get all input files from "config.sources" array
- change version in YAML without touching/reformatting the whole file
- improve README with documenting:
- ~~getting started section~~
- ~~configuration (in projects)~~
- ~~CI setup (in projects)~~
- ~~override linter rules (default set + extend OASG ruleset)~~
- contributing guideline (e.g. extending config schema)