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 argparse
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import json
|
||||||
from yaml.loader import SafeLoader
|
from yaml.loader import SafeLoader
|
||||||
from generateHelper import CsOperationNameConverter, OpenApiExtractRefType
|
from generateHelper import CsOperationNameConverter, OpenApiExtractRefType, CsTypeConverter
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="generate.py")
|
parser = argparse.ArgumentParser(description="generate.py")
|
||||||
parser.add_argument('--apiDefinitionFile', '-a',
|
parser.add_argument('--apiDefinitionFile', '-a',
|
||||||
@ -91,9 +91,18 @@ for path in apiDefinition['paths'].values():
|
|||||||
if not statementChecker[method].match(statement):
|
if not statementChecker[method].match(statement):
|
||||||
raise Exception(f"Invalid statement {statement} for method {method}")
|
raise Exception(f"Invalid statement {statement} for method {method}")
|
||||||
|
|
||||||
inputType = None
|
bodyInputType = {}
|
||||||
if 'requestBody' in operation:
|
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({
|
operations.append({
|
||||||
'description': description,
|
'description': description,
|
||||||
'method':method,
|
'method':method,
|
||||||
@ -103,9 +112,10 @@ for path in apiDefinition['paths'].values():
|
|||||||
'allSelector': operation['operationId'].endswith('all'),
|
'allSelector': operation['operationId'].endswith('all'),
|
||||||
'byIdSelector': operation['operationId'].endswith('byid'),
|
'byIdSelector': operation['operationId'].endswith('byid'),
|
||||||
'statement': statement,
|
'statement': statement,
|
||||||
'inputType': { 'apiName': inputType, 'csName': CsOperationNameConverter(inputType) } if inputType else {}
|
'bodyInputType': bodyInputType,
|
||||||
|
'paramsInputTypes': paramsInputTypes
|
||||||
})
|
})
|
||||||
print(f"{operations=}")
|
#print(f"{operations=}")
|
||||||
apiDefinition["operations"] = operations
|
apiDefinition["operations"] = operations
|
||||||
|
|
||||||
types = {}
|
types = {}
|
||||||
@ -123,9 +133,10 @@ for (typeName, typeDefinition) in apiDefinition['components']['schemas'].items()
|
|||||||
'csName': typeName.capitalize(),
|
'csName': typeName.capitalize(),
|
||||||
'properties': typeProperties
|
'properties': typeProperties
|
||||||
}
|
}
|
||||||
print(f"{types=}")
|
#print(f"{types=}")
|
||||||
apiDefinition['types'] = types
|
apiDefinition['types'] = types
|
||||||
|
|
||||||
|
print(json.dumps(apiDefinition, indent=4))
|
||||||
for f in glob.glob(args.template, recursive=True):
|
for f in glob.glob(args.template, recursive=True):
|
||||||
print(f"process {f}")
|
print(f"process {f}")
|
||||||
tmpl = Template(file=f, searchList=[apiDefinition])
|
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):
|
def CsOperationNameConverter(i):
|
||||||
return ''.join([capitalizeOnlyFirstLetter(x) for x in i.split('.')]) if i else 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):
|
def OpenApiExtractRefType(i):
|
||||||
e = i.split('/')
|
e = i.split('/')
|
||||||
if e[:-1] == ['#', 'components', 'schemas']:
|
if e[:-1] == ['#', 'components', 'schemas']:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
openapi: 3.0.0
|
openapi: 3.0.0
|
||||||
|
|
||||||
info:
|
info:
|
||||||
title: PDB API
|
title: Generic Database API Service
|
||||||
version: "0.0.2"
|
version: "0.0.2"
|
||||||
|
|
||||||
paths:
|
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:
|
Build and run the stub webservice:
|
||||||
|
|
||||||
docker run -it --rm -p 8080:8080 -v $PWD:/work \
|
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
|
bash
|
||||||
|
|
||||||
ATTENTION: This won't work with a set UID
|
ATTENTION: This won't work with a set UID
|
||||||
@ -27,5 +27,12 @@ Build:
|
|||||||
|
|
||||||
Run:
|
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']}.Attributes;
|
||||||
using ${env['packagename']}.Models;
|
using ${env['packagename']}.Models;
|
||||||
using ${env['packagename']}.Controllers;
|
using ${env['packagename']}.Controllers;
|
||||||
|
using ${env['packagename']}.Services;
|
||||||
|
|
||||||
namespace ${env['packagename']}.Implementations
|
namespace ${env['packagename']}.Implementations
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// </summary>
|
||||||
public class RegularApiImplementation : RegularApiController
|
public class RegularApiImplementation : RegularApiController
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private readonly IDbService _dbService;
|
||||||
|
public RegularApiImplementation(IDbService dbService) {
|
||||||
|
_dbService = dbService;
|
||||||
|
}
|
||||||
|
|
||||||
#for $operation in $operations
|
#for $operation in $operations
|
||||||
#if $operation['method'] == 'get'
|
#if $operation['method'] == 'get'
|
||||||
|
/// <summary>
|
||||||
|
/// $operation['description']
|
||||||
|
/// </summary>
|
||||||
public override IActionResult ${operation['func']}( #slurp
|
public override IActionResult ${operation['func']}( #slurp
|
||||||
#if $operation['byIdSelector']
|
#if $operation['paramsInputTypes']
|
||||||
INSERT CODE TO GET ID #slurp
|
#set $sep = ""
|
||||||
#elif $operation['inputType']
|
#for $paramsInputType in $operation['paramsInputTypes']
|
||||||
[FromBody]$operation['inputType']['csName'] inputItem #slurp
|
$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
|
#end if
|
||||||
) {
|
) {
|
||||||
|
_dbService.JustDoSomething("Hello ${operation['func']}");
|
||||||
|
|
||||||
// Statement:
|
// Statement:
|
||||||
#if not $operation['statement']
|
#if not $operation['statement']
|
||||||
// SELECT
|
// SELECT
|
||||||
@ -37,9 +59,9 @@ namespace ${env['packagename']}.Implementations
|
|||||||
#else
|
#else
|
||||||
// $operation['statement']
|
// $operation['statement']
|
||||||
#end if
|
#end if
|
||||||
#if $operation['inputType']
|
#if $operation['bodyInputType']
|
||||||
// Input type mapping: $operation['inputType']['apiName'] -> $operation['inputType']['csName']
|
// Input type mapping: $operation['bodyInputType']['apiName'] -> $operation['bodyInputType']['csName']
|
||||||
#for $property in $types[$operation['inputType']['apiName']]['properties']
|
#for $property in $types[$operation['bodyInputType']['apiName']]['properties']
|
||||||
// $property['sqlName'] -> $property['csName']
|
// $property['sqlName'] -> $property['csName']
|
||||||
#end for
|
#end for
|
||||||
#end if
|
#end if
|
||||||
@ -51,11 +73,17 @@ namespace ${env['packagename']}.Implementations
|
|||||||
#if $operation['isList']
|
#if $operation['isList']
|
||||||
// result must be mapped in list
|
// result must be mapped in list
|
||||||
#end if
|
#end if
|
||||||
return new ObjectResult();
|
return new ObjectResult(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif $operation['method'] == 'post'
|
#elif $operation['method'] == 'post'
|
||||||
bla
|
// INSERT
|
||||||
|
|
||||||
|
#elif $operation['method'] == 'put'
|
||||||
|
// UPDATE
|
||||||
|
|
||||||
|
#elif $operation['method'] == 'delete'
|
||||||
|
// DELETE
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#raise Exception('invalid method')
|
#raise Exception('invalid method')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user