Wizard generates sample entity and service container

This commit is contained in:
Daniele Teti 2024-04-29 17:49:54 +02:00
parent 9b079a9d6b
commit 91a019c113
6 changed files with 269 additions and 54 deletions

View File

@ -140,6 +140,18 @@ type
); override;
end;
TUnitServicesDeclarationCommand = class(TCustomCommand)
public
procedure ExecuteInterface(
Section: TStringBuilder;
Model: TJSONObject
); override;
procedure ExecuteImplementation(
Section: TStringBuilder;
Model: TJsonObject
); override;
end;
TUnitMustacheHelpersDeclarationCommand = class(TCustomCommand)
public
procedure ExecuteInterface(
@ -286,18 +298,23 @@ begin
.AppendLine(' Web.WebReq,')
.AppendLine(' Web.WebBroker,')
.AppendLine(' IdContext,')
.AppendLine(' IdHTTPWebBrokerBridge,');
.AppendLine(' IdHTTPWebBrokerBridge,')
.AppendLine(' MVCFramework,')
.AppendLine(' MVCFramework.Logger,')
.AppendLine(' MVCFramework.DotEnv,')
.AppendLine(' MVCFramework.Commons,');
if Model.B[TConfigKey.program_ssv_mustache] then
begin
Section
.AppendLine(' MVCFramework.View.Renderers.Mustache,')
.AppendLine(' SynMustache,');
end;
if Model.B[TConfigKey.program_service_container_generate] then
begin
Section
.AppendLine(' MVCFramework.Container,')
end;
Section
.AppendLine(' MVCFramework,')
.AppendLine(' MVCFramework.Logger,')
.AppendLine(' MVCFramework.DotEnv,')
.AppendLine(' MVCFramework.Commons,')
.AppendLine(' MVCFramework.Signal;')
.AppendLine()
.AppendLine('{$R *.res}')
@ -331,9 +348,15 @@ begin
.Append(' MVCFramework, MVCFramework.Commons, ');
if Model.B[TConfigKey.entity_generate] then
begin
Section.Append('MVCFramework.Nullables, ');
Section
.Append('MVCFramework.Nullables, ')
.Append(Model[TConfigKey.entity_unit_name] + ', ');
end;
if Model.B[TConfigKey.program_service_container_generate] then
begin
Section
.Append(Model[TConfigKey.program_service_container_unit_name] + ', ');
end;
Section
.AppendLine('MVCFramework.Serializer.Commons, System.Generics.Collections;')
.AppendLine
@ -346,6 +369,8 @@ begin
inherited;
if not Model.B[TConfigKey.entity_generate] then Exit;
Section
.AppendLine('implementation')
.AppendLine
.AppendLine('constructor ' + Model[TConfigKey.entity_classname] + '.Create(ID: Integer; FirstName, LastName: String; DOB: TDate);')
.AppendLine('begin')
.AppendLine(' inherited Create;')
@ -354,6 +379,9 @@ begin
.AppendLine(' fLastName := LastName;')
.AppendLine(' fDOB := DOB;')
.AppendLine('end;')
.AppendLine
.AppendLine
.AppendLine('end.')
end;
{ TUnitControllerEntitiesCommand }
@ -366,6 +394,14 @@ begin
CheckFor('entity.classname', Model);
Section
.AppendLine('unit ' + Model[TConfigKey.entity_unit_name] + ';')
.AppendLine
.AppendLine('interface')
.AppendLine
.AppendLine('uses')
.AppendLine(' MVCFramework.Nullables, MVCFramework.Serializer.Commons;')
.AppendLine
.AppendLine('type')
.AppendLine(' [MVCNameCase(ncCamelCase)]')
.AppendLine(' ' + Model[TConfigKey.entity_classname] + ' = class')
.AppendLine(' private')
@ -462,33 +498,57 @@ begin
if Model.B[TConfigKey.controller_crud_methods_generate] then
begin
Section
.AppendLine
.AppendLine('//Sample CRUD Actions for a "People" entity')
.AppendLine('function ' + Model[TConfigKey.controller_classname] + '.GetPeople: IMVCResponse;')
.AppendLine('var')
.AppendLine(' lPeople: TObjectList<TPerson>;')
.AppendLine('begin');
if Model.B[TConfigKey.controller_actions_profiling_generate] then
if Model.B[TConfigKey.program_service_container_generate] then
begin
Section
.AppendLine('{$IF CompilerVersion >= 34} //SYDNEY+')
.AppendLine(' var lProf := Profiler.Start(Context.ActionQualifiedName);')
.AppendLine('{$ENDIF}')
.AppendLine;
.AppendLine
.AppendLine('//Sample CRUD Actions for a "People" entity (with service injection)')
.AppendLine('function ' + Model[TConfigKey.controller_classname] + '.GetPeople(PeopleService: IPeopleService): IMVCResponse;')
.AppendLine('begin');
if Model.B[TConfigKey.controller_actions_profiling_generate] then
begin
Section
.AppendLine('{$IF CompilerVersion >= 34} //SYDNEY+')
.AppendLine(' var lProf := Profiler.Start(Context.ActionQualifiedName);')
.AppendLine('{$ENDIF}')
.AppendLine;
end;
Section
.AppendLine(' Result := OkResponse(PeopleService.GetAll);')
.AppendLine('end;')
end
else
begin
Section
.AppendLine
.AppendLine('//Sample CRUD Actions for a "People" entity (no service injection)')
.AppendLine('function ' + Model[TConfigKey.controller_classname] + '.GetPeople: IMVCResponse;')
.AppendLine('var')
.AppendLine(' lPeople: TObjectList<TPerson>;')
.AppendLine('begin');
if Model.B[TConfigKey.controller_actions_profiling_generate] then
begin
Section
.AppendLine('{$IF CompilerVersion >= 34} //SYDNEY+')
.AppendLine(' var lProf := Profiler.Start(Context.ActionQualifiedName);')
.AppendLine('{$ENDIF}')
.AppendLine;
end;
Section
.AppendLine(' lPeople := TObjectList<TPerson>.Create(True);')
.AppendLine(' try')
.AppendLine(' lPeople.Add(TPerson.Create(1, ''Peter'',''Parker'', EncodeDate(1965, 10, 4)));')
.AppendLine(' lPeople.Add(TPerson.Create(2, ''Bruce'',''Banner'', EncodeDate(1945, 9, 6)));')
.AppendLine(' lPeople.Add(TPerson.Create(3, ''Reed'',''Richards'', EncodeDate(1955, 3, 7)));')
.AppendLine(' Result := OkResponse(lPeople);')
.AppendLine(' except')
.AppendLine(' lPeople.Free;')
.AppendLine(' raise;')
.AppendLine(' end;')
.AppendLine('end;')
end;
Section
.AppendLine(' lPeople := TObjectList<TPerson>.Create(True);')
.AppendLine(' try')
.AppendLine(' lPeople.Add(TPerson.Create(1, ''Peter'',''Parker'', EncodeDate(1965, 10, 4)));')
.AppendLine(' lPeople.Add(TPerson.Create(2, ''Bruce'',''Banner'', EncodeDate(1945, 9, 6)));')
.AppendLine(' lPeople.Add(TPerson.Create(3, ''Reed'',''Richards'', EncodeDate(1955, 3, 7)));')
.AppendLine(' Result := OkResponse(lPeople);')
.AppendLine(' except')
.AppendLine(' lPeople.Free;')
.AppendLine(' raise;')
.AppendLine(' end;')
.AppendLine('end;')
.AppendLine
.AppendLine('function ' + Model[TConfigKey.controller_classname] + '.GetPerson(ID: Integer): TPerson;')
.AppendLine('begin');
@ -595,8 +655,20 @@ begin
Section
.AppendLine(' //Sample CRUD Actions for a "People" entity')
.AppendLine(' [MVCPath(''/people'')]')
.AppendLine(' [MVCHTTPMethod([httpGET])]')
.AppendLine(' function GetPeople: IMVCResponse;')
.AppendLine(' [MVCHTTPMethod([httpGET])]');
if Model.B[TConfigKey.program_service_container_generate] then
begin
Section
.AppendLine(' function GetPeople([MVCInject] PeopleService: IPeopleService): IMVCResponse;');
end
else
begin
Section
.AppendLine(' function GetPeople: IMVCResponse;')
end;
Section
.AppendLine
.AppendLine(' [MVCPath(''/people/($ID)'')]')
.AppendLine(' [MVCHTTPMethod([httpGET])]')
@ -946,6 +1018,7 @@ begin
.AppendLine(' end;')
.AppendLine('{$ENDIF}')
.AppendLine;
if Model.B[TConfigKey.program_ssv_mustache] then
begin
Section
@ -957,6 +1030,15 @@ begin
.AppendLine(' end;')
.AppendLine;
end;
if Model.B[TConfigKey.program_service_container_generate] then
begin
Section
.AppendLine(' RegisterServices(DefaultMVCServiceContainer);')
.AppendLine(' DefaultMVCServiceContainer.Build;')
.AppendLine;
end;
Section
.AppendLine(' RunServer(dotEnv.Env(''dmvc.server.port'', ' + Model[TConfigKey.program_default_server_port] + '));')
.AppendLine(' except')
@ -1142,4 +1224,64 @@ begin
.AppendLine;
end;
{ TUnitServicesDeclarationCommand }
procedure TUnitServicesDeclarationCommand.ExecuteImplementation(
Section: TStringBuilder; Model: TJsonObject);
begin
Section
.AppendLine('implementation')
.AppendLine
.AppendLine('uses')
.AppendLine(' System.SysUtils;')
.AppendLine
.AppendLine('procedure RegisterServices(Container: IMVCServiceContainer);')
.AppendLine('begin')
.AppendLine(' Container.RegisterType(TPeopleService, IPeopleService, TRegistrationType.SingletonPerRequest);')
.AppendLine(' // Register other services here')
.AppendLine('end;')
.AppendLine
.AppendLine('function TPeopleService.GetAll: TObjectList<TPerson>;')
.AppendLine('begin')
.AppendLine(' Result := TObjectList<TPerson>.Create;')
.AppendLine(' Result.AddRange([')
.AppendLine(' TPerson.Create(1, ''Henry'', ''Ford'', EncodeDate(1863, 7, 30)),')
.AppendLine(' TPerson.Create(2, ''Guglielmo'', ''Marconi'', EncodeDate(1874, 4, 25)),')
.AppendLine(' TPerson.Create(3, ''Antonio'', ''Meucci'', EncodeDate(1808, 4, 13)),')
.AppendLine(' TPerson.Create(4, ''Michael'', ''Faraday'', EncodeDate(1867, 9, 22))')
.AppendLine(' ]);')
.AppendLine('end;')
.AppendLine
.AppendLine
.AppendLine('end.');
end;
procedure TUnitServicesDeclarationCommand.ExecuteInterface(
Section: TStringBuilder; Model: TJSONObject);
begin
Section
.AppendLine('unit ' + Model[TConfigKey.program_service_container_unit_name] + ';')
.AppendLine
.AppendLine('interface')
.AppendLine
.AppendLine('uses')
.AppendLine(' ' + Model[TConfigKey.entity_unit_name] + ',')
.AppendLine(' MVCFramework.Container, System.Generics.Collections;')
.AppendLine
.AppendLine('type')
.AppendLine(' IPeopleService = interface')
.AppendLine(' [''' + TGUID.NewGuid.ToString + ''']')
.AppendLine(' function GetAll: TObjectList<TPerson>;')
.AppendLine(' end;')
.AppendLine
.AppendLine(' TPeopleService = class(TInterfacedObject, IPeopleService)')
.AppendLine(' protected')
.AppendLine(' function GetAll: TObjectList<TPerson>;')
.AppendLine(' end;')
.AppendLine
.AppendLine('procedure RegisterServices(Container: IMVCServiceContainer);')
.AppendLine;
end;
end.

View File

@ -35,6 +35,8 @@ procedure FillWebModuleTemplates(Gen: TMVCCodeGenerator);
procedure FillWebModuleDFMTemplates(Gen: TMVCCodeGenerator);
procedure FillJSONRPCTemplates(Gen: TMVCCodeGenerator);
procedure FillMustacheTemplates(Gen: TMVCCodeGenerator);
procedure FillEntitiesTemplates(Gen: TMVCCodeGenerator);
procedure FillServicesTemplates(Gen: TMVCCodeGenerator);
implementation
@ -55,7 +57,6 @@ procedure FillControllerTemplates(Gen: TMVCCodeGenerator);
begin
Gen.Commands.AddRange([
TUnitControllerCommand.Create,
TUnitControllerEntityDeclarationCommand.Create,
TUnitControllerControllerDeclarationCommand.Create,
TUnitFooterCommand.Create
]);
@ -82,8 +83,6 @@ begin
]);
end;
procedure FillMustacheTemplates(Gen: TMVCCodeGenerator);
begin
Gen.Commands.AddRange([
@ -91,4 +90,19 @@ begin
]);
end;
procedure FillServicesTemplates(Gen: TMVCCodeGenerator);
begin
Gen.Commands.AddRange([
TUnitServicesDeclarationCommand.Create
]);
end;
procedure FillEntitiesTemplates(Gen: TMVCCodeGenerator);
begin
Gen.Commands.AddRange([
TUnitControllerEntityDeclarationCommand.Create
]);
end;
end.

View File

@ -58,6 +58,8 @@ type
program_msheap='program.msheap';
program_dotenv='program.dotenv';
program_ssv_mustache='program.ssv.mustache';
program_service_container_generate = 'program.service.container.generate';
program_service_container_unit_name = 'program.service.container.unit_name';
mustache_helpers_unit_name = 'mustache.helpers_unit_name';
controller_unit_name='controller.unit_name';
controller_classname= 'controller.classname';
@ -67,6 +69,7 @@ type
controller_actions_profiling_generate= 'controller.actions.profiling.generate';
entity_generate= 'entity.generate';
entity_classname= 'entity.classname';
entity_unit_name='entity.unit_name';
jsonrpc_generate= 'jsonrpc.generate';
jsonrpc_classname= 'jsonrpc.classname';
jsonrpc_unit_name='jsonrpc.unit_name';

View File

@ -3,7 +3,7 @@ object frmDMVCNewProject: TfrmDMVCNewProject
Top = 0
BorderStyle = bsDialog
Caption = 'DelphiMVCFramework :: New Project Wizard'
ClientHeight = 598
ClientHeight = 615
ClientWidth = 729
Color = clBtnFace
Constraints.MinHeight = 145
@ -18,7 +18,7 @@ object frmDMVCNewProject: TfrmDMVCNewProject
OnDestroy = FormDestroy
DesignSize = (
729
598)
615)
TextHeight = 13
object Shape1: TShape
Left = 0
@ -400,7 +400,7 @@ object frmDMVCNewProject: TfrmDMVCNewProject
object lblBook: TLabel
AlignWithMargins = True
Left = 15
Top = 563
Top = 579
Width = 259
Height = 16
Cursor = crHandPoint
@ -458,7 +458,7 @@ object frmDMVCNewProject: TfrmDMVCNewProject
end
object btnOK: TButton
Left = 549
Top = 563
Top = 580
Width = 77
Height = 27
Anchors = [akRight, akBottom]
@ -467,11 +467,10 @@ object frmDMVCNewProject: TfrmDMVCNewProject
ModalResult = 1
TabOrder = 3
OnClick = btnOKClick
ExplicitTop = 541
end
object btnCancel: TButton
Left = 632
Top = 563
Top = 580
Width = 77
Height = 27
Anchors = [akRight, akBottom]
@ -479,7 +478,6 @@ object frmDMVCNewProject: TfrmDMVCNewProject
Caption = 'Cancel'
ModalResult = 2
TabOrder = 4
ExplicitTop = 541
end
object chkAddToProjectGroup: TCheckBox
Left = 24
@ -508,7 +506,7 @@ object frmDMVCNewProject: TfrmDMVCNewProject
end
object Panel2: TPanel
Left = 0
Top = 342
Top = 359
Width = 308
Height = 215
Anchors = [akLeft, akBottom]
@ -518,7 +516,6 @@ object frmDMVCNewProject: TfrmDMVCNewProject
ParentCtl3D = False
ShowCaption = False
TabOrder = 5
ExplicitTop = 320
DesignSize = (
308
215)
@ -573,8 +570,6 @@ object frmDMVCNewProject: TfrmDMVCNewProject
Height = 17
Anchors = [akLeft, akTop, akRight]
Caption = 'Create Action Filters Methods'
Checked = True
State = cbChecked
TabOrder = 1
end
object chkCreateCRUDMethods: TCheckBox
@ -729,13 +724,12 @@ object frmDMVCNewProject: TfrmDMVCNewProject
end
object GroupBoxJSONRPC: TGroupBox
Left = 314
Top = 371
Top = 388
Width = 396
Height = 105
Anchors = [akLeft, akRight, akBottom]
Caption = 'JSON-RPC 2.0'
TabOrder = 7
ExplicitTop = 349
DesignSize = (
396
105)
@ -769,7 +763,7 @@ object frmDMVCNewProject: TfrmDMVCNewProject
end
object chkMSHeap: TCheckBox
Left = 24
Top = 286
Top = 292
Width = 225
Height = 17
Anchors = [akLeft, akRight, akBottom]
@ -778,7 +772,7 @@ object frmDMVCNewProject: TfrmDMVCNewProject
end
object chkCustomConfigDotEnv: TCheckBox
Left = 24
Top = 267
Top = 273
Width = 225
Height = 17
Anchors = [akLeft, akRight, akBottom]
@ -787,13 +781,24 @@ object frmDMVCNewProject: TfrmDMVCNewProject
end
object chkMustache: TCheckBox
Left = 24
Top = 306
Top = 312
Width = 225
Height = 17
Anchors = [akLeft, akRight, akBottom]
Caption = 'Use Mustache as Server Side View engine'
TabOrder = 10
end
object chkServicesContainer: TCheckBox
Left = 24
Top = 332
Width = 225
Height = 17
Anchors = [akLeft, akRight, akBottom]
Caption = 'Use Services Container'
Checked = True
State = cbChecked
TabOrder = 11
end
object ApplicationEvents: TApplicationEvents
OnIdle = ApplicationEventsIdle
Left = 232

View File

@ -98,6 +98,7 @@ type
chkProfileActions: TCheckBox;
lblPATREON: TLabel;
chkMustache: TCheckBox;
chkServicesContainer: TCheckBox;
procedure chkCreateControllerUnitClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Image1Click(Sender: TObject);
@ -341,6 +342,8 @@ begin
fModel.B[TConfigKey.program_msheap] := chkMSHeap.Checked;
fModel.B[TConfigKey.program_dotenv] := chkCustomConfigDotEnv.Checked;
fModel.B[TConfigKey.program_ssv_mustache] := chkMustache.Checked;
fModel.B[TConfigKey.program_service_container_generate] := chkServicesContainer.Checked;
fModel.S[TConfigKey.program_service_container_unit_name] := 'TBA';
fModel.S[TConfigKey.controller_unit_name] := 'TBA';
fModel.S[TConfigKey.controller_classname] := GetControllerClassName;
fModel.B[TConfigKey.controller_index_methods_generate] := chkCreateIndexMethod.Checked;
@ -350,8 +353,8 @@ begin
fModel.B[TConfigKey.entity_generate] := fModel.B[TConfigKey.controller_crud_methods_generate];
fModel.S[TConfigKey.entity_classname] := 'TPerson';
fModel.B[TConfigKey.jsonrpc_generate] := GetCreateJSONRPCInterface;
fModel.S[TConfigKey.jsonrpc_classname] := GetJSONRPCClassName;
fModel.S[TConfigKey.jsonrpc_unit_name] := 'TBA';
fModel.S[TConfigKey.jsonrpc_classname] := GetJSONRPCClassName;
fModel.S[TConfigKey.jsonrpc_unit_name] := 'TBA';
//webmodule

View File

@ -92,16 +92,22 @@ begin
Config: IOTABuildConfiguration;
ControllerUnit: IOTAModule;
JSONRPCUnit: IOTAModule;
ServicesUnit: IOTAModule;
WebModuleUnit: IOTAModule;
MustacheHelperUnit: IOTAModule;
ControllerCreator: IOTACreator;
EntityCreator: IOTACreator;
JSONRPCUnitCreator: IOTACreator;
ServicesUnitCreator: IOTACreator;
MustacheHelpersUnitCreator: IOTACreator;
WebModuleCreator: IOTAModuleCreator;
lProjectSourceCreator: IOTACreator;
lJSONRPCUnitName: string;
lServicesUnitName: string;
lJSON: TJSONObject;
lMustacheHelpersUnitName: string;
lMustacheHelpersUnitName: string;
lEntityUnitName: string;
EntityUnit: IOTAModule;
begin
WizardForm := TfrmDMVCNewProject.Create(Application);
try
@ -122,6 +128,46 @@ begin
Config := (Project.ProjectOptions as IOTAProjectOptionsConfigurations).BaseConfiguration;
Config.SetValue(sUnitSearchPath, '$(DMVC)');
Config.SetValue(sFramework, 'FMX');
lEntityUnitName := '';
// Create ENTITY Unit
if lJSON.B[TConfigKey.controller_crud_methods_generate] then
begin
EntityCreator := TNewGenericUnitFromTemplate.Create(
lJSON,
FillEntitiesTemplates,
TConfigKey.entity_unit_name,
APersonality);
EntityUnit := ModuleServices.CreateModule(EntityCreator);
ChangeIOTAModuleFileNamePrefix(EntityUnit, 'Entity.' + lJSON.S[TConfigKey.entity_classname].Substring(1));
lEntityUnitName := GetUnitName(EntityUnit.FileName);
lJSON.S[TConfigKey.entity_unit_name] := lEntityUnitName;
if Project <> nil then
begin
Project.AddFile(EntityUnit.FileName, True);
end;
end;
lServicesUnitName := '';
// Create Services Unit
if lJSON.B[TConfigKey.program_service_container_generate] then
begin
ServicesUnitCreator := TNewGenericUnitFromTemplate.Create(
lJSON,
FillServicesTemplates,
TConfigKey.program_service_container_unit_name,
APersonality);
ServicesUnit := ModuleServices.CreateModule(ServicesUnitCreator);
ChangeIOTAModuleFileNamePrefix(ServicesUnit, 'Services');
lServicesUnitName := GetUnitName(ServicesUnit.FileName);
lJSON.S[TConfigKey.program_service_container_unit_name] := lServicesUnitName;
if Project <> nil then
begin
Project.AddFile(ServicesUnit.FileName, True);
end;
end;
// Create Controller Unit
if WizardForm.CreateControllerUnit then
begin
@ -135,6 +181,7 @@ begin
end;
end;
lJSONRPCUnitName := '';
// Create JSONRPC Unit
if lJSON.B[TConfigKey.jsonrpc_generate] then
@ -174,6 +221,7 @@ begin
end;
end;
// Create Webmodule Unit
WebModuleCreator := TNewWebModuleUnitEx.Create(
lJSON,