mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-15 15:55:54 +01:00
New Project Generator Architecture
This commit is contained in:
parent
dea575f3df
commit
089513e2cf
@ -2210,7 +2210,6 @@ begin
|
||||
lCust.Free;
|
||||
end;
|
||||
|
||||
|
||||
lCust := TMVCActiveRecord.GetByPK<TCustomerWithVersion>(lID);
|
||||
try
|
||||
lCust.CompanyName := 'Alphabet Inc.';
|
||||
@ -2218,6 +2217,27 @@ begin
|
||||
finally
|
||||
lCust.Free;
|
||||
end;
|
||||
|
||||
// Let's load 2 instances
|
||||
var lCust1 := TMVCActiveRecord.GetByPK<TCustomerWithVersion>(lID);
|
||||
try
|
||||
var lCust2 := TMVCActiveRecord.GetByPK<TCustomerWithVersion>(lID);
|
||||
try
|
||||
//User1
|
||||
lCust1.CompanyName := 'MyCompany';
|
||||
lCust1.Store; //save the first version
|
||||
//User1 - end
|
||||
|
||||
//User2
|
||||
lCust2.Rating := 4;
|
||||
lCust2.Store; //save another version starting from an older version - exception
|
||||
//User2 - end
|
||||
finally
|
||||
lCust2.Free;
|
||||
end;
|
||||
finally
|
||||
lCust1.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.btnOOPClick(Sender: TObject);
|
||||
|
250
tools/projectgenerator/Commands.ImplementationU.pas
Normal file
250
tools/projectgenerator/Commands.ImplementationU.pas
Normal file
@ -0,0 +1,250 @@
|
||||
unit Commands.ImplementationU;
|
||||
|
||||
interface
|
||||
|
||||
uses CommonsU, System.SysUtils, MVCFramework.Commons, JsonDataObjects;
|
||||
|
||||
type
|
||||
TUnitFooterCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
procedure ExecuteInterface(
|
||||
Section: TStringBuilder;
|
||||
Model: TJsonObject); override;
|
||||
end;
|
||||
|
||||
TUnitMainBeginEndCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
procedure ExecuteInterface(Section: TStringBuilder; Model: TJsonObject); override;
|
||||
end;
|
||||
|
||||
TUnitRunServerProcBody = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
procedure ExecuteInterface(Section: TStringBuilder; Model: TJsonObject); override;
|
||||
end;
|
||||
|
||||
TUnitControllerEntityImplementationCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
end;
|
||||
|
||||
TUnitControllerControllerImplementationCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TUnitFooterCommand }
|
||||
|
||||
procedure TUnitFooterCommand.ExecuteImplementation(Section: TStringBuilder;
|
||||
Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
Section.AppendLine.AppendLine('end.');
|
||||
end;
|
||||
|
||||
procedure TUnitFooterCommand.ExecuteInterface(Section: TStringBuilder;
|
||||
Model: TJsonObject);
|
||||
begin
|
||||
inherited;
|
||||
|
||||
end;
|
||||
|
||||
{ TUnitMainBeginEndCommand }
|
||||
|
||||
procedure TUnitMainBeginEndCommand.ExecuteImplementation(Section: TStringBuilder;
|
||||
Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
Section
|
||||
.AppendLine
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' { Enable ReportMemoryLeaksOnShutdown during debug }')
|
||||
.AppendLine(' // ReportMemoryLeaksOnShutdown := True;')
|
||||
.AppendLine(' IsMultiThread := True;'' + sLineBreak + sLineBreak +')
|
||||
.AppendLine(' // DMVCFramework Specific Configuration ')
|
||||
.AppendLine(' // When MVCSerializeNulls = True empty nullables and nil are serialized as json null.')
|
||||
.AppendLine(' // When MVCSerializeNulls = False empty nullables and nil are not serialized at all.')
|
||||
.AppendLine(' MVCSerializeNulls := True;')
|
||||
.AppendLine(' UseConsoleLogger := True;')
|
||||
.AppendLine(' LogI(''** DMVCFramework Server ** build '' + DMVCFRAMEWORK_VERSION);')
|
||||
.AppendLine(' try')
|
||||
.AppendLine(' if WebRequestHandler <> nil then')
|
||||
.AppendLine(' WebRequestHandler.WebModuleClass := WebModuleClass;')
|
||||
.AppendLine
|
||||
.AppendLine(' dotEnvConfigure(')
|
||||
.AppendLine(' function: IMVCDotEnv')
|
||||
.AppendLine(' begin')
|
||||
.AppendLine(' Result := NewDotEnv')
|
||||
.AppendLine(' .UseStrategy(TMVCDotEnvPriority.FileThenEnv)')
|
||||
.AppendLine(' //if available, by default, loads default environment (.env)')
|
||||
.AppendLine(' .UseProfile(''test'') //if available loads the test environment (.env.test)')
|
||||
.AppendLine(' .UseProfile(''prod'') //if available loads the prod environment (.env.prod)')
|
||||
.AppendLine(' .UseLogger(procedure(LogItem: String)')
|
||||
.AppendLine(' begin')
|
||||
.AppendLine(' LogD(''dotEnv: '' + LogItem);')
|
||||
.AppendLine(' end)')
|
||||
.AppendLine(' .Build(); //uses the executable folder to look for .env* files')
|
||||
.AppendLine(' end);')
|
||||
.AppendLine
|
||||
.AppendLine(' WebRequestHandlerProc.MaxConnections := dotEnv.Env(''dmvc.handler.max_connections'', 1024);')
|
||||
.AppendLine
|
||||
.AppendLine('{$IF Defined(SYDNEYORBETTER)}')
|
||||
.AppendLine(' if dotEnv.Env(''dmvc.profiler.enabled'', false) then')
|
||||
.AppendLine(' begin')
|
||||
.AppendLine(' Profiler.ProfileLogger := Log;')
|
||||
.AppendLine(' Profiler.WarningThreshold := dotEnv.Env(''dmvc.profiler.warning_threshold'', 2000);')
|
||||
.AppendLine(' end;')
|
||||
.AppendLine('{$ENDIF}')
|
||||
.AppendLine
|
||||
.AppendLine(' RunServer(dotEnv.Env(''dmvc.server.port'', %1:d));')
|
||||
.AppendLine(' except')
|
||||
.AppendLine(' on E: Exception do')
|
||||
.AppendLine(' LogF(E.ClassName + '': '' + E.Message);')
|
||||
.AppendLine(' end;')
|
||||
.AppendLine('end.')
|
||||
end;
|
||||
|
||||
procedure TUnitMainBeginEndCommand.ExecuteInterface(Section: TStringBuilder;
|
||||
Model: TJsonObject);
|
||||
begin
|
||||
inherited;
|
||||
|
||||
end;
|
||||
|
||||
{ TUnitRunServerProcBody }
|
||||
|
||||
procedure TUnitRunServerProcBody.ExecuteImplementation(Section: TStringBuilder;
|
||||
Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
Section
|
||||
.AppendLine('procedure RunServer(APort: Integer);')
|
||||
.AppendLine('var')
|
||||
.AppendLine(' LServer: TIdHTTPWebBrokerBridge;')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' LServer := TIdHTTPWebBrokerBridge.Create(nil);')
|
||||
.AppendLine(' try')
|
||||
.AppendLine(' LServer.OnParseAuthentication := TMVCParseAuthentication.OnParseAuthentication;')
|
||||
.AppendLine(' LServer.DefaultPort := APort;')
|
||||
.AppendLine(' LServer.KeepAlive := True;')
|
||||
.AppendLine(' LServer.MaxConnections := dotEnv.Env(''dmvc.webbroker.max_connections'', 0);')
|
||||
.AppendLine(' LServer.ListenQueue := dotEnv.Env(''dmvc.indy.listen_queue'', 500);')
|
||||
.AppendLine(' LServer.Active := True;')
|
||||
.AppendLine(' LogI(''Listening on port '' + APort.ToString);')
|
||||
.AppendLine(' LogI(''Application started. Press Ctrl+C to shut down.'');')
|
||||
.AppendLine(' WaitForTerminationSignal;')
|
||||
.AppendLine(' EnterInShutdownState;')
|
||||
.AppendLine(' LServer.Active := False;')
|
||||
.AppendLine(' finally')
|
||||
.AppendLine(' LServer.Free;')
|
||||
.AppendLine(' end;')
|
||||
.AppendLine('end;')
|
||||
end;
|
||||
|
||||
procedure TUnitRunServerProcBody.ExecuteInterface(Section: TStringBuilder;
|
||||
Model: TJsonObject);
|
||||
begin
|
||||
inherited;
|
||||
|
||||
end;
|
||||
|
||||
{ TUnitControllerEntityImplementationCommand }
|
||||
|
||||
procedure TUnitControllerEntityImplementationCommand.ExecuteImplementation(
|
||||
Section: TStringBuilder; Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
if not Model.B['entity.generate'] then Exit;
|
||||
CheckFor('entity.class_name', Model);
|
||||
Section
|
||||
.AppendLine('constructor ' + Model['entity.class_name'] + '.Create(FirstName, LastName: String; DOB: TDate);')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' inherited Create;')
|
||||
.AppendLine(' fFirstName := FirstName;')
|
||||
.AppendLine(' fLastName := LastName;')
|
||||
.AppendLine(' fDOB := DOB;')
|
||||
.AppendLine('end;')
|
||||
end;
|
||||
|
||||
{ TUnitControllerControllerImplementationCommand }
|
||||
|
||||
procedure TUnitControllerControllerImplementationCommand.ExecuteImplementation(
|
||||
Section: TStringBuilder; Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
CheckFor('controller.name', Model);
|
||||
|
||||
Section
|
||||
.AppendLine('[MVCPath(''/api'')]')
|
||||
.AppendLine(Model['controller.name'] + ' = class(TMVCController)')
|
||||
.AppendLine(' public');
|
||||
|
||||
if Model.B['controller.index_methods.generate'] then
|
||||
begin
|
||||
Section
|
||||
.AppendLine(' [MVCPath]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpGET])]')
|
||||
.AppendLine(' function Index: String;')
|
||||
.AppendLine(' [MVCPath(''/reversedstrings/($Value)'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpGET])]')
|
||||
.AppendLine(' [MVCProduces(TMVCMediaType.TEXT_PLAIN)]')
|
||||
.AppendLine(' function GetReversedString(const Value: String): String;')
|
||||
end;
|
||||
|
||||
if Model.B['controller.action_filters.generate'] then
|
||||
begin
|
||||
Section
|
||||
.AppendLine(' protected')
|
||||
.AppendLine(' procedure OnBeforeAction(Context: TWebContext; const AActionName: string; var Handled: Boolean); override;')
|
||||
.AppendLine
|
||||
.AppendLine(' procedure OnAfterAction(Context: TWebContext; const AActionName: string); override;')
|
||||
end;
|
||||
|
||||
if Model.B['controller.crud_methods.generate'] then
|
||||
begin
|
||||
Section
|
||||
.AppendLine(' public')
|
||||
.AppendLine(' //Sample CRUD Actions for a "People" entity')
|
||||
.AppendLine(' [MVCPath(''/people'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpGET])]')
|
||||
.AppendLine(' function GetPeople: TObjectList<TPerson>;')
|
||||
.AppendLine(' [MVCPath(''/people/($ID)'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpGET])]')
|
||||
.AppendLine(' function GetPerson(ID: Integer): TPerson;')
|
||||
.AppendLine(' [MVCPath(''/people'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpPOST])]')
|
||||
.AppendLine(' function CreatePerson([MVCFromBody] Person: TPerson): IMVCResponse;')
|
||||
.AppendLine(' [MVCPath(''/people/($ID)'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpPUT])]')
|
||||
.AppendLine(' function UpdatePerson(ID: Integer; [MVCFromBody] Person: TPerson): IMVCResponse;')
|
||||
.AppendLine(' [MVCPath(''/people/($ID)'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpDELETE])]')
|
||||
.AppendLine(' function DeletePerson(ID: Integer): IMVCResponse;')
|
||||
end;
|
||||
|
||||
Section
|
||||
.AppendLine('end;')
|
||||
.AppendLine
|
||||
|
||||
end;
|
||||
|
||||
end.
|
59
tools/projectgenerator/Commands.TemplatesU.pas
Normal file
59
tools/projectgenerator/Commands.TemplatesU.pas
Normal file
@ -0,0 +1,59 @@
|
||||
unit Commands.TemplatesU;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
System.Generics.Collections, CommonsU, ProjectGeneratorU;
|
||||
|
||||
procedure FillProgramTemplates(Gen: TMVCCodeGenerator);
|
||||
procedure FillControllerTemplates(Gen: TMVCCodeGenerator);
|
||||
procedure FillWebModuleTemplates(Gen: TMVCCodeGenerator);
|
||||
procedure FillWebModuleDFMTemplates(Gen: TMVCCodeGenerator);
|
||||
procedure FillJSONRPCTemplates(Gen: TMVCCodeGenerator);
|
||||
|
||||
implementation
|
||||
|
||||
uses Commands.ImplementationU, CommandsU;
|
||||
|
||||
procedure FillProgramTemplates(Gen: TMVCCodeGenerator);
|
||||
begin
|
||||
Gen.Commands.AddRange([
|
||||
TUnitProgramCommand.Create,
|
||||
TUnitRunServerProcBody.Create,
|
||||
TUnitMainBeginEndCommand.Create
|
||||
]);
|
||||
end;
|
||||
|
||||
procedure FillControllerTemplates(Gen: TMVCCodeGenerator);
|
||||
begin
|
||||
Gen.Commands.AddRange([
|
||||
TUnitControllerCommand.Create,
|
||||
TUnitControllerEntityDeclarationCommand.Create,
|
||||
TUnitControllerControllerDeclarationCommand.Create,
|
||||
TUnitFooterCommand.Create
|
||||
]);
|
||||
end;
|
||||
|
||||
procedure FillWebModuleTemplates(Gen: TMVCCodeGenerator);
|
||||
begin
|
||||
Gen.Commands.AddRange([
|
||||
TUnitWebModuleDeclarationCommand.Create
|
||||
]);
|
||||
end;
|
||||
|
||||
procedure FillJSONRPCTemplates(Gen: TMVCCodeGenerator);
|
||||
begin
|
||||
Gen.Commands.AddRange([
|
||||
TUnitJSONRPCDeclarationCommand.Create
|
||||
]);
|
||||
end;
|
||||
|
||||
procedure FillWebModuleDFMTemplates(Gen: TMVCCodeGenerator);
|
||||
begin
|
||||
Gen.Commands.AddRange([
|
||||
TWebModuleDFMCommand.Create
|
||||
]);
|
||||
end;
|
||||
|
||||
|
||||
end.
|
978
tools/projectgenerator/CommandsU.pas
Normal file
978
tools/projectgenerator/CommandsU.pas
Normal file
@ -0,0 +1,978 @@
|
||||
unit CommandsU;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
CommonsU, System.SysUtils, MVCFramework.Commons, System.DateUtils,
|
||||
JsonDataObjects;
|
||||
|
||||
type
|
||||
TUnitInterfaceKeywordCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteInterface(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
end;
|
||||
|
||||
TUnitDMVCLicenseCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteInterface(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
end;
|
||||
|
||||
|
||||
TUnitHeaderCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteInterface(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
end;
|
||||
|
||||
TUnitControllerCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteInterface(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJsonObject
|
||||
); override;
|
||||
end;
|
||||
|
||||
TUnitControllerEntityDeclarationCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteInterface(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJsonObject
|
||||
); override;
|
||||
end;
|
||||
|
||||
|
||||
TUnitControllerDeclarationCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteInterface(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
end;
|
||||
|
||||
TUnitControllerControllerDeclarationCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteInterface(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJsonObject
|
||||
); override;
|
||||
end;
|
||||
|
||||
TUnitProgramCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteInterface(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
procedure ExecuteImplementation(Section: TStringBuilder; Model: TJsonObject); override;
|
||||
end;
|
||||
|
||||
TUnitUsesCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteInterface(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
end;
|
||||
|
||||
TWebModuleDFMCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteInterface(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJsonObject); override;
|
||||
end;
|
||||
|
||||
TUnitWebModuleDeclarationCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteInterface(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJsonObject
|
||||
); override;
|
||||
end;
|
||||
|
||||
TUnitJSONRPCDeclarationCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteInterface(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJsonObject
|
||||
); override;
|
||||
end;
|
||||
|
||||
TUnitFooterCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
procedure ExecuteInterface(
|
||||
Section: TStringBuilder;
|
||||
Model: TJsonObject); override;
|
||||
end;
|
||||
|
||||
TUnitMainBeginEndCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
procedure ExecuteInterface(Section: TStringBuilder; Model: TJsonObject); override;
|
||||
end;
|
||||
|
||||
TUnitRunServerProcBody = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
procedure ExecuteInterface(Section: TStringBuilder; Model: TJsonObject); override;
|
||||
end;
|
||||
|
||||
TUnitControllerEntityImplementationCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
end;
|
||||
|
||||
TUnitControllerControllerImplementationCommand = class(TCustomCommand)
|
||||
public
|
||||
procedure ExecuteImplementation(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject
|
||||
); override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TUnitHeaderCommand }
|
||||
|
||||
procedure TUnitHeaderCommand.ExecuteInterface(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
Section
|
||||
.AppendLine('unit ' + Model['unit_name'] + ';')
|
||||
.AppendLine()
|
||||
end;
|
||||
|
||||
{ TUnitUsesCommand }
|
||||
|
||||
procedure TUnitUsesCommand.ExecuteInterface(Section: TStringBuilder;
|
||||
Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
Section
|
||||
.AppendLine('uses')
|
||||
.AppendLine(' System.SysUtils')
|
||||
.AppendLine(' ;')
|
||||
.AppendLine
|
||||
end;
|
||||
|
||||
{ TUnitDMVCLicenseCommand }
|
||||
|
||||
procedure TUnitDMVCLicenseCommand.ExecuteInterface(Section: TStringBuilder;
|
||||
Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
Section
|
||||
.AppendLine('// ***************************************************************************')
|
||||
.AppendLine('//')
|
||||
.AppendLine('// Delphi MVC Framework')
|
||||
.AppendLine('//')
|
||||
.AppendLine('// Copyright (c) 2010-' + YearOf(Date).ToString + ' Daniele Teti and the DMVCFramework Team')
|
||||
.AppendLine('//')
|
||||
.AppendLine('// https://github.com/danieleteti/delphimvcframework')
|
||||
.AppendLine('//')
|
||||
.AppendLine('// ***************************************************************************')
|
||||
.AppendLine('//')
|
||||
.AppendLine('// Licensed under the Apache License, Version 2.0 (the "License");')
|
||||
.AppendLine('// you may not use this file except in compliance with the License.')
|
||||
.AppendLine('// You may obtain a copy of the License at')
|
||||
.AppendLine('//')
|
||||
.AppendLine('// http://www.apache.org/licenses/LICENSE-2.0')
|
||||
.AppendLine('//')
|
||||
.AppendLine('// Unless required by applicable law or agreed to in writing, software')
|
||||
.AppendLine('// distributed under the License is distributed on an "AS IS" BASIS,')
|
||||
.AppendLine('// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.')
|
||||
.AppendLine('// See the License for the specific language governing permissions and')
|
||||
.AppendLine('// limitations under the License.')
|
||||
.AppendLine('//')
|
||||
.AppendLine('// This IDE expert is based off of the one included with the DUnitX')
|
||||
.AppendLine('// project. Original source by Robert Love. Adapted by Nick Hodges.')
|
||||
.AppendLine('//')
|
||||
.AppendLine('// The DUnitX project is run by Vincent Parrett and can be found at:')
|
||||
.AppendLine('//')
|
||||
.AppendLine('// https://github.com/VSoftTechnologies/DUnitX')
|
||||
.AppendLine('// ***************************************************************************')
|
||||
.AppendLine;
|
||||
end;
|
||||
|
||||
{ TUnitProgramCommand }
|
||||
|
||||
procedure TUnitProgramCommand.ExecuteImplementation(Section: TStringBuilder;
|
||||
Model: TJsonObject);
|
||||
begin
|
||||
inherited;
|
||||
|
||||
end;
|
||||
|
||||
procedure TUnitProgramCommand.ExecuteInterface(
|
||||
Section: TStringBuilder;
|
||||
Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
CheckFor('program.name', Model);
|
||||
Section
|
||||
.AppendLine('program ' + Model['program.name'] + ';')
|
||||
.AppendLine
|
||||
.AppendLine('{$APPTYPE CONSOLE}')
|
||||
.AppendLine
|
||||
.AppendLine('uses');
|
||||
|
||||
if Model['msheap'] then
|
||||
begin
|
||||
Section.AppendLine(' MSHeap,');
|
||||
end;
|
||||
|
||||
Section
|
||||
.AppendLine(' System.SysUtils,')
|
||||
.AppendLine(' Web.ReqMulti,')
|
||||
.AppendLine(' Web.WebReq,')
|
||||
.AppendLine(' Web.WebBroker,')
|
||||
.AppendLine(' IdContext,')
|
||||
.AppendLine(' IdHTTPWebBrokerBridge,')
|
||||
.AppendLine(' MVCFramework,')
|
||||
.AppendLine(' MVCFramework.Logger,')
|
||||
.AppendLine(' MVCFramework.DotEnv,')
|
||||
.AppendLine(' MVCFramework.Commons,')
|
||||
.AppendLine(' MVCFramework.Signal;')
|
||||
.AppendLine()
|
||||
.AppendLine('{$R *.res}')
|
||||
.AppendLine
|
||||
end;
|
||||
|
||||
{ TUnitControllerCommand }
|
||||
|
||||
procedure TUnitControllerCommand.ExecuteImplementation(Section: TStringBuilder;
|
||||
Model: TJsonObject);
|
||||
begin
|
||||
inherited;
|
||||
Section
|
||||
.AppendLine('implementation')
|
||||
.AppendLine
|
||||
.AppendLine('uses')
|
||||
.AppendLine(' System.StrUtils, System.SysUtils, MVCFramework.Logger;')
|
||||
.AppendLine;
|
||||
end;
|
||||
|
||||
procedure TUnitControllerCommand.ExecuteInterface(Section: TStringBuilder;
|
||||
Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
Section
|
||||
.AppendLine('unit ' + Model['controller.unit_name'] + ';')
|
||||
.AppendLine
|
||||
.AppendLine('interface')
|
||||
.AppendLine
|
||||
.AppendLine('uses')
|
||||
.AppendLine(' MVCFramework, MVCFramework.Commons, MVCFramework.Serializer.Commons, System.Generics.Collections;')
|
||||
.AppendLine
|
||||
.AppendLine('type')
|
||||
end;
|
||||
|
||||
{ TUnitControllerDeclarationCommand }
|
||||
|
||||
procedure TUnitControllerDeclarationCommand.ExecuteInterface(Section: TStringBuilder;
|
||||
Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
|
||||
|
||||
end;
|
||||
|
||||
procedure TUnitControllerEntityDeclarationCommand.ExecuteImplementation(
|
||||
Section: TStringBuilder; Model: TJsonObject);
|
||||
begin
|
||||
inherited;
|
||||
if not Model.B['entity.generate'] then Exit;
|
||||
Section
|
||||
.AppendLine('constructor ' + Model['entity.classname'] + '.Create(FirstName, LastName: String; DOB: TDate);')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' inherited Create;')
|
||||
.AppendLine(' fFirstName := FirstName;')
|
||||
.AppendLine(' fLastName := LastName;')
|
||||
.AppendLine(' fDOB := DOB;')
|
||||
.AppendLine('end;')
|
||||
end;
|
||||
|
||||
{ TUnitControllerEntitiesCommand }
|
||||
|
||||
procedure TUnitControllerEntityDeclarationCommand.ExecuteInterface(Section: TStringBuilder;
|
||||
Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
if not Model.B['entity.generate'] then Exit;
|
||||
|
||||
CheckFor('entity.classname', Model);
|
||||
Section
|
||||
.AppendLine(' [MVCNameCase(ncCamelCase)]')
|
||||
.AppendLine(' ' + Model['entity.classname'] + ' = class')
|
||||
.AppendLine(' private')
|
||||
.AppendLine(' fFirstName: String;')
|
||||
.AppendLine(' fLastName: String;')
|
||||
.AppendLine(' fDOB: TDate;')
|
||||
.AppendLine(' public')
|
||||
.AppendLine(' property FirstName: String read fFirstName write fFirstName;')
|
||||
.AppendLine(' property LastName: String read fLastName write fLastName;')
|
||||
.AppendLine(' property DOB: TDate read fDOB write fDOB; ')
|
||||
.AppendLine(' constructor Create(FirstName, LastName: String; DOB: TDate);')
|
||||
.AppendLine(' end;')
|
||||
.AppendLine
|
||||
end;
|
||||
|
||||
{ TUnitInterfaceKeywordCommand }
|
||||
|
||||
procedure TUnitInterfaceKeywordCommand.ExecuteImplementation(
|
||||
Section: TStringBuilder; Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
Section.AppendLine('implementation').AppendLine;
|
||||
end;
|
||||
|
||||
procedure TUnitInterfaceKeywordCommand.ExecuteInterface(Section: TStringBuilder;
|
||||
Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
Section.AppendLine('interface').AppendLine;
|
||||
end;
|
||||
|
||||
{ TUnitControllerControllerDeclarationCommand }
|
||||
|
||||
procedure TUnitControllerControllerDeclarationCommand.ExecuteImplementation(
|
||||
Section: TStringBuilder; Model: TJsonObject);
|
||||
begin
|
||||
inherited;
|
||||
CheckFor('controller.classname', Model);
|
||||
|
||||
if Model.B['controller.action_filters.generate'] then
|
||||
begin
|
||||
Section
|
||||
.AppendLine
|
||||
.AppendLine('procedure ' + Model['controller.classname'] + '.OnAfterAction(Context: TWebContext; const AActionName: string);')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' { Executed after each action }')
|
||||
.AppendLine(' inherited;')
|
||||
.AppendLine('end;')
|
||||
.AppendLine
|
||||
.AppendLine('procedure ' + Model['controller.classname'] + '.OnBeforeAction(Context: TWebContext; const AActionName: string; var Handled: Boolean);')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' { Executed before each action')
|
||||
.AppendLine(' if handled is true (or an exception is raised) the actual')
|
||||
.AppendLine(' action will not be called }')
|
||||
.AppendLine(' inherited;')
|
||||
.AppendLine('end;')
|
||||
end;
|
||||
|
||||
if Model.B['controller.index_methods.generate'] then
|
||||
begin
|
||||
Section
|
||||
.AppendLine
|
||||
.AppendLine('function ' + Model['controller.classname'] + '.Index: String;')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' //use Context property to access to the HTTP request and response')
|
||||
.AppendLine(' Result := ''Hello DelphiMVCFramework World'';')
|
||||
.AppendLine('end;')
|
||||
.AppendLine
|
||||
.AppendLine('function ' + Model['controller.classname'] + '.GetReversedString(const Value: String): String;')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' Result := System.StrUtils.ReverseString(Value.Trim);')
|
||||
.AppendLine('end;')
|
||||
end;
|
||||
|
||||
if Model.B['controller.crud_methods.generate'] then
|
||||
begin
|
||||
Section
|
||||
.AppendLine
|
||||
.AppendLine('//Sample CRUD Actions for a "People" entity')
|
||||
.AppendLine('function ' + Model['controller.classname'] + '.GetPeople: TObjectList<TPerson>;')
|
||||
.AppendLine('var')
|
||||
.AppendLine(' lPeople: TObjectList<TPerson>;')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' lPeople := TObjectList<TPerson>.Create(True);')
|
||||
.AppendLine(' try')
|
||||
.AppendLine(' lPeople.Add(TPerson.Create(''Peter'',''Parker'', EncodeDate(1965, 10, 4)));')
|
||||
.AppendLine(' lPeople.Add(TPerson.Create(''Bruce'',''Banner'', EncodeDate(1945, 9, 6)));')
|
||||
.AppendLine(' lPeople.Add(TPerson.Create(''Reed'',''Richards'', EncodeDate(1955, 3, 7)));')
|
||||
.AppendLine(' Result := lPeople;')
|
||||
.AppendLine(' except')
|
||||
.AppendLine(' lPeople.Free;')
|
||||
.AppendLine(' raise;')
|
||||
.AppendLine(' end;')
|
||||
.AppendLine('end;')
|
||||
.AppendLine
|
||||
.AppendLine('function ' + Model['controller.classname'] + '.GetPerson(ID: Integer): TPerson;')
|
||||
.AppendLine('var')
|
||||
.AppendLine(' lPeople: TObjectList<TPerson>;')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' lPeople := GetPeople;')
|
||||
.AppendLine(' try')
|
||||
.AppendLine(' Result := lPeople.ExtractAt(ID mod lPeople.Count);')
|
||||
.AppendLine(' finally')
|
||||
.AppendLine(' lPeople.Free;')
|
||||
.AppendLine(' end;')
|
||||
.AppendLine('end;')
|
||||
.AppendLine
|
||||
.AppendLine('function ' + Model['controller.classname'] + '.CreatePerson([MVCFromBody] Person: TPerson): IMVCResponse;')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' LogI(''Created '' + Person.FirstName + '' '' + Person.LastName);')
|
||||
.AppendLine(' Result := MVCResponseBuilder')
|
||||
.AppendLine(' .StatusCode(HTTP_STATUS.Created)')
|
||||
.AppendLine(' .Body(''Person created'')')
|
||||
.AppendLine(' .Build;')
|
||||
.AppendLine('end;')
|
||||
.AppendLine
|
||||
.AppendLine('function ' + Model['controller.classname'] + '.UpdatePerson(ID: Integer; [MVCFromBody] Person: TPerson): IMVCResponse;')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' LogI(''Updated '' + Person.FirstName + '' '' + Person.LastName);')
|
||||
.AppendLine(' Result := MVCResponseBuilder')
|
||||
.AppendLine(' .StatusCode(HTTP_STATUS.NoContent)')
|
||||
.AppendLine(' .Build;')
|
||||
.AppendLine('end;')
|
||||
.AppendLine
|
||||
.AppendLine('function ' + Model['controller.classname'] + '.DeletePerson(ID: Integer): IMVCResponse;')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' LogI(''Deleted person with id '' + ID.ToString);')
|
||||
.AppendLine(' Result := MVCResponseBuilder')
|
||||
.AppendLine(' .StatusCode(HTTP_STATUS.NoContent)')
|
||||
.AppendLine(' .Build;')
|
||||
.AppendLine('end;')
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TUnitControllerControllerDeclarationCommand.ExecuteInterface(
|
||||
Section: TStringBuilder; Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
CheckFor('controller.classname', Model);
|
||||
|
||||
Section
|
||||
.AppendLine(' [MVCPath(''/api'')]')
|
||||
.AppendLine(' ' + Model['controller.classname'] + ' = class(TMVCController)');
|
||||
|
||||
if Model.B['controller.action_filters.generate'] then
|
||||
begin
|
||||
Section
|
||||
.AppendLine(' protected')
|
||||
.AppendLine(' procedure OnBeforeAction(Context: TWebContext; const AActionName: string; var Handled: Boolean); override;')
|
||||
.AppendLine(' procedure OnAfterAction(Context: TWebContext; const AActionName: string); override;')
|
||||
end;
|
||||
|
||||
if Model.B['controller.index_methods.generate'] then
|
||||
begin
|
||||
Section
|
||||
.AppendLine(' public')
|
||||
.AppendLine(' [MVCPath]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpGET])]')
|
||||
.AppendLine(' function Index: String;')
|
||||
.AppendLine(' [MVCPath(''/reversedstrings/($Value)'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpGET])]')
|
||||
.AppendLine(' [MVCProduces(TMVCMediaType.TEXT_PLAIN)]')
|
||||
.AppendLine(' function GetReversedString(const Value: String): String;')
|
||||
end;
|
||||
|
||||
if Model.B['controller.crud_methods.generate'] then
|
||||
begin
|
||||
if not Model.B['controller.index_methods.generate'] then
|
||||
begin
|
||||
Section
|
||||
.AppendLine(' public')
|
||||
end;
|
||||
Section
|
||||
.AppendLine(' //Sample CRUD Actions for a "People" entity')
|
||||
.AppendLine(' [MVCPath(''/people'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpGET])]')
|
||||
.AppendLine(' function GetPeople: TObjectList<TPerson>;')
|
||||
.AppendLine(' [MVCPath(''/people/($ID)'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpGET])]')
|
||||
.AppendLine(' function GetPerson(ID: Integer): TPerson;')
|
||||
.AppendLine(' [MVCPath(''/people'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpPOST])]')
|
||||
.AppendLine(' function CreatePerson([MVCFromBody] Person: TPerson): IMVCResponse;')
|
||||
.AppendLine(' [MVCPath(''/people/($ID)'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpPUT])]')
|
||||
.AppendLine(' function UpdatePerson(ID: Integer; [MVCFromBody] Person: TPerson): IMVCResponse;')
|
||||
.AppendLine(' [MVCPath(''/people/($ID)'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpDELETE])]')
|
||||
.AppendLine(' function DeletePerson(ID: Integer): IMVCResponse;')
|
||||
end;
|
||||
|
||||
Section
|
||||
.AppendLine(' end;')
|
||||
.AppendLine
|
||||
|
||||
end;
|
||||
|
||||
{ TWebModuleDFMCommand }
|
||||
|
||||
procedure TWebModuleDFMCommand.ExecuteImplementation(Section: TStringBuilder;
|
||||
Model: TJsonObject);
|
||||
begin
|
||||
inherited;
|
||||
Section
|
||||
.AppendLine('object ' + Model.S['webmodule.classname'].Substring(1) + ': ' + Model['webmodule.classname'])
|
||||
.AppendLine(' OldCreateOrder = False')
|
||||
.AppendLine(' OnCreate = WebModuleCreate')
|
||||
.AppendLine(' OnDestroy = WebModuleDestroy')
|
||||
.AppendLine(' Height = 230')
|
||||
.AppendLine(' Width = 415')
|
||||
.AppendLine('end')
|
||||
end;
|
||||
|
||||
procedure TWebModuleDFMCommand.ExecuteInterface(Section: TStringBuilder;
|
||||
Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
|
||||
end;
|
||||
|
||||
{ TUnitWebModuleDeclarationCommand }
|
||||
|
||||
procedure TUnitWebModuleDeclarationCommand.ExecuteImplementation(
|
||||
Section: TStringBuilder; Model: TJsonObject);
|
||||
var
|
||||
activerecord_con_def_name: string;
|
||||
activerecord_con_def_filename: string;
|
||||
begin
|
||||
inherited;
|
||||
Section
|
||||
.AppendLine
|
||||
.AppendLine('implementation')
|
||||
.AppendLine
|
||||
.AppendLine('{$R *.dfm}')
|
||||
.AppendLine
|
||||
.AppendLine('uses')
|
||||
.AppendLine(' ' + Model['controller.unit_name'] + ',');
|
||||
|
||||
if Model.B['jsonrpc.generate'] then
|
||||
begin
|
||||
Section.AppendLine(' ' + Model['jsonrpc.unit_name'] + ',')
|
||||
end;
|
||||
|
||||
Section
|
||||
.AppendLine(' System.IOUtils,')
|
||||
.AppendLine(' MVCFramework.Commons,')
|
||||
.AppendLine(' MVCFramework.Middleware.ActiveRecord,')
|
||||
.AppendLine(' MVCFramework.Middleware.StaticFiles,')
|
||||
.AppendLine(' MVCFramework.Middleware.Analytics,')
|
||||
.AppendLine(' MVCFramework.Middleware.Trace,')
|
||||
.AppendLine(' MVCFramework.Middleware.CORS,')
|
||||
.AppendLine(' MVCFramework.Middleware.ETag,')
|
||||
.AppendLine(' MVCFramework.Middleware.Compression;')
|
||||
.AppendLine
|
||||
.AppendLine('procedure ' + Model.S['webmodule.classname'] + '.WebModuleCreate(Sender: TObject);')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' FMVC := TMVCEngine.Create(Self,')
|
||||
.AppendLine(' procedure(Config: TMVCConfig)')
|
||||
.AppendLine(' begin')
|
||||
.AppendLine(' Config.dotEnv := dotEnv; ')
|
||||
.AppendLine(' // session timeout (0 means session cookie)')
|
||||
.AppendLine(' Config[TMVCConfigKey.SessionTimeout] := dotEnv.Env(''dmvc.session_timeout'', ''0'');')
|
||||
.AppendLine(' //default content-type')
|
||||
.AppendLine(' Config[TMVCConfigKey.DefaultContentType] := dotEnv.Env(''dmvc.default.content_type'', TMVCConstants.DEFAULT_CONTENT_TYPE);')
|
||||
.AppendLine(' //default content charset')
|
||||
.AppendLine(' Config[TMVCConfigKey.DefaultContentCharset] := dotEnv.Env(''dmvc.default.content_charset'', TMVCConstants.DEFAULT_CONTENT_CHARSET);')
|
||||
.AppendLine(' //unhandled actions are permitted?')
|
||||
.AppendLine(' Config[TMVCConfigKey.AllowUnhandledAction] := dotEnv.Env(''dmvc.allow_unhandled_actions'', ''false'');')
|
||||
.AppendLine(' //enables or not system controllers loading (available only from localhost requests)')
|
||||
.AppendLine(' Config[TMVCConfigKey.LoadSystemControllers] := dotEnv.Env(''dmvc.load_system_controllers'', ''true'');')
|
||||
.AppendLine(' //default view file extension')
|
||||
.AppendLine(' Config[TMVCConfigKey.DefaultViewFileExtension] := dotEnv.Env(''dmvc.default.view_file_extension'', ''html'');')
|
||||
.AppendLine(' //view path')
|
||||
.AppendLine(' Config[TMVCConfigKey.ViewPath] := dotEnv.Env(''dmvc.view_path'', ''templates'');')
|
||||
.AppendLine(' //use cache for server side views (use "false" in debug and "true" in production for faster performances')
|
||||
.AppendLine(' Config[TMVCConfigKey.ViewCache] := dotEnv.Env(''dmvc.view_cache'', ''false'');')
|
||||
.AppendLine(' //Max Record Count for automatic Entities CRUD')
|
||||
.AppendLine(' Config[TMVCConfigKey.MaxEntitiesRecordCount] := dotEnv.Env(''dmvc.max_entities_record_count'', IntToStr(TMVCConstants.MAX_RECORD_COUNT));')
|
||||
.AppendLine(' //Enable Server Signature in response')
|
||||
.AppendLine(' Config[TMVCConfigKey.ExposeServerSignature] := dotEnv.Env(''dmvc.expose_server_signature'', ''false'');')
|
||||
.AppendLine(' //Enable X-Powered-By Header in response')
|
||||
.AppendLine(' Config[TMVCConfigKey.ExposeXPoweredBy] := dotEnv.Env(''dmvc.expose_x_powered_by'', ''true'');')
|
||||
.AppendLine(' // Max request size in bytes')
|
||||
.AppendLine(' Config[TMVCConfigKey.MaxRequestSize] := dotEnv.Env(''dmvc.max_request_size'', IntToStr(TMVCConstants.DEFAULT_MAX_REQUEST_SIZE));')
|
||||
.AppendLine(' end);')
|
||||
.AppendLine
|
||||
.AppendLine(' // Controllers')
|
||||
.AppendLine(' FMVC.AddController(' + Model['controller.classname'] + ');')
|
||||
.AppendLine(' // Controllers - END')
|
||||
.AppendLine
|
||||
.AppendLine(' // Middleware');
|
||||
|
||||
if Model.B['webmodule.middleware.analytics'] then
|
||||
begin
|
||||
Section.AppendLine(' fMVC.AddMiddleware(TMVCAnalyticsMiddleware.Create(GetAnalyticsDefaultLogger));')
|
||||
end;
|
||||
|
||||
if Model.B['webmodule.middleware.staticfiles'] then
|
||||
begin
|
||||
Section.AppendLine(' fMVC.AddMiddleware(TMVCStaticFilesMiddleware.Create(''/static'', TPath.Combine(ExtractFilePath(GetModuleName(HInstance)), ''www'')));')
|
||||
end;
|
||||
|
||||
if Model.B['webmodule.middleware.trace'] then
|
||||
begin
|
||||
Section.AppendLine(' fMVC.AddMiddleware(TMVCTraceMiddleware.Create);')
|
||||
end;
|
||||
|
||||
if Model.B['webmodule.middleware.compression'] then
|
||||
begin
|
||||
Section.AppendLine(' fMVC.AddMiddleware(TMVCCompressionMiddleware.Create);')
|
||||
end;
|
||||
|
||||
if Model.B['webmodule.middleware.etag'] then
|
||||
begin
|
||||
Section.AppendLine(' fMVC.AddMiddleware(TMVCETagMiddleware.Create);')
|
||||
end;
|
||||
|
||||
if Model.B['webmodule.middleware.cors'] then
|
||||
begin
|
||||
Section.AppendLine(' fMVC.AddMiddleware(TMVCCORSMiddleware.Create);')
|
||||
end;
|
||||
|
||||
if Model.B['webmodule.middleware.activerecord'] then
|
||||
begin
|
||||
activerecord_con_def_name := Model['webmodule.middleware.activerecord.con_def_name'];
|
||||
activerecord_con_def_filename := Model['webmodule.middleware.activerecord.con_def_filename'];
|
||||
Section
|
||||
.AppendLine(' fMVC.AddMiddleware(TMVCActiveRecordMiddleware.Create(')
|
||||
.AppendLine(' dotEnv.Env(''firedac.connection_definition_name'', ''' + activerecord_con_def_name + '''),')
|
||||
.AppendLine(' dotEnv.Env(''firedac.connection_definitions_filename'', ''' + activerecord_con_def_filename + ''')')
|
||||
.AppendLine(' ));')
|
||||
end;
|
||||
|
||||
Section
|
||||
.AppendLine(' // Middleware - END');
|
||||
|
||||
if Model.B['jsonrpc.generate'] then
|
||||
begin
|
||||
Section
|
||||
.AppendLine
|
||||
.AppendLine(' // JSONRPC')
|
||||
.AppendLine(' fMVC.PublishObject(')
|
||||
.AppendLine(' function : TObject')
|
||||
.AppendLine(' begin')
|
||||
.AppendLine(' Result := ' + Model['jsonrpc.classname'] + '.Create;')
|
||||
.AppendLine(' end, ''/jsonrpc'');')
|
||||
.AppendLine(' // JSONRPC - END')
|
||||
end;
|
||||
|
||||
Section
|
||||
.AppendLine
|
||||
.AppendLine('end;')
|
||||
.AppendLine
|
||||
.AppendLine('procedure ' + Model.S['webmodule.classname'] + '.WebModuleDestroy(Sender: TObject);')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' FMVC.Free;')
|
||||
.AppendLine('end;')
|
||||
.AppendLine
|
||||
.AppendLine('end.')
|
||||
end;
|
||||
|
||||
procedure TUnitWebModuleDeclarationCommand.ExecuteInterface(
|
||||
Section: TStringBuilder; Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
CheckFor('webmodule.classname', Model);
|
||||
Section
|
||||
.AppendLine('unit ' + Model.S['webmodule.classname'].Substring(1) + 'U;')
|
||||
.AppendLine('')
|
||||
.AppendLine('interface')
|
||||
.AppendLine
|
||||
.AppendLine('uses ')
|
||||
.AppendLine(' System.SysUtils,')
|
||||
.AppendLine(' System.Classes,')
|
||||
.AppendLine(' Web.HTTPApp,')
|
||||
.AppendLine(' MVCFramework;')
|
||||
.AppendLine
|
||||
.AppendLine('type')
|
||||
.AppendLine(' ' + Model.S['webmodule.classname'] + ' = class(TWebModule)')
|
||||
.AppendLine(' procedure WebModuleCreate(Sender: TObject);')
|
||||
.AppendLine(' procedure WebModuleDestroy(Sender: TObject);')
|
||||
.AppendLine(' private')
|
||||
.AppendLine(' fMVC: TMVCEngine;')
|
||||
.AppendLine(' end;')
|
||||
.AppendLine
|
||||
.AppendLine('var')
|
||||
.AppendLine(' WebModuleClass: TComponentClass = ' + Model.S['webmodule.classname'] + ';')
|
||||
end;
|
||||
|
||||
{ TUnitJSONRPCDeclarationCommand }
|
||||
|
||||
procedure TUnitJSONRPCDeclarationCommand.ExecuteImplementation(
|
||||
Section: TStringBuilder; Model: TJsonObject);
|
||||
begin
|
||||
inherited;
|
||||
Section
|
||||
.AppendLine('implementation')
|
||||
.AppendLine
|
||||
.AppendLine('uses')
|
||||
.AppendLine(' System.StrUtils;')
|
||||
.AppendLine
|
||||
.AppendLine('function ' + Model.S['jsonrpc.classname'] + '.ReverseString(const Value: String): String;')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' Result := System.StrUtils.ReverseString(Value);')
|
||||
.AppendLine('end;')
|
||||
.AppendLine
|
||||
.AppendLine('end.')
|
||||
end;
|
||||
|
||||
procedure TUnitJSONRPCDeclarationCommand.ExecuteInterface(
|
||||
Section: TStringBuilder; Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
Section
|
||||
.AppendLine('unit ' + Model['jsonrpc.unit_name'] + ';')
|
||||
.AppendLine
|
||||
.AppendLine('interface')
|
||||
.AppendLine
|
||||
.AppendLine('type')
|
||||
.AppendLine(' ' + Model['jsonrpc.classname'] + ' = class')
|
||||
.AppendLine(' public')
|
||||
.AppendLine(' function ReverseString(const Value: String): String;')
|
||||
.AppendLine(' end;')
|
||||
.AppendLine;
|
||||
end;
|
||||
|
||||
{ TUnitFooterCommand }
|
||||
|
||||
procedure TUnitFooterCommand.ExecuteImplementation(Section: TStringBuilder;
|
||||
Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
Section.AppendLine.AppendLine('end.');
|
||||
end;
|
||||
|
||||
procedure TUnitFooterCommand.ExecuteInterface(Section: TStringBuilder;
|
||||
Model: TJsonObject);
|
||||
begin
|
||||
inherited;
|
||||
|
||||
end;
|
||||
|
||||
{ TUnitMainBeginEndCommand }
|
||||
|
||||
procedure TUnitMainBeginEndCommand.ExecuteImplementation(Section: TStringBuilder;
|
||||
Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
Section
|
||||
.AppendLine
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' { Enable ReportMemoryLeaksOnShutdown during debug }')
|
||||
.AppendLine(' // ReportMemoryLeaksOnShutdown := True;')
|
||||
.AppendLine(' IsMultiThread := True;')
|
||||
.AppendLine(' // DMVCFramework Specific Configuration ')
|
||||
.AppendLine(' // When MVCSerializeNulls = True empty nullables and nil are serialized as json null.')
|
||||
.AppendLine(' // When MVCSerializeNulls = False empty nullables and nil are not serialized at all.')
|
||||
.AppendLine(' MVCSerializeNulls := True;')
|
||||
.AppendLine(' UseConsoleLogger := True;')
|
||||
.AppendLine
|
||||
.AppendLine(' LogI(''** DMVCFramework Server ** build '' + DMVCFRAMEWORK_VERSION);')
|
||||
.AppendLine(' try')
|
||||
.AppendLine(' if WebRequestHandler <> nil then')
|
||||
.AppendLine(' WebRequestHandler.WebModuleClass := WebModuleClass;')
|
||||
.AppendLine
|
||||
.AppendLine(' dotEnvConfigure(')
|
||||
.AppendLine(' function: IMVCDotEnv')
|
||||
.AppendLine(' begin')
|
||||
.AppendLine(' Result := NewDotEnv')
|
||||
.AppendLine(' .UseStrategy(TMVCDotEnvPriority.FileThenEnv)')
|
||||
.AppendLine(' //if available, by default, loads default environment (.env)')
|
||||
.AppendLine(' .UseProfile(''test'') //if available loads the test environment (.env.test)')
|
||||
.AppendLine(' .UseProfile(''prod'') //if available loads the prod environment (.env.prod)')
|
||||
.AppendLine(' .UseLogger(procedure(LogItem: String)')
|
||||
.AppendLine(' begin')
|
||||
.AppendLine(' LogD(''dotEnv: '' + LogItem);')
|
||||
.AppendLine(' end)')
|
||||
.AppendLine(' .Build(); //uses the executable folder to look for .env* files')
|
||||
.AppendLine(' end);')
|
||||
.AppendLine
|
||||
.AppendLine(' WebRequestHandlerProc.MaxConnections := dotEnv.Env(''dmvc.handler.max_connections'', 1024);')
|
||||
.AppendLine
|
||||
.AppendLine('{$IF Defined(SYDNEYORBETTER)}')
|
||||
.AppendLine(' if dotEnv.Env(''dmvc.profiler.enabled'', false) then')
|
||||
.AppendLine(' begin')
|
||||
.AppendLine(' Profiler.ProfileLogger := Log;')
|
||||
.AppendLine(' Profiler.WarningThreshold := dotEnv.Env(''dmvc.profiler.warning_threshold'', 2000);')
|
||||
.AppendLine(' end;')
|
||||
.AppendLine('{$ENDIF}')
|
||||
.AppendLine
|
||||
.AppendLine(' RunServer(dotEnv.Env(''dmvc.server.port'', ' + Model['program.default_server_port'] + '));')
|
||||
.AppendLine(' except')
|
||||
.AppendLine(' on E: Exception do')
|
||||
.AppendLine(' LogF(E.ClassName + '': '' + E.Message);')
|
||||
.AppendLine(' end;')
|
||||
.AppendLine('end.')
|
||||
end;
|
||||
|
||||
procedure TUnitMainBeginEndCommand.ExecuteInterface(Section: TStringBuilder;
|
||||
Model: TJsonObject);
|
||||
begin
|
||||
inherited;
|
||||
|
||||
end;
|
||||
|
||||
{ TUnitRunServerProcBody }
|
||||
|
||||
procedure TUnitRunServerProcBody.ExecuteImplementation(Section: TStringBuilder;
|
||||
Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
Section
|
||||
.AppendLine('procedure RunServer(APort: Integer);')
|
||||
.AppendLine('var')
|
||||
.AppendLine(' LServer: TIdHTTPWebBrokerBridge;')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' LServer := TIdHTTPWebBrokerBridge.Create(nil);')
|
||||
.AppendLine(' try')
|
||||
.AppendLine(' LServer.OnParseAuthentication := TMVCParseAuthentication.OnParseAuthentication;')
|
||||
.AppendLine(' LServer.DefaultPort := APort;')
|
||||
.AppendLine(' LServer.KeepAlive := True;')
|
||||
.AppendLine(' LServer.MaxConnections := dotEnv.Env(''dmvc.webbroker.max_connections'', 0);')
|
||||
.AppendLine(' LServer.ListenQueue := dotEnv.Env(''dmvc.indy.listen_queue'', 500);')
|
||||
.AppendLine(' LServer.Active := True;')
|
||||
.AppendLine(' LogI(''Listening on port '' + APort.ToString);')
|
||||
.AppendLine(' LogI(''Application started. Press Ctrl+C to shut down.'');')
|
||||
.AppendLine(' WaitForTerminationSignal;')
|
||||
.AppendLine(' EnterInShutdownState;')
|
||||
.AppendLine(' LServer.Active := False;')
|
||||
.AppendLine(' finally')
|
||||
.AppendLine(' LServer.Free;')
|
||||
.AppendLine(' end;')
|
||||
.AppendLine('end;')
|
||||
end;
|
||||
|
||||
procedure TUnitRunServerProcBody.ExecuteInterface(Section: TStringBuilder;
|
||||
Model: TJsonObject);
|
||||
begin
|
||||
inherited;
|
||||
|
||||
end;
|
||||
|
||||
{ TUnitControllerEntityImplementationCommand }
|
||||
|
||||
procedure TUnitControllerEntityImplementationCommand.ExecuteImplementation(
|
||||
Section: TStringBuilder; Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
if not Model.B['entity.generate'] then Exit;
|
||||
CheckFor('entity.class_name', Model);
|
||||
Section
|
||||
.AppendLine('constructor ' + Model['entity.class_name'] + '.Create(FirstName, LastName: String; DOB: TDate);')
|
||||
.AppendLine('begin')
|
||||
.AppendLine(' inherited Create;')
|
||||
.AppendLine(' fFirstName := FirstName;')
|
||||
.AppendLine(' fLastName := LastName;')
|
||||
.AppendLine(' fDOB := DOB;')
|
||||
.AppendLine('end;')
|
||||
end;
|
||||
|
||||
{ TUnitControllerControllerImplementationCommand }
|
||||
|
||||
procedure TUnitControllerControllerImplementationCommand.ExecuteImplementation(
|
||||
Section: TStringBuilder; Model: TJSONObject);
|
||||
begin
|
||||
inherited;
|
||||
CheckFor('controller.name', Model);
|
||||
|
||||
Section
|
||||
.AppendLine('[MVCPath(''/api'')]')
|
||||
.AppendLine(Model['controller.name'] + ' = class(TMVCController)')
|
||||
.AppendLine(' public');
|
||||
|
||||
if Model.B['controller.index_methods.generate'] then
|
||||
begin
|
||||
Section
|
||||
.AppendLine(' [MVCPath]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpGET])]')
|
||||
.AppendLine(' function Index: String;')
|
||||
.AppendLine(' [MVCPath(''/reversedstrings/($Value)'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpGET])]')
|
||||
.AppendLine(' [MVCProduces(TMVCMediaType.TEXT_PLAIN)]')
|
||||
.AppendLine(' function GetReversedString(const Value: String): String;')
|
||||
end;
|
||||
|
||||
if Model.B['controller.action_filters.generate'] then
|
||||
begin
|
||||
Section
|
||||
.AppendLine(' protected')
|
||||
.AppendLine(' procedure OnBeforeAction(Context: TWebContext; const AActionName: string; var Handled: Boolean); override;')
|
||||
.AppendLine
|
||||
.AppendLine(' procedure OnAfterAction(Context: TWebContext; const AActionName: string); override;')
|
||||
end;
|
||||
|
||||
if Model.B['controller.crud_methods.generate'] then
|
||||
begin
|
||||
Section
|
||||
.AppendLine(' public')
|
||||
.AppendLine(' //Sample CRUD Actions for a "People" entity')
|
||||
.AppendLine(' [MVCPath(''/people'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpGET])]')
|
||||
.AppendLine(' function GetPeople: TObjectList<TPerson>;')
|
||||
.AppendLine(' [MVCPath(''/people/($ID)'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpGET])]')
|
||||
.AppendLine(' function GetPerson(ID: Integer): TPerson;')
|
||||
.AppendLine(' [MVCPath(''/people'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpPOST])]')
|
||||
.AppendLine(' function CreatePerson([MVCFromBody] Person: TPerson): IMVCResponse;')
|
||||
.AppendLine(' [MVCPath(''/people/($ID)'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpPUT])]')
|
||||
.AppendLine(' function UpdatePerson(ID: Integer; [MVCFromBody] Person: TPerson): IMVCResponse;')
|
||||
.AppendLine(' [MVCPath(''/people/($ID)'')]')
|
||||
.AppendLine(' [MVCHTTPMethod([httpDELETE])]')
|
||||
.AppendLine(' function DeletePerson(ID: Integer): IMVCResponse;')
|
||||
end;
|
||||
|
||||
Section
|
||||
.AppendLine('end;')
|
||||
.AppendLine
|
||||
|
||||
end;
|
||||
|
||||
end.
|
36
tools/projectgenerator/CommonsU.pas
Normal file
36
tools/projectgenerator/CommonsU.pas
Normal file
@ -0,0 +1,36 @@
|
||||
unit CommonsU;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
MVCFramework.Commons, System.SysUtils, JsonDataObjects;
|
||||
|
||||
type
|
||||
IGenCommand = interface
|
||||
['{B5F6B048-FB5A-48EA-80F9-D8395B4DE40D}']
|
||||
procedure ExecuteInterface(Section: TStringBuilder; Model: TJSONObject);
|
||||
procedure ExecuteImplementation(Section: TStringBuilder; Model: TJSONObject);
|
||||
end;
|
||||
|
||||
TCustomCommand = class abstract(TInterfacedObject, IGenCommand)
|
||||
protected
|
||||
procedure CheckFor(const Key: String; Model: TJSONObject);
|
||||
public
|
||||
procedure ExecuteInterface(Section: TStringBuilder; Model: TJSONObject); virtual; abstract;
|
||||
procedure ExecuteImplementation(Section: TStringBuilder; Model: TJSONObject); virtual; abstract;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TCustomCommand }
|
||||
|
||||
procedure TCustomCommand.CheckFor(const Key: String;
|
||||
Model: TJSONObject);
|
||||
begin
|
||||
if not Model.Contains(Key) then
|
||||
begin
|
||||
raise Exception.CreateFmt('Required key "%s" not found while processing %s', [Key, ClassName]);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
77
tools/projectgenerator/ProjectGeneratorU.pas
Normal file
77
tools/projectgenerator/ProjectGeneratorU.pas
Normal file
@ -0,0 +1,77 @@
|
||||
unit ProjectGeneratorU;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
MVCFramework.Commons, System.SysUtils, System.Generics.Collections, CommonsU,
|
||||
JsonDataObjects;
|
||||
|
||||
type
|
||||
TMVCCodeGenerator = class
|
||||
private
|
||||
fIntf: TStringBuilder;
|
||||
fImpl: TStringBuilder;
|
||||
fCommands: TList<IGenCommand>;
|
||||
fSource: string;
|
||||
public
|
||||
constructor Create; virtual;
|
||||
destructor Destroy; override;
|
||||
procedure Execute(Model: TJSONObject);
|
||||
function Commands: TList<IGenCommand>;
|
||||
function Source: String;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
function TMVCCodeGenerator.Commands: TList<IGenCommand>;
|
||||
begin
|
||||
Result := fCommands;
|
||||
end;
|
||||
|
||||
constructor TMVCCodeGenerator.Create;
|
||||
begin
|
||||
inherited;
|
||||
fCommands := TList<IGenCommand>.Create;
|
||||
fSource := '';
|
||||
end;
|
||||
|
||||
destructor TMVCCodeGenerator.Destroy;
|
||||
begin
|
||||
fCommands.Free;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
{ TMVCProjectGenerator }
|
||||
|
||||
procedure TMVCCodeGenerator.Execute(Model: TJSONObject);
|
||||
var
|
||||
I: Integer;
|
||||
begin
|
||||
fSource := '';
|
||||
fIntf := TStringBuilder.Create;
|
||||
try
|
||||
fImpl := TStringBuilder.Create;
|
||||
try
|
||||
for I := 0 to fCommands.Count - 1 do
|
||||
begin
|
||||
fCommands[I].ExecuteInterface(fIntf, Model);
|
||||
fCommands[I].ExecuteImplementation(fImpl, Model);
|
||||
end;
|
||||
fSource := fIntf.ToString + fImpl.ToString;
|
||||
finally
|
||||
fImpl.Free;
|
||||
end;
|
||||
finally
|
||||
fIntf.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TIntfCommand }
|
||||
|
||||
function TMVCCodeGenerator.Source: String;
|
||||
begin
|
||||
Result := fSource;
|
||||
end;
|
||||
|
||||
end.
|
109
tools/projectgenerator/dmvcprjgen.dpr
Normal file
109
tools/projectgenerator/dmvcprjgen.dpr
Normal file
@ -0,0 +1,109 @@
|
||||
program dmvcprjgen;
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
{$R *.res}
|
||||
|
||||
uses
|
||||
System.SysUtils,
|
||||
System.Generics.Collections,
|
||||
MVCFramework.Rtti.Utils,
|
||||
ProjectGeneratorU in 'ProjectGeneratorU.pas',
|
||||
CommandsU in 'CommandsU.pas',
|
||||
CommonsU in 'CommonsU.pas',
|
||||
MVCFramework.Commons,
|
||||
Commands.TemplatesU in 'Commands.TemplatesU.pas',
|
||||
System.IOUtils,
|
||||
JsonDataObjects;
|
||||
|
||||
function GenerateSource(JSON: TJSONObject; FillerProc: TProc<TMVCCodeGenerator>): String;
|
||||
var
|
||||
lGenerator: TMVCCodeGenerator;
|
||||
begin
|
||||
lGenerator := TMVCCodeGenerator.Create;
|
||||
try
|
||||
lGenerator.Commands.Clear;
|
||||
FillerProc(lGenerator);
|
||||
lGenerator.Execute(JSON);
|
||||
Result := lGenerator.Source;
|
||||
finally
|
||||
lGenerator.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure Main;
|
||||
begin
|
||||
var lJSON := TJSONObject.Create;
|
||||
try
|
||||
lJSON.S['program.name'] := 'MyProgram';
|
||||
lJSON.S['program.default_server_port'] := '8080';
|
||||
lJSON.S['controller.unit_name'] := 'MyControllerU';
|
||||
lJSON.S['controller.classname'] := 'TMyController';
|
||||
lJSON.B['controller.index_methods.generate'] := true;
|
||||
lJSON.B['controller.action_filters.generate'] := true;
|
||||
lJSON.B['controller.crud_methods.generate'] := true;
|
||||
lJSON.B['entity.generate'] := true;
|
||||
lJSON.S['entity.classname'] := 'TPerson';
|
||||
lJSON.B['jsonrpc.generate'] := true;
|
||||
lJSON.S['jsonrpc.classname'] := 'TMyJSONRPC';
|
||||
lJSON.S['jsonrpc.unit_name'] := 'MyJSONRPCU';
|
||||
|
||||
//webmodule
|
||||
|
||||
lJSON.S['webmodule.classname'] := 'TMyWebModule';
|
||||
lJSON.B['webmodule.middleware.analytics'] := true;
|
||||
lJSON.B['webmodule.middleware.staticfiles'] := true;
|
||||
lJSON.B['webmodule.middleware.trace'] := true;
|
||||
lJSON.B['webmodule.middleware.compression'] := true;
|
||||
lJSON.B['webmodule.middleware.etag'] := true;
|
||||
lJSON.B['webmodule.middleware.cors'] := true;
|
||||
lJSON.B['webmodule.middleware.activerecord'] := true;
|
||||
lJSON.S['webmodule.middleware.activerecord.con_def_name'] := 'MyConnection';
|
||||
lJSON.S['webmodule.middleware.activerecord.con_def_filename'] := '';
|
||||
|
||||
//webmodule - end
|
||||
|
||||
|
||||
lJSON.B['msheap'] := true;
|
||||
TFile.WriteAllText(lJSON.S['program.name'] + '.dpr', GenerateSource(lJSON,
|
||||
procedure (Gen: TMVCCodeGenerator)
|
||||
begin
|
||||
FillProgramTemplates(Gen)
|
||||
end));
|
||||
TFile.WriteAllText('MyControllerU.pas', GenerateSource(lJSON,
|
||||
procedure (Gen: TMVCCodeGenerator)
|
||||
begin
|
||||
FillControllerTemplates(Gen)
|
||||
end));
|
||||
TFile.WriteAllText('MyWebModuleU.pas', GenerateSource(lJSON,
|
||||
procedure (Gen: TMVCCodeGenerator)
|
||||
begin
|
||||
FillWebModuleTemplates(Gen)
|
||||
end));
|
||||
TFile.WriteAllText('MyWebModuleU.dfm', GenerateSource(lJSON,
|
||||
procedure (Gen: TMVCCodeGenerator)
|
||||
begin
|
||||
FillWebModuleDFMTemplates(Gen)
|
||||
end));
|
||||
if lJSON.B['jsonrpc.generate'] then
|
||||
begin
|
||||
TFile.WriteAllText('MyJSONRPCU.pas', GenerateSource(lJSON,
|
||||
procedure (Gen: TMVCCodeGenerator)
|
||||
begin
|
||||
FillJSONRPCTemplates(Gen)
|
||||
end));
|
||||
end;
|
||||
|
||||
finally
|
||||
lJSON.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
try
|
||||
Main;
|
||||
except
|
||||
on E: Exception do
|
||||
Writeln(E.ClassName, ': ', E.Message);
|
||||
end;
|
||||
end.
|
1112
tools/projectgenerator/dmvcprjgen.dproj
Normal file
1112
tools/projectgenerator/dmvcprjgen.dproj
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user