2023-05-24 10:55:43 +02:00
|
|
|
// *************************************************************************** }
|
|
|
|
//
|
|
|
|
// Delphi MVC Framework
|
|
|
|
//
|
|
|
|
// Copyright (c) 2010-2023 Daniele Teti and the DMVCFramework Team
|
|
|
|
//
|
|
|
|
// https://github.com/danieleteti/delphimvcframework
|
|
|
|
//
|
|
|
|
// ***************************************************************************
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
//
|
|
|
|
// ***************************************************************************
|
|
|
|
|
|
|
|
unit MVCFramework.DotEnv;
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
2023-06-06 13:00:21 +02:00
|
|
|
uses
|
2023-09-01 12:49:10 +02:00
|
|
|
System.Generics.Collections,
|
|
|
|
MVCFramework.DotEnv.Parser,
|
|
|
|
System.SysUtils;
|
2023-05-24 10:55:43 +02:00
|
|
|
|
|
|
|
type
|
|
|
|
{$SCOPEDENUMS ON}
|
|
|
|
TMVCDotEnvPriority = (FileThenEnv, EnvThenFile, OnlyFile, OnlyEnv);
|
|
|
|
|
|
|
|
EMVCDotEnv = class(Exception)
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
IMVCDotEnv = interface
|
|
|
|
['{5FD2C3CB-0895-4CCD-985F-27394798E4A8}']
|
|
|
|
function Env(const Name: string): string; overload;
|
2023-06-06 10:16:34 +02:00
|
|
|
function Env(const Name: string; const DefaultValue: String): string; overload;
|
|
|
|
function Env(const Name: string; const DefaultValue: Integer): Integer; overload;
|
2023-06-15 23:42:07 +02:00
|
|
|
function Env(const Name: string; const DefaultValue: Boolean): Boolean; overload;
|
2023-05-24 10:55:43 +02:00
|
|
|
function SaveToFile(const FileName: String): IMVCDotEnv;
|
2023-05-25 00:48:03 +02:00
|
|
|
function ToArray(): TArray<String>;
|
2023-05-24 10:55:43 +02:00
|
|
|
end;
|
|
|
|
|
2023-05-30 12:03:20 +02:00
|
|
|
IMVCDotEnvBuilder = interface
|
|
|
|
['{1A5EDD44-7226-40BC-A8EE-789E27522392}']
|
|
|
|
function WithStrategy(const Strategy: TMVCDotEnvPriority = TMVCDotEnvPriority.EnvThenFile): IMVCDotEnvBuilder;
|
2023-06-06 13:00:21 +02:00
|
|
|
function UseLogger( const Logger: TProc<String>): IMVCDotEnvBuilder;
|
2023-09-01 12:49:10 +02:00
|
|
|
function UseProfile(const ProfileName: String): IMVCDotEnvBuilder; overload;
|
|
|
|
function UseProfile(const ProfileDelegate: TFunc<String>): IMVCDotEnvBuilder; overload;
|
2023-05-30 12:03:20 +02:00
|
|
|
function ClearProfiles: IMVCDotEnvBuilder;
|
|
|
|
function Build(const DotEnvPath: string = ''): IMVCDotEnv; overload;
|
|
|
|
end;
|
2023-05-24 10:55:43 +02:00
|
|
|
|
2023-05-30 12:03:20 +02:00
|
|
|
function NewDotEnv: IMVCDotEnvBuilder;
|
2023-05-24 10:55:43 +02:00
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
uses
|
|
|
|
System.IOUtils,
|
|
|
|
System.TypInfo,
|
2023-09-01 12:49:10 +02:00
|
|
|
System.Classes,
|
|
|
|
MVCFramework.Commons;
|
2023-05-24 10:55:43 +02:00
|
|
|
|
|
|
|
var
|
2023-05-30 12:03:20 +02:00
|
|
|
gDotEnv: IMVCDotEnvBuilder = nil;
|
2023-05-24 10:55:43 +02:00
|
|
|
|
|
|
|
{ TDotEnv }
|
|
|
|
|
|
|
|
type
|
2023-05-25 00:48:03 +02:00
|
|
|
{$SCOPEDENUMS ON}
|
|
|
|
TdotEnvEngineState = (created, building, built);
|
2023-05-30 12:03:20 +02:00
|
|
|
TMVCDotEnv = class(TInterfacedObject, IMVCDotEnv, IMVCDotEnvBuilder)
|
2023-05-24 10:55:43 +02:00
|
|
|
strict private
|
2023-05-25 00:48:03 +02:00
|
|
|
fState: TdotEnvEngineState;
|
2023-05-24 10:55:43 +02:00
|
|
|
fPriority: TMVCDotEnvPriority;
|
|
|
|
fEnvPath: string;
|
|
|
|
fEnvDict: TMVCDotEnvDictionary;
|
2023-06-06 13:00:21 +02:00
|
|
|
fLoggerProc: TProc<String>;
|
2023-05-24 10:55:43 +02:00
|
|
|
fProfiles: TList<String>;
|
2023-06-06 13:00:21 +02:00
|
|
|
procedure DoLog(const Value: String);
|
2023-05-24 10:55:43 +02:00
|
|
|
procedure ReadEnvFile;
|
|
|
|
function GetDotEnvVar(const key: string): string;
|
2023-09-01 12:49:10 +02:00
|
|
|
function GetBuiltInVariable(const VarName: String; out Value: String): Boolean;
|
2023-05-24 10:55:43 +02:00
|
|
|
function ExplodePlaceholders(const Value: string): string;
|
|
|
|
procedure PopulateDictionary(const EnvDict: TDictionary<string, string>; const EnvFilePath: String);
|
|
|
|
procedure CheckAlreadyBuilt;
|
|
|
|
procedure ExplodeReferences;
|
|
|
|
strict protected
|
2023-05-30 12:03:20 +02:00
|
|
|
function WithStrategy(const Priority: TMVCDotEnvPriority = TMVCDotEnvPriority.EnvThenFile): IMVCDotEnvBuilder; overload;
|
2023-09-01 12:49:10 +02:00
|
|
|
function UseProfile(const ProfileName: String): IMVCDotEnvBuilder; overload;
|
|
|
|
function UseProfile(const ProfileDelegate: TFunc<String>): IMVCDotEnvBuilder; overload;
|
2023-06-06 13:00:21 +02:00
|
|
|
function UseLogger(const LoggerProc: TProc<String>): IMVCDotEnvBuilder;
|
2023-05-30 12:03:20 +02:00
|
|
|
function ClearProfiles: IMVCDotEnvBuilder;
|
2023-05-24 10:55:43 +02:00
|
|
|
function Build(const DotEnvDirectory: string = ''): IMVCDotEnv; overload;
|
|
|
|
function Env(const Name: string): string; overload;
|
2023-06-06 10:16:34 +02:00
|
|
|
function Env(const Name: string; const DefaultValue: String): string; overload;
|
|
|
|
function Env(const Name: string; const DefaultValue: Integer): Integer; overload;
|
2023-06-15 23:42:07 +02:00
|
|
|
function Env(const Name: string; const DefaultValue: Boolean): Boolean; overload;
|
2023-05-24 10:55:43 +02:00
|
|
|
function SaveToFile(const FileName: String): IMVCDotEnv;
|
2023-05-25 00:48:03 +02:00
|
|
|
function ToArray(): TArray<String>;
|
2023-05-24 10:55:43 +02:00
|
|
|
public
|
|
|
|
constructor Create;
|
|
|
|
destructor Destroy; override;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2023-09-01 12:49:10 +02:00
|
|
|
function TMVCDotEnv.GetBuiltInVariable(const VarName: String;
|
|
|
|
out Value: String): Boolean;
|
|
|
|
var
|
|
|
|
lVarName: string;
|
|
|
|
begin
|
|
|
|
Result := False;
|
|
|
|
lVarName := VarName.ToLower.Remove(VarName.Length -2, 2).Remove(0,2);
|
|
|
|
|
|
|
|
if lVarName = 'os' then
|
|
|
|
begin
|
|
|
|
Value := TOSVersion.Name;
|
|
|
|
Exit(True);
|
|
|
|
end;
|
|
|
|
|
|
|
|
if lVarName = 'home' then
|
|
|
|
begin
|
|
|
|
Value := AppPath;
|
|
|
|
Exit(True);
|
|
|
|
end;
|
|
|
|
|
|
|
|
if lVarName = 'dmvc.version' then
|
|
|
|
begin
|
|
|
|
Value := DMVCFRAMEWORK_VERSION;
|
|
|
|
Exit(True);
|
|
|
|
end;
|
|
|
|
DoLog('Unknown built-in env var named ' + lVarName + '.');
|
|
|
|
end;
|
|
|
|
|
2023-05-24 10:55:43 +02:00
|
|
|
function TMVCDotEnv.GetDotEnvVar(const key: string): string;
|
|
|
|
begin
|
|
|
|
fEnvDict.TryGetValue(key, Result);
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TMVCDotEnv.Env(const Name: string): string;
|
2023-05-25 00:48:03 +02:00
|
|
|
var
|
|
|
|
lTmp: String;
|
2023-05-24 10:55:43 +02:00
|
|
|
begin
|
2023-05-25 00:48:03 +02:00
|
|
|
if fState = TdotEnvEngineState.created then
|
|
|
|
begin
|
|
|
|
raise EMVCDotEnv.Create('dotEnv Engine not built');
|
|
|
|
end;
|
|
|
|
|
2023-05-24 10:55:43 +02:00
|
|
|
if fPriority in [TMVCDotEnvPriority.FileThenEnv, TMVCDotEnvPriority.OnlyFile] then
|
|
|
|
begin
|
|
|
|
Result := GetDotEnvVar(name);
|
2023-05-25 00:48:03 +02:00
|
|
|
if Result.Contains('${' + Name + '}') then
|
|
|
|
begin
|
|
|
|
raise EMVCDotEnv.CreateFmt('Configuration loop detected with key "%s"', [Name]);
|
|
|
|
end;
|
|
|
|
|
2023-05-24 10:55:43 +02:00
|
|
|
if fPriority = TMVCDotEnvPriority.OnlyFile then
|
|
|
|
begin
|
|
|
|
// OnlyFile
|
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
// FileThenEnv
|
|
|
|
if Result.IsEmpty then
|
|
|
|
begin
|
|
|
|
Exit(ExplodePlaceholders(GetEnvironmentVariable(Name)));
|
|
|
|
end;
|
|
|
|
end
|
|
|
|
else if fPriority in [TMVCDotEnvPriority.EnvThenFile, TMVCDotEnvPriority.OnlyEnv] then
|
|
|
|
begin
|
|
|
|
Result := ExplodePlaceholders(GetEnvironmentVariable(Name));
|
|
|
|
if fPriority = TMVCDotEnvPriority.OnlyEnv then
|
|
|
|
begin
|
|
|
|
// OnlyEnv
|
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
// EnvThenFile
|
|
|
|
if Result.IsEmpty then
|
|
|
|
begin
|
2023-05-25 00:48:03 +02:00
|
|
|
lTmp := GetDotEnvVar(Name);
|
|
|
|
if lTmp.Contains('${' + Name + '}') then
|
|
|
|
begin
|
|
|
|
raise EMVCDotEnv.CreateFmt('Configuration loop detected with key "%s"', [Name]);
|
|
|
|
end;
|
|
|
|
Exit(lTmp);
|
2023-05-24 10:55:43 +02:00
|
|
|
end;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
2023-05-30 12:03:20 +02:00
|
|
|
raise EMVCDotEnv.CreateFmt('Unknown dotEnv Priority: %s', [GetEnumName(TypeInfo(TMVCDotEnvPriority), Ord(fPriority))]);
|
2023-05-24 10:55:43 +02:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2023-06-06 13:00:21 +02:00
|
|
|
function TMVCDotEnv.UseLogger(
|
|
|
|
const LoggerProc: TProc<String>): IMVCDotEnvBuilder;
|
|
|
|
begin
|
|
|
|
if Assigned(fLoggerProc) then
|
|
|
|
begin
|
|
|
|
raise EMVCDotEnv.Create('Logger already set');
|
|
|
|
end;
|
|
|
|
fLoggerProc := LoggerProc;
|
|
|
|
Result := Self;
|
|
|
|
end;
|
|
|
|
|
2023-09-01 12:49:10 +02:00
|
|
|
function TMVCDotEnv.UseProfile(
|
|
|
|
const ProfileDelegate: TFunc<String>): IMVCDotEnvBuilder;
|
|
|
|
begin
|
|
|
|
CheckAlreadyBuilt;
|
|
|
|
fProfiles.Add(ProfileDelegate());
|
|
|
|
Result := Self;
|
|
|
|
end;
|
|
|
|
|
2023-05-30 12:03:20 +02:00
|
|
|
function TMVCDotEnv.UseProfile(const ProfileName: String): IMVCDotEnvBuilder;
|
2023-05-24 10:55:43 +02:00
|
|
|
begin
|
|
|
|
CheckAlreadyBuilt;
|
|
|
|
fProfiles.Add(ProfileName);
|
|
|
|
Result := Self;
|
|
|
|
end;
|
|
|
|
|
2023-05-30 12:03:20 +02:00
|
|
|
function TMVCDotEnv.WithStrategy(const Priority: TMVCDotEnvPriority): IMVCDotEnvBuilder;
|
2023-05-24 10:55:43 +02:00
|
|
|
begin
|
|
|
|
CheckAlreadyBuilt;
|
|
|
|
Result := Self;
|
|
|
|
fPriority := Priority;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TMVCDotEnv.Build(const DotEnvDirectory: string): IMVCDotEnv;
|
2023-06-06 13:00:21 +02:00
|
|
|
var
|
|
|
|
lAllProfiles: TArray<String>;
|
2023-05-24 10:55:43 +02:00
|
|
|
begin
|
2023-05-25 00:48:03 +02:00
|
|
|
if fState <> TdotEnvEngineState.created then
|
|
|
|
begin
|
|
|
|
raise EMVCDotEnv.Create('dotEnv engine already built');
|
|
|
|
end;
|
|
|
|
fState := TdotEnvEngineState.building;
|
2023-05-24 10:55:43 +02:00
|
|
|
Result := Self;
|
|
|
|
fEnvPath := TDirectory.GetParent(GetModuleName(HInstance));
|
|
|
|
if not DotEnvDirectory.IsEmpty then
|
|
|
|
begin
|
|
|
|
fEnvPath := TPath.Combine(fEnvPath, DotEnvDirectory);
|
|
|
|
end;
|
2023-08-09 15:57:28 +02:00
|
|
|
DoLog('Path = ' + fEnvPath);
|
2023-05-24 10:55:43 +02:00
|
|
|
fEnvDict.Clear;
|
2023-06-06 13:00:21 +02:00
|
|
|
lAllProfiles := ['default'] + fProfiles.ToArray();
|
|
|
|
DoLog('Active profile/s priority = [' + String.Join(',', lAllProfiles) + ']');
|
2023-05-24 10:55:43 +02:00
|
|
|
ReadEnvFile;
|
|
|
|
ExplodeReferences;
|
2023-05-25 00:48:03 +02:00
|
|
|
fState := TdotEnvEngineState.built;
|
2023-05-24 10:55:43 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TMVCDotEnv.CheckAlreadyBuilt;
|
|
|
|
begin
|
2023-05-25 00:48:03 +02:00
|
|
|
if fState in [TdotEnvEngineState.built] then
|
2023-05-24 10:55:43 +02:00
|
|
|
begin
|
|
|
|
raise Exception.Create('DotEnv Engine Already Built');
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2023-05-30 12:03:20 +02:00
|
|
|
function TMVCDotEnv.ClearProfiles: IMVCDotEnvBuilder;
|
2023-05-24 10:55:43 +02:00
|
|
|
begin
|
|
|
|
CheckAlreadyBuilt;
|
|
|
|
fProfiles.Clear;
|
|
|
|
Result := Self;
|
|
|
|
end;
|
|
|
|
|
|
|
|
constructor TMVCDotEnv.Create;
|
|
|
|
begin
|
|
|
|
inherited;
|
2023-05-25 00:48:03 +02:00
|
|
|
fState := TdotEnvEngineState.created;
|
2023-05-24 10:55:43 +02:00
|
|
|
fProfiles := TList<String>.Create;
|
|
|
|
fEnvDict := TMVCDotEnvDictionary.Create;
|
|
|
|
fEnvPath := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)));
|
|
|
|
fPriority := TMVCDotEnvPriority.EnvThenFile;
|
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TMVCDotEnv.Destroy;
|
|
|
|
begin
|
|
|
|
FreeAndNil(fEnvDict);
|
|
|
|
fProfiles.Free;
|
|
|
|
inherited;
|
|
|
|
end;
|
|
|
|
|
2023-06-06 13:00:21 +02:00
|
|
|
procedure TMVCDotEnv.DoLog(const Value: String);
|
|
|
|
begin
|
|
|
|
if Assigned(fLoggerProc) then
|
|
|
|
begin
|
|
|
|
fLoggerProc(Value);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2023-06-06 10:16:34 +02:00
|
|
|
function TMVCDotEnv.Env(const Name, DefaultValue: String): string;
|
|
|
|
begin
|
|
|
|
Result := Env(Name);
|
|
|
|
if Result.IsEmpty then
|
|
|
|
begin
|
|
|
|
Result := DefaultValue;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TMVCDotEnv.Env(const Name: string;
|
|
|
|
const DefaultValue: Integer): Integer;
|
|
|
|
var
|
|
|
|
lTmp: string;
|
|
|
|
begin
|
|
|
|
lTmp := Env(Name);
|
|
|
|
if lTmp.IsEmpty then
|
|
|
|
begin
|
|
|
|
Result := DefaultValue;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
2023-09-22 09:41:37 +02:00
|
|
|
if not TryStrToInt(lTmp.Trim, Result) then
|
2023-06-06 10:16:34 +02:00
|
|
|
begin
|
2023-09-22 09:41:37 +02:00
|
|
|
raise EMVCDotEnv.CreateFmt('Env "%s" is not a valid integer [Current Value: "%s"]', [Name, lTmp]);
|
2023-06-06 10:16:34 +02:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2023-06-15 23:42:07 +02:00
|
|
|
function TMVCDotEnv.Env(const Name: string;
|
|
|
|
const DefaultValue: Boolean): Boolean;
|
|
|
|
var
|
|
|
|
lTmp: string;
|
|
|
|
begin
|
|
|
|
lTmp := Env(Name);
|
|
|
|
if lTmp.IsEmpty then
|
|
|
|
begin
|
|
|
|
Result := DefaultValue;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
2023-09-22 09:41:37 +02:00
|
|
|
if not TryStrToBool(lTmp.Trim, Result) then
|
2023-06-15 23:42:07 +02:00
|
|
|
begin
|
2023-09-22 09:41:37 +02:00
|
|
|
raise EMVCDotEnv.CreateFmt('Env "%s" is not a valid boolean [Current Value: "%s"]', [Name, lTmp]);
|
2023-06-15 23:42:07 +02:00
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2023-05-24 10:55:43 +02:00
|
|
|
function TMVCDotEnv.ExplodePlaceholders(const Value: string): string;
|
|
|
|
var
|
|
|
|
lStartPos, lEndPos: Integer;
|
|
|
|
lKey, lValue: string;
|
|
|
|
begin
|
|
|
|
Result := Value;
|
|
|
|
while Result.IndexOf('${') > -1 do
|
|
|
|
begin
|
|
|
|
lStartPos := Result.IndexOf('${');
|
|
|
|
lEndPos := Result.IndexOf('}');
|
|
|
|
if (lEndPos = -1) or (lEndPos < lStartPos) then
|
|
|
|
begin
|
|
|
|
raise EMVCDotEnv.Create('Unclosed expansion (${...}) at: ' + Value);
|
|
|
|
end;
|
|
|
|
lKey := Result.Substring(lStartPos + 2, lEndPos - (lStartPos + 2));
|
2023-09-01 12:49:10 +02:00
|
|
|
|
|
|
|
if lKey.StartsWith('__') and lKey.EndsWith('__') then
|
|
|
|
begin
|
|
|
|
if not GetBuiltInVariable(lKey, lValue) then
|
|
|
|
begin
|
|
|
|
lValue := Env(lKey);
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
lValue := Env(lKey);
|
|
|
|
end;
|
2023-05-24 10:55:43 +02:00
|
|
|
Result := StringReplace(Result, '${' + lKey + '}', lValue, [rfReplaceAll]);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TMVCDotEnv.ExplodeReferences;
|
|
|
|
var
|
|
|
|
lKey: String;
|
|
|
|
begin
|
|
|
|
for lKey in fEnvDict.Keys do
|
|
|
|
begin
|
|
|
|
fEnvDict.AddOrSetValue(lKey, ExplodePlaceholders(fEnvDict[lKey]));
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TMVCDotEnv.SaveToFile(const FileName: String): IMVCDotEnv;
|
|
|
|
var
|
|
|
|
lKeys: TArray<String>;
|
|
|
|
lKey: String;
|
|
|
|
lSL: TStringList;
|
|
|
|
begin
|
|
|
|
lKeys := fEnvDict.Keys.ToArray;
|
|
|
|
TArray.Sort<String>(lKeys);
|
|
|
|
lSL := TStringList.Create;
|
|
|
|
try
|
|
|
|
for lKey in lKeys do
|
|
|
|
begin
|
|
|
|
lSL.Values[lKey] := GetDotEnvVar(lKey);
|
|
|
|
end;
|
|
|
|
lSL.SaveToFile(FileName);
|
|
|
|
finally
|
|
|
|
lSL.Free;
|
|
|
|
end;
|
|
|
|
Result := Self;
|
|
|
|
end;
|
|
|
|
|
2023-05-25 00:48:03 +02:00
|
|
|
function TMVCDotEnv.ToArray: TArray<String>;
|
|
|
|
var
|
|
|
|
lKeys: TArray<String>;
|
|
|
|
lKey: String;
|
|
|
|
I: Integer;
|
|
|
|
begin
|
|
|
|
lKeys := fEnvDict.Keys.ToArray;
|
|
|
|
TArray.Sort<String>(lKeys);
|
|
|
|
SetLength(Result, Length(lKeys));
|
|
|
|
I := 0;
|
|
|
|
for lKey in lKeys do
|
|
|
|
begin
|
|
|
|
Result[I] := lKey + '=' + GetDotEnvVar(lKey);
|
|
|
|
Inc(I);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2023-05-24 10:55:43 +02:00
|
|
|
procedure TMVCDotEnv.PopulateDictionary(const EnvDict: TDictionary<string, string>; const EnvFilePath: String);
|
|
|
|
var
|
|
|
|
lDotEnvCode: string;
|
|
|
|
lParser: TMVCDotEnvParser;
|
|
|
|
begin
|
|
|
|
if not TFile.Exists(EnvFilePath) then
|
|
|
|
begin
|
2023-06-06 13:00:21 +02:00
|
|
|
DoLog('Missed dotEnv file ' + EnvFilePath);
|
2023-05-24 10:55:43 +02:00
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
|
|
|
|
lDotEnvCode := TFile.ReadAllText(EnvFilePath);
|
|
|
|
lParser := TMVCDotEnvParser.Create;
|
|
|
|
try
|
|
|
|
lParser.Parse(fEnvDict, lDotEnvCode);
|
2023-06-06 13:00:21 +02:00
|
|
|
DoLog('Applied dotEnv file ' + EnvFilePath);
|
2023-05-24 10:55:43 +02:00
|
|
|
finally
|
|
|
|
lParser.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TMVCDotEnv.ReadEnvFile;
|
|
|
|
var
|
|
|
|
lProfileEnvPath: string;
|
|
|
|
I: Integer;
|
|
|
|
begin
|
|
|
|
PopulateDictionary(fEnvDict, IncludeTrailingPathDelimiter(fEnvPath) + '.env');
|
|
|
|
for I := 0 to fProfiles.Count - 1 do
|
|
|
|
begin
|
|
|
|
lProfileEnvPath := TPath.Combine(fEnvPath, '.env') + '.' + fProfiles[I];
|
|
|
|
PopulateDictionary(fEnvDict, lProfileEnvPath);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2023-05-30 12:03:20 +02:00
|
|
|
function NewDotEnv: IMVCDotEnvBuilder;
|
2023-05-24 10:55:43 +02:00
|
|
|
begin
|
|
|
|
Result := TMVCDotEnv.Create;
|
|
|
|
end;
|
|
|
|
|
|
|
|
end.
|