generate all script, service integration and injection
This commit is contained in:
parent
590e9da904
commit
bd85599a98
14
DbService.cs
Normal file
14
DbService.cs
Normal 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
4
ENV
@ -1 +1,3 @@
|
||||
PACKAGE_NAME=KROHNE.PdbApiService
|
||||
PACKAGE_NAME=de.hottis.genericdatabaseapiservice
|
||||
export PACKAGE_NAME
|
||||
|
||||
|
25
generate.py
25
generate.py
@ -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
42
generateAll.sh
Normal 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
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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']:
|
||||
|
@ -1,7 +1,7 @@
|
||||
openapi: 3.0.0
|
||||
|
||||
info:
|
||||
title: PDB API
|
||||
title: Generic Database API Service
|
||||
version: "0.0.2"
|
||||
|
||||
paths:
|
||||
|
11
readme.md
11
readme.md
@ -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
|
||||
|
||||
|
@ -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')
|
||||
|
Loading…
x
Reference in New Issue
Block a user