Removed dotEnv(<instance>), introduced dotEnvConfigure(TFunc<IMVCDotEnv>); ide expert updated accordingly

This commit is contained in:
Daniele Teti 2023-06-14 17:57:33 +02:00
parent 93ee4225f4
commit 9c5cdecccc
12 changed files with 230 additions and 165 deletions

1
.gitignore vendored
View File

@ -143,3 +143,4 @@ samples/WineCellarSample/winecellarclient_mobile/Android/Debug/strings.xml
samples/WineCellarSample/winecellarclient_mobile/Android/Debug/styles.xml
samples/WineCellarSample/winecellarclient_mobile/Android/Debug/styles-v21.xml
samples/WineCellarSample/winecellarclient_mobile/Android/Debug/WineCellarMobileClient.classes/classes.dex
samples/apachemodule/Apache24/logs/httpd.pid

View File

@ -101,18 +101,20 @@ resourcestring
' if WebRequestHandler <> nil then' + sLineBreak +
' WebRequestHandler.WebModuleClass := WebModuleClass;' + sLineBreak +
'' + sLineBreak +
' dotEnv(' + sLineBreak +
' NewDotEnv' + sLineBreak +
' .WithStrategy(TMVCDotEnvPriority.FileThenEnv)' + sLineBreak +
' //if available, by default, loads default environment (.env)' + sLineBreak +
' .UseProfile(''test'') //if available loads the test environment (.env.test)' + sLineBreak +
' .UseProfile(''prod'') //if available loads the prod environment (.env.prod)' + sLineBreak +
' .UseLogger(procedure(LogItem: String)' + sLineBreak +
' begin' + sLineBreak +
' LogW(''dotEnv: '' + LogItem);' + sLineBreak +
' end)' + sLineBreak +
' .Build() //uses the executable folder to look for .env* files' + sLineBreak +
' );' + sLineBreak +
' dotEnvConfigure(' + sLineBreak +
' function: IMVCDotEnv' + sLineBreak +
' begin' + sLineBreak +
' Result := NewDotEnv' + sLineBreak +
' .WithStrategy(TMVCDotEnvPriority.FileThenEnv)' + sLineBreak +
' //if available, by default, loads default environment (.env)' + sLineBreak +
' .UseProfile(''test'') //if available loads the test environment (.env.test)' + sLineBreak +
' .UseProfile(''prod'') //if available loads the prod environment (.env.prod)' + sLineBreak +
' .UseLogger(procedure(LogItem: String)' + sLineBreak +
' begin' + sLineBreak +
' LogW(''dotEnv: '' + LogItem);' + sLineBreak +
' end)' + sLineBreak +
' .Build(); //uses the executable folder to look for .env* files' + sLineBreak +
' end);' + sLineBreak +
'' + sLineBreak +
' WebRequestHandlerProc.MaxConnections := dotEnv.Env(''dmvc.handler.max_connections'', 1024);' + sLineBreak +
' RunServer(dotEnv.Env(''dmvc.server.port'', %1:d));' + sLineBreak +

View File

@ -1,5 +1,4 @@
object WineCellarDataModule: TWineCellarDataModule
OldCreateOrder = False
Height = 211
Width = 336
object Connection: TFDConnection

View File

