Package: evonik-openapi
openapiThis repo contains helper-scripts to generate API client/server code from an OpenAPI specification usingopenapi-generator.It solves a common problem: merging newly generated versions of an API with existing implementations.Workflowuseopenapi-generatorto generate client/server codemerge or replace new files with existing onesreplace content of generated files (based on config)Repo structureexamples/             example configurations
src/                  source filesExamplesSome examples for the configuration and usage can be foundhere.InstallationThe script expect a local installation of theopenapi-generatortool.
For details on the installation, sehere.
We recommend installing it via brew:brew install openapi-generatorTo execute our wrapper script, you must install python (3.7+) and the required modules:brew install python3
cd src/
pip3 install -r requirements.txtExecutionTo execute the script and generate all components specified in the configuration file, simply call the python script as follows:python openapi.py [openapi.json]Note that the specification of the path to the configuration file is optional and defaults to./openapi.json.ConfigurationThe configuration is stored in a.jsonfile.
It is used to specify paths and client/server stubs to be generated using theopenapi-generator.StructureA basic configuration file must contain the following fields:{
	"defaults": {},
	"generators": []
}generatorsis a list of generator configurations.defaultscontains the default configuration shared by all generators.
These default properties are merged with specific ones such that values are replaced, lists are appended, and dicts are merged.GeneratorEach generator configuration must contain the following fields, specified directly or viadefaults:{
	"spec": "../backend.yml",
	"tempDir": "temp",
	"tempSuffix": ".tmp",
	"updatedFileSuffix": ".updated",
	"updatedDirSuffix": "-updated",
	"generator": "python-flask",
	"srcSubDir": "openapi_server",
	"outputDir": "backend",
	"replaceInFiles": {},
	"mode": "merge",
	"filesToKeep": [],
	"dirsToKeep": []
}The fields have the following meaning:spec: openapi specification to usetempDir: path to use for the temporary code generationtempSuffix: suffix to use for temporary filesupdatedFileSuffix: suffix for updated filesupdatedDirSuffix: suffix for updated dirsgenerator: the generator to use (seethe official documentationfor a complete listsrcSubDir: the sub dir of generated code to use as outputoutputDir: the target path where to move the generated filesreplaceInFiles: dicts of in-file replacements (see below)mode: how to proceed ifoutputDiris not empty (overwriteormerge)filesToKeep: files that should not be overwritten inmodemergedirsToKeep: dirs that should not be overwritten inmodemergeBefore processing, each configuration is merged with the default values (defaults) as described above.replaceInFilesThe keys of this dict are regular expressions (seehere,here, andherefor documentation) that describe the filenames of files to be processed.
The values are dicts which map strings to their replacement in the corresponding file(s).An example of this field is:{
	"(.*\\.)(yml|yaml|py)": {
		"openapi_server": "backend"
	},
	"__main__.py": {
		"import connexion": "import connexion, os",
		"app\\.run\\(port=8080\\)": "app.run(port=int(os.getenv('PORT', 8080)), debug=bool(os.getenv('DEBUG', False)))",
		"openapi_server": "backend"
	}
}This results in the replacement ofopenapi_serverwithbackendin all.pyand.yamlfiles as well as three replacements in__main__.py.modeThemodespecifies how to proceed with the generated files if the target diroutputDiris not empty, i.e., the respective component has been generated before.
So far, two modes are available:overwrite: delete all files and dirs inoutputDirand move content fromtempDir/srcSubDirtheremerge: replace all files/dirs not infilesToKeepordirsToKeep(handle those as described below)All newly created files are processed as specified inreplaceInFilesbefore replacing or being merged with existing ones.mode:overwriteIn this mode, all existing files and dirs inoutputDirare deleted before the generated files fromtempDir/srcSubDirare moved tooutputDir.mode:mergeIn this mode, all files inoutputDirare replaced by the files intempDir/srcSubDirexcept for those specifeid indirsToKeepandfilesToKeep.
For those firs/files, the newly generated ones are suffixed byupdatedDirSuffixorupdatedFileSuffixresp. and moved next to their existing version intargetDir.As an example, consider the following configuration and file structure after generation:{
	"mode": "merge",
	"filesToKeep": [
		"a/a1.txt",
		"a/a2.txt"
	],
	"dirsToKeep": [
		"b",
		"c",
	]
}backend/                 # the existing files (targetDir)
        a/
          a1.txt
        b/
          b1.txt
temp/                    # the newly generated files (tempDir)
     relevant/           # the files to consider (srcSubDir)
              a/
                a1.txt
                a2.txt
              b/
                b1.txt
                b2.txt
              c/
                c1.txt
                c2.txtThis would result in the following file structure:backend/
        a/
          a1.txt                # old
          a1.txt.updated        # new
          a2.txt                # new
        b/
          b1.txt                # old
        b-updated/
                  b1.txt        # new
                  b2.txt        # new
        c/
          c1.txt                # new
          c2.txt                # newNote thattemp/relevant/b/b2.txtis not moved to the new files frombaclend//b/b2.txtbecause the whole dir is specified indirsToKeepand it exists already inbackend/.
In contrast,c/does not exist inbackend/yet and is therefore moved to the target position.