generate all script, service integration and injection

This commit is contained in:
Wolfgang Hottgenroth 2021-11-22 19:07:46 +01:00
parent 590e9da904
commit bd85599a98
8 changed files with 132 additions and 21 deletions

14
DbService.cs Normal file
View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
namespace de.hottis.genericdatabaseapiservice.Services {
public interface IDbService {
void JustDoSomething(string msg);
}
public class DbService : IDbService {
public void JustDoSomething(string msg) {
Console.WriteLine(msg);
}
}
}

4
ENV
View File

@ -1 +1,3 @@
PACKAGE_NAME=KROHNE.PdbApiService
PACKAGE_NAME=de.hottis.genericdatabaseapiservice
export PACKAGE_NAME

View File

@ -4,9 +4,9 @@ import glob
import argparse
import os
import re
import json
from yaml.loader import SafeLoader
from generateHelper import CsOperationNameConverter, OpenApiExtractRefType
from generateHelper import CsOperationNameConverter, OpenApiExtractRefType, CsTypeConverter
parser = argparse.ArgumentParser(description="generate.py")
parser.add_argument('--apiDefinitionFile', '-a',
@ -91,9 +91,18 @@ for path in apiDefinition['paths'].values():
if not statementChecker[method].match(statement):
raise Exception(f"Invalid statement {statement} for method {method}")
inputType = None
bodyInputType = {}
if 'requestBody' in operation:
inputType = OpenApiExtractRefType(operation['requestBody']['content']['application/json']['schema']['$ref'])
bodyInputTypeName = OpenApiExtractRefType(operation['requestBody']['content']['application/json']['schema']['$ref'])
bodyInputType = { 'apiName': bodyInputTypeName, 'csName': CsOperationNameConverter(bodyInputTypeName) }
paramsInputTypes =[]
if 'parameters' in operation:
for paramsInputType in operation['parameters']:
paramsInputType['type'] = CsTypeConverter(paramsInputType['schema']['type'])
del paramsInputType['schema']
paramsInputTypes.append(paramsInputType)
operations.append({
'description': description,
'method':method,
@ -103,9 +112,10 @@ for path in apiDefinition['paths'].values():
'allSelector': operation['operationId'].endswith('all'),
'byIdSelector': operation['operationId'].endswith('byid'),
'statement': statement,
'inputType': { 'apiName': inputType, 'csName': CsOperationNameConverter(inputType) } if inputType else {}
'bodyInputType': bodyInputType,
'paramsInputTypes': paramsInputTypes
})
print(f"{operations=}")
#print(f"{operations=}")
apiDefinition["operations"] = operations
types = {}
@ -123,9 +133,10 @@ for (typeName, typeDefinition) in apiDefinition['components']['schemas'].items()
'csName': typeName.capitalize(),
'properties': typeProperties
}
print(f"{types=}")
#print(f"{types=}")
apiDefinition['types'] = types
print(json.dumps(apiDefinition, indent=4))
for f in glob.glob(args.template, recursive=True):
print(f"process {f}")
tmpl = Template(file=f, searchList=[apiDefinition])

42
generateAll.sh Normal file
View File

@ -0,0 +1,42 @@
#!/bin/bash
# safety measure
if [ -d output ]; then
echo "output directory already exist"
echo "remove manually and try again"
fi
# PACKAGE_NAME will be loaded here
. ENV
# generate server code and endpoint stubs from openapi.yaml
docker run -it --rm -v $PWD:/work -u $UID openapitools/openapi-generator:cli-v5.1.0 \
generate -i /work/openapi.yaml -g aspnetcore -o /work/output \
--package-name $PACKAGE_NAME \
--additional-properties="packageVersion=0.0.1,aspnetCoreVersion=5.0,operationIsAsync=true,modelPropertyNaming=camelCase,\
generateBody=false,classModifier=abstract,operationModifier=abstract"
# patch DbService registering into generated startup code
sed -i output/src/$PACKAGE_NAME/Startup \
-e 's/\(using '$PACKAGE_NAME'.OpenApi;\)/\1\nusing '$PACKAGE_NAME'.Services;/'\
-e 's#\(// Add framework services.\)#services.AddTransient<IDbService, DbService>();\n\1#'
# create directories for manually developed code
mkdir output/src/$PACKAGE_NAME/Implementations
mkdir output/src/$PACKAGE_NAME/Services
# copy database service into source code try
cp DbService.cs output/src/$PACKAGE_NAME/Services
# generate endpoint code from openapi.yaml
python3.10 generate.py
# copy endpoint code into source code try
cp regular.cs output/src/$PACKAGE_NAME/Implementations

View File

@ -7,6 +7,13 @@ def JsNameConverter(i):
def CsOperationNameConverter(i):
return ''.join([capitalizeOnlyFirstLetter(x) for x in i.split('.')]) if i else i
def CsTypeConverter(i):
r = i
match (i):
case 'integer':
r = 'int'
return r
def OpenApiExtractRefType(i):
e = i.split('/')
if e[:-1] == ['#', 'components', 'schemas']:

View File

@ -1,7 +1,7 @@
openapi: 3.0.0
info:
title: PDB API
title: Generic Database API Service
version: "0.0.2"
paths:

View File

@ -16,7 +16,7 @@ Configuration details for generator: https://openapi-generator.tech/docs/generat
Build and run the stub webservice:
docker run -it --rm -p 8080:8080 -v $PWD:/work \
devnexus.krohne.com:18079/repository/docker-krohne/dotnetcoresdkenv:5.0 \
registry.hottis.de/dockerized/dotnetcore5sdk:1.0.0 \
bash
ATTENTION: This won't work with a set UID
@ -27,5 +27,12 @@ Build:
Run:
dotnet run -p src/KROHNE.ManufacturingCycleReportWebService/KROHNE.ManufacturingCycleReportWebService.csproj
dotnet run -p src/$PACKAGE_NAME/$PACKAGE_NAME.csproj
From output/src/$PACKAGE_NAME:
* dotnet add package MySqlConnector --version 2.0.0
* make implementations directory
* copy generate endpoint implementation code to implementations directory

View File

@ -11,20 +11,42 @@ using Newtonsoft.Json;
using ${env['packagename']}.Attributes;
using ${env['packagename']}.Models;
using ${env['packagename']}.Controllers;
using ${env['packagename']}.Services;
namespace ${env['packagename']}.Implementations
{
/// <summary>
/// </summary>
public class RegularApiImplementation : RegularApiController
{
private readonly IDbService _dbService;
public RegularApiImplementation(IDbService dbService) {
_dbService = dbService;
}
#for $operation in $operations
#if $operation['method'] == 'get'
/// <summary>
/// $operation['description']
/// </summary>
public override IActionResult ${operation['func']}( #slurp
#if $operation['byIdSelector']
INSERT CODE TO GET ID #slurp
#elif $operation['inputType']
[FromBody]$operation['inputType']['csName'] inputItem #slurp
#if $operation['paramsInputTypes']
#set $sep = ""
#for $paramsInputType in $operation['paramsInputTypes']
$sep [FromRoute (Name = "$paramsInputType['name']")] #slurp
#if $paramsInputType['required']
[Required] #slurp
#end if
$paramsInputType['type'] $paramsInputType['name'] #slurp
#set $sep = ","
#end for
#elif $operation['bodyInputType']
[FromBody]$operation['bodyInputType']['csName'] $operation['bodyInputType']['apiName'] #slurp
#end if
) {
) {
_dbService.JustDoSomething("Hello ${operation['func']}");
// Statement:
#if not $operation['statement']
// SELECT
@ -37,9 +59,9 @@ namespace ${env['packagename']}.Implementations
#else
// $operation['statement']
#end if
#if $operation['inputType']
// Input type mapping: $operation['inputType']['apiName'] -> $operation['inputType']['csName']
#for $property in $types[$operation['inputType']['apiName']]['properties']
#if $operation['bodyInputType']
// Input type mapping: $operation['bodyInputType']['apiName'] -> $operation['bodyInputType']['csName']
#for $property in $types[$operation['bodyInputType']['apiName']]['properties']
// $property['sqlName'] -> $property['csName']
#end for
#end if
@ -51,11 +73,17 @@ namespace ${env['packagename']}.Implementations
#if $operation['isList']
// result must be mapped in list
#end if
return new ObjectResult();
return new ObjectResult(null);
}
#elif $operation['method'] == 'post'
bla
// INSERT
#elif $operation['method'] == 'put'
// UPDATE
#elif $operation['method'] == 'delete'
// DELETE
#else
#raise Exception('invalid method')