@ -5,6 +5,7 @@ interface
uses
System.SysUtils,
System.Classes,
MVCFramework.Commons,
Data.DB,
Data.SqlExpr,
@ -59,7 +60,6 @@ implementation
uses
System.StrUtils,
Data.DBXCommon,
MVCFramework.FireDAC.Utils;
{ TCellarSM }
@ -80,19 +80,28 @@ procedure TWineCellarDataModule.ConnectionBeforeConnect(Sender: TObject);
var
lDBPath: string;
begin
// if you are using firebird 2.5, uses the file WINES_FB25.FDB
if not IsLibrary then
// if database is defined in .env use that, otherwise try to
// understand where the database is
if not dotEnv.Env('database.path').IsEmpty then
begin
// Is compiled as EXE
Connection.Params.Values['Database'] := ExtractFilePath(ParamStr(0)) + '..\..\WINES_FB30.FDB';
Connection.Params.Values['Database'] := dotEnv.Env('database.path');
end
else
begin
// compiled as apache module or isapi
lDBPath := ExtractFilePath(GetModuleName(HInstance)) + '..\..\..\winecellarserver\WINES_FB30.FDB';
if lDBPath.StartsWith('\\?\') then
lDBPath := lDBPath.Remove(0, 4);
Connection.Params.Values['Database'] := lDBPath;
// if you are using firebird 2.5, uses the file WINES_FB25.FDB
if not IsLibrary then
begin
// Is compiled as EXE
Connection.Params.Values['Database'] := ExtractFilePath(ParamStr(0)) + '..\..\WINES_FB30.FDB';
end
else
begin
// compiled as apache module or isapi
lDBPath := ExtractFilePath(GetModuleName(HInstance)) + '..\..\..\WineCellarSample\winecellarserver\WINES_FB30.FDB';
if lDBPath.StartsWith('\\?\') then
lDBPath := lDBPath.Remove(0, 4);
Connection.Params.Values['Database'] := lDBPath;
end;
end;
end;

View File

@ -6,7 +6,11 @@ uses
System.SysUtils,
System.Classes,
Web.HTTPApp,
MVCFramework;
MVCFramework,
MVCFramework.Commons,
MVCFramework.Logger,
MVCFramework.DotEnv
;
type
Twm = class(TWebModule)
@ -14,9 +18,6 @@ type
private
MVCEngine: TMVCEngine;
public
{ Public declarations }
end;
var
@ -26,7 +27,6 @@ implementation
uses
WineCellarAppControllerU,
MVCFramework.Commons,
MVCFramework.Middleware.StaticFiles,
System.IOUtils;

View File

@ -57,7 +57,7 @@ ServerRoot ${serverroot}
# prevent Apache from glomming onto all bound IP addresses.
#
#Listen 12.34.56.78:80
Listen 80
Listen 8080
#
# Dynamic Shared Object (DSO) Support

View File

@ -1 +0,0 @@
14916

View File

@ -0,0 +1 @@
database.path = C:\DEV\dmvcframework\samples\WineCellarSample\winecellarserver\WINES_FB30.FDB

View File

@ -8,6 +8,9 @@ uses
Web.ApacheApp,
Web.HTTPD24Impl,
MVCFramework.Logger,
MVCFramework.DotEnv,
MVCFramework.Commons,
Web.HTTPDMethods,
Winapi.Windows,
System.Classes,
MainDataModuleUnit in '..\WineCellarSample\winecellarserver\MainDataModuleUnit.pas' {WineCellarDataModule: TDataModule},
@ -45,7 +48,37 @@ exports
Navigate to http://localhost/winecellar/
}
procedure RegisterLogger(const p: Pointer);
begin
dotEnv(
NewDotEnv
.WithStrategy(TMVCDotEnvPriority.FileThenEnv)
//if available, by default, loads default environment (.env)
.UseProfile('test') //if available loads the test environment (.env.test)
.UseProfile('prod') //if available loads the prod environment (.env.prod)
.UseLogger(procedure(LogItem: String)
begin
LogW('dotEnv: ' + LogItem);
end)
.Build() //uses the executable folder to look for .env* files
);
end;
begin
UseDotEnvDelegate(
function : IMVCDotEnv
begin
Result := NewDotEnv
.WithStrategy(TMVCDotEnvPriority.FileThenEnv)
//if available, by default, loads default environment (.env)
.UseProfile('test') //if available loads the test environment (.env.test)
.UseProfile('prod') //if available loads the prod environment (.env.prod)
.UseLogger(procedure(LogItem: String)
begin
LogW('dotEnv: ' + LogItem);
end)
.Build(); //uses the executable folder to look for .env* files
end);
CoInitFlags := COINIT_MULTITHREADED;
Web.ApacheApp.InitApplication(@GModuleData);
Application.Initialize;

View File

@ -75,8 +75,7 @@
<DCC_RemoteDebug>true</DCC_RemoteDebug>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
<Debugger_RunParams>-X</Debugger_RunParams>
<Debugger_HostApplication>.\apache24\bin\httpd.exe</Debugger_HostApplication>
<Debugger_HostApplication>apache24\bin\httpd.exe</Debugger_HostApplication>
<VerInfo_Locale>1033</VerInfo_Locale>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<DCC_ExeOutput>.\Apache24\modules</DCC_ExeOutput>
@ -94,12 +93,10 @@
</DelphiCompile>
<DCCReference Include="..\WineCellarSample\winecellarserver\MainDataModuleUnit.pas">
<Form>WineCellarDataModule</Form>
<FormType>dfm</FormType>
<DesignClass>TDataModule</DesignClass>
</DCCReference>
<DCCReference Include="..\WineCellarSample\winecellarserver\MainWebModuleUnit.pas">
<Form>wm</Form>
<FormType>dfm</FormType>
<DesignClass>TWebModule</DesignClass>
</DCCReference>
<DCCReference Include="..\WineCellarSample\winecellarserver\WineCellarAppControllerU.pas"/>
@ -527,6 +524,127 @@
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android">
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXDebug"/>
<DeployClass Name="ProjectOSXEntitlements"/>
<DeployClass Name="ProjectOSXInfoPList"/>
<DeployClass Name="ProjectOSXResource">
<Platform Name="OSX32">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSXARM64">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="ProjectOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\arm64-v8a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<Operation>1</Operation>
</Platform>
<Platform Name="Linux64">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<Operation>1</Operation>
</Platform>
<Platform Name="OSXARM64">
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOutput_Android32">
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectUWPManifest">
<Platform Name="Win32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceDebug">
<Platform Name="iOSDevice32">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSEntitlements"/>
<DeployClass Name="ProjectiOSInfoPList"/>
<DeployClass Name="ProjectiOSLaunchScreen"/>
<DeployClass Name="ProjectiOSResource">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo150">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo44">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iOS_AppStore1024">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
@ -727,127 +845,6 @@
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android">
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceDebug">
<Platform Name="iOSDevice32">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSEntitlements"/>
<DeployClass Name="ProjectiOSInfoPList"/>
<DeployClass Name="ProjectiOSLaunchScreen"/>
<DeployClass Name="ProjectiOSResource">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXDebug"/>
<DeployClass Name="ProjectOSXEntitlements"/>
<DeployClass Name="ProjectOSXInfoPList"/>
<DeployClass Name="ProjectOSXResource">
<Platform Name="OSX32">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSXARM64">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="ProjectOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\arm64-v8a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<Operation>1</Operation>
</Platform>
<Platform Name="Linux64">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<Operation>1</Operation>
</Platform>
<Platform Name="OSXARM64">
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOutput_Android32">
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectUWPManifest">
<Platform Name="Win32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo150">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo44">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Android64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>

View File

@ -48,14 +48,16 @@ begin
if WebRequestHandler <> nil then
WebRequestHandler.WebModuleClass := WebModuleClass;
dotEnv(
NewDotEnv
dotEnvConfigure(
function : IMVCDotEnv
begin
Result := NewDotEnv
.WithStrategy(TMVCDotEnvPriority.FileThenEnv)
//if available, by default, loads default environment (.env)
.UseProfile('test') //if available loads the test environment (.env.test)
.UseProfile('prod') //if available loads the prod environment (.env.prod)
.Build() //uses the executable folder to look for .env* files
);
.Build(); //uses the executable folder to look for .env* files
end);
WebRequestHandlerProc.MaxConnections := dotEnv.Env('dmvc.handler.max_connections', 1024);
RunServer(dotEnv.Env('dmvc.server.port', 9999));

View File

@ -760,8 +760,8 @@ type
VPassword: string; var VHandled: Boolean);
end;
procedure dotEnv(const dotEnv: IMVCDotEnv); overload;
function dotEnv: IMVCDotEnv; overload;
procedure dotEnvConfigure(const dotEnvDelegate: TFunc<IMVCDotEnv>);
implementation
@ -779,6 +779,7 @@ var
GlobalAppName, GlobalAppPath, GlobalAppExe: string;
var
GdotEnv: IMVCDotEnv = nil;
GdotEnvDelegate: TFunc<IMVCDotEnv> = nil;
function URLEncode(const Value: string): string; overload;
@ -1735,16 +1736,37 @@ begin
Result := ReasonStringByHTTPStatusCode(HTTPStatusCode);
end;
procedure dotEnv(const dotEnv: IMVCDotEnv);
procedure dotEnvConfigure(const dotEnvDelegate: TFunc<IMVCDotEnv>);
begin
Assert(GdotEnv = nil, 'dotEnv already set');
GdotEnv := dotEnv;
if GdotEnv <> nil then
begin
raise EMVCDotEnv.Create('dotEnv already initialized');
end;
GdotEnvDelegate := dotEnvDelegate;
end;
function dotEnv: IMVCDotEnv;
begin
Assert(GdotEnv <> nil, 'dotEnv not set');
if GdotEnv = nil then
begin
TMonitor.Enter(gLock);
try
if GdotEnv = nil then
begin
if GdotEnvDelegate = nil then
begin
raise EMVCDotEnv.Create('"dotEnvConfigure" not called');
end;
GdotEnv := GdotEnvDelegate();
if GdotEnv = nil then
begin
raise EMVCDotEnv.Create('Delegated passed to "dotEnvConfigure" must return a valid IMVCDotEnv instance');
end;
end;
finally
TMonitor.Exit(gLock);
end;
end;
Result := GdotEnv;
end;