WIP
This commit is contained in:
28
.devcontainer/Dockerfile
Normal file
28
.devcontainer/Dockerfile
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
FROM mcr.microsoft.com/dotnet/core/sdk:2.2
|
||||||
|
|
||||||
|
# Add keys and sources lists
|
||||||
|
RUN curl -sL https://deb.nodesource.com/setup_11.x | bash
|
||||||
|
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
||||||
|
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" \
|
||||||
|
| tee /etc/apt/sources.list.d/yarn.list
|
||||||
|
|
||||||
|
# Install node, 7zip, yarn, git, process tools
|
||||||
|
RUN apt-get update && apt-get install -y nodejs p7zip-full yarn git procps
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
RUN apt-get autoremove -y \
|
||||||
|
&& apt-get clean -y \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Install fake
|
||||||
|
RUN dotnet tool install fake-cli -g
|
||||||
|
|
||||||
|
# Install Paket
|
||||||
|
RUN dotnet tool install paket -g
|
||||||
|
|
||||||
|
# add dotnet tools to path to pick up fake and paket installation
|
||||||
|
ENV PATH="/root/.dotnet/tools:${PATH}"
|
||||||
|
|
||||||
|
# Copy endpoint specific user settings into container to specify
|
||||||
|
# .NET Core should be used as the runtime.
|
||||||
|
COPY settings.vscode.json /root/.vscode-remote/data/Machine/settings.json
|
||||||
11
.devcontainer/devcontainer.json
Normal file
11
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "SAFE",
|
||||||
|
"dockerFile": "Dockerfile",
|
||||||
|
"appPort": [8080, 8085],
|
||||||
|
"extensions": [
|
||||||
|
"ionide.ionide-fsharp",
|
||||||
|
"ms-vscode.csharp",
|
||||||
|
"editorconfig.editorconfig",
|
||||||
|
"msjsdiag.debugger-for-chrome"
|
||||||
|
]
|
||||||
|
}
|
||||||
3
.devcontainer/settings.vscode.json
Normal file
3
.devcontainer/settings.vscode.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"FSharp.fsacRuntime":"netcore"
|
||||||
|
}
|
||||||
8
.editorconfig
Normal file
8
.editorconfig
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = false
|
||||||
16
.gitignore
vendored
Normal file
16
.gitignore
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
.fable/
|
||||||
|
.fake/
|
||||||
|
.vs/
|
||||||
|
obj/
|
||||||
|
bin/
|
||||||
|
packages/
|
||||||
|
paket-files/
|
||||||
|
node_modules/
|
||||||
|
src/Client/public/js/
|
||||||
|
release.cmd
|
||||||
|
release.sh
|
||||||
|
.idea/
|
||||||
|
*.orig
|
||||||
|
*.DotSettings.user
|
||||||
|
deploy
|
||||||
|
.ionide/
|
||||||
461
.paket/Paket.Restore.targets
Normal file
461
.paket/Paket.Restore.targets
Normal file
@@ -0,0 +1,461 @@
|
|||||||
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<!-- Prevent dotnet template engine to parse this file -->
|
||||||
|
<!--/-:cnd:noEmit-->
|
||||||
|
<PropertyGroup>
|
||||||
|
<!-- make MSBuild track this file for incremental builds. -->
|
||||||
|
<!-- ref https://blogs.msdn.microsoft.com/msbuild/2005/09/26/how-to-ensure-changes-to-a-custom-target-file-prompt-a-rebuild/ -->
|
||||||
|
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||||
|
|
||||||
|
<DetectedMSBuildVersion>$(MSBuildVersion)</DetectedMSBuildVersion>
|
||||||
|
<DetectedMSBuildVersion Condition="$(MSBuildVersion) == ''">15.0.0</DetectedMSBuildVersion>
|
||||||
|
<MSBuildSupportsHashing>false</MSBuildSupportsHashing>
|
||||||
|
<MSBuildSupportsHashing Condition=" '$(DetectedMSBuildVersion)' > '15.8.0' ">true</MSBuildSupportsHashing>
|
||||||
|
<!-- Mark that this target file has been loaded. -->
|
||||||
|
<IsPaketRestoreTargetsFileLoaded>true</IsPaketRestoreTargetsFileLoaded>
|
||||||
|
<PaketToolsPath>$(MSBuildThisFileDirectory)</PaketToolsPath>
|
||||||
|
<PaketRootPath>$(MSBuildThisFileDirectory)..\</PaketRootPath>
|
||||||
|
<PaketRestoreCacheFile>$(PaketRootPath)paket-files\paket.restore.cached</PaketRestoreCacheFile>
|
||||||
|
<PaketLockFilePath>$(PaketRootPath)paket.lock</PaketLockFilePath>
|
||||||
|
<PaketBootstrapperStyle>classic</PaketBootstrapperStyle>
|
||||||
|
<PaketBootstrapperStyle Condition="Exists('$(PaketToolsPath)paket.bootstrapper.proj')">proj</PaketBootstrapperStyle>
|
||||||
|
<PaketExeImage>assembly</PaketExeImage>
|
||||||
|
<PaketExeImage Condition=" '$(PaketBootstrapperStyle)' == 'proj' ">native</PaketExeImage>
|
||||||
|
<MonoPath Condition="'$(MonoPath)' == '' And Exists('/Library/Frameworks/Mono.framework/Commands/mono')">/Library/Frameworks/Mono.framework/Commands/mono</MonoPath>
|
||||||
|
<MonoPath Condition="'$(MonoPath)' == ''">mono</MonoPath>
|
||||||
|
|
||||||
|
<!-- PaketBootStrapper -->
|
||||||
|
<PaketBootStrapperExePath Condition=" '$(PaketBootStrapperExePath)' == '' AND Exists('$(PaketRootPath)paket.bootstrapper.exe')">$(PaketRootPath)paket.bootstrapper.exe</PaketBootStrapperExePath>
|
||||||
|
<PaketBootStrapperExePath Condition=" '$(PaketBootStrapperExePath)' == '' ">$(PaketToolsPath)paket.bootstrapper.exe</PaketBootStrapperExePath>
|
||||||
|
<PaketBootStrapperExeDir Condition=" Exists('$(PaketBootStrapperExePath)') " >$([System.IO.Path]::GetDirectoryName("$(PaketBootStrapperExePath)"))\</PaketBootStrapperExeDir>
|
||||||
|
|
||||||
|
<!-- Paket -->
|
||||||
|
|
||||||
|
<!-- windows, root => tool => proj style => bootstrapper => global -->
|
||||||
|
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' AND Exists('$(PaketRootPath)paket.exe') ">$(PaketRootPath)paket.exe</PaketExePath>
|
||||||
|
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' AND Exists('$(PaketToolsPath)paket.exe') ">$(PaketToolsPath)paket.exe</PaketExePath>
|
||||||
|
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' AND '$(PaketBootstrapperStyle)' == 'proj' ">$(PaketToolsPath)paket.exe</PaketExePath>
|
||||||
|
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' AND Exists('$(PaketBootStrapperExeDir)') ">$(_PaketBootStrapperExeDir)paket.exe</PaketExePath>
|
||||||
|
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' ">paket.exe</PaketExePath>
|
||||||
|
|
||||||
|
<!-- no windows, try native paket as default, root => tool => proj style => mono paket => bootstrpper => global -->
|
||||||
|
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND Exists('$(PaketRootPath)paket') ">$(PaketRootPath)paket</PaketExePath>
|
||||||
|
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND Exists('$(PaketToolsPath)paket') ">$(PaketToolsPath)paket</PaketExePath>
|
||||||
|
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND '$(PaketBootstrapperStyle)' == 'proj' ">$(PaketToolsPath)paket</PaketExePath>
|
||||||
|
|
||||||
|
<!-- no windows, try mono paket -->
|
||||||
|
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND Exists('$(PaketRootPath)paket.exe') ">$(PaketRootPath)paket.exe</PaketExePath>
|
||||||
|
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND Exists('$(PaketToolsPath)paket.exe') ">$(PaketToolsPath)paket.exe</PaketExePath>
|
||||||
|
|
||||||
|
<!-- no windows, try bootstrapper -->
|
||||||
|
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND Exists('$(PaketBootStrapperExeDir)') ">$(PaketBootStrapperExeDir)paket.exe</PaketExePath>
|
||||||
|
|
||||||
|
<!-- no windows, try global native paket -->
|
||||||
|
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' ">paket</PaketExePath>
|
||||||
|
|
||||||
|
<!-- Paket command -->
|
||||||
|
<_PaketExeExtension>$([System.IO.Path]::GetExtension("$(PaketExePath)"))</_PaketExeExtension>
|
||||||
|
<PaketCommand Condition=" '$(PaketCommand)' == '' AND '$(_PaketExeExtension)' == '.dll' ">dotnet "$(PaketExePath)"</PaketCommand>
|
||||||
|
<PaketCommand Condition=" '$(PaketCommand)' == '' AND '$(OS)' != 'Windows_NT' AND '$(_PaketExeExtension)' == '.exe' ">$(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)"</PaketCommand>
|
||||||
|
<PaketCommand Condition=" '$(PaketCommand)' == '' ">"$(PaketExePath)"</PaketCommand>
|
||||||
|
|
||||||
|
|
||||||
|
<PaketBootStrapperCommand Condition=" '$(OS)' == 'Windows_NT'">"$(PaketBootStrapperExePath)"</PaketBootStrapperCommand>
|
||||||
|
<PaketBootStrapperCommand Condition=" '$(OS)' != 'Windows_NT' ">$(MonoPath) --runtime=v4.0.30319 "$(PaketBootStrapperExePath)"</PaketBootStrapperCommand>
|
||||||
|
|
||||||
|
<!-- Disable automagic references for F# dotnet sdk -->
|
||||||
|
<!-- This will not do anything for other project types -->
|
||||||
|
<!-- see https://github.com/fsharp/fslang-design/blob/master/RFCs/FS-1032-fsharp-in-dotnet-sdk.md -->
|
||||||
|
<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
|
||||||
|
<DisableImplicitSystemValueTupleReference>true</DisableImplicitSystemValueTupleReference>
|
||||||
|
|
||||||
|
<!-- Disable Paket restore under NCrunch build -->
|
||||||
|
<PaketRestoreDisabled Condition="'$(NCrunch)' == '1'">True</PaketRestoreDisabled>
|
||||||
|
|
||||||
|
<PaketIntermediateOutputPath Condition=" '$(PaketIntermediateOutputPath)' == '' ">$(BaseIntermediateOutputPath.TrimEnd('\').TrimEnd('\/'))</PaketIntermediateOutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Target Name="PaketBootstrapping" Condition="Exists('$(PaketToolsPath)paket.bootstrapper.proj')">
|
||||||
|
<MSBuild Projects="$(PaketToolsPath)paket.bootstrapper.proj" Targets="Restore" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<!-- Official workaround for https://docs.microsoft.com/en-us/visualstudio/msbuild/getfilehash-task?view=vs-2019 -->
|
||||||
|
<UsingTask TaskName="Microsoft.Build.Tasks.GetFileHash" AssemblyName="Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" Condition=" '$(MSBuildSupportsHashing)' == 'true' And '$(DetectedMSBuildVersion)' < '16.0.360' " />
|
||||||
|
<UsingTask TaskName="Microsoft.Build.Tasks.VerifyFileHash" AssemblyName="Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" Condition=" '$(MSBuildSupportsHashing)' == 'true' And '$(DetectedMSBuildVersion)' < '16.0.360' " />
|
||||||
|
<Target Name="PaketRestore" Condition="'$(PaketRestoreDisabled)' != 'True'" BeforeTargets="_GenerateDotnetCliToolReferenceSpecs;_GenerateProjectRestoreGraphPerFramework;_GenerateRestoreGraphWalkPerFramework;CollectPackageReferences" DependsOnTargets="PaketBootstrapping">
|
||||||
|
|
||||||
|
<!-- Step 1 Check if lockfile is properly restored (if the hash of the lockfile and the cache-file match) -->
|
||||||
|
<PropertyGroup>
|
||||||
|
<PaketRestoreRequired>true</PaketRestoreRequired>
|
||||||
|
<NoWarn>$(NoWarn);NU1603;NU1604;NU1605;NU1608</NoWarn>
|
||||||
|
<CacheFilesExist>false</CacheFilesExist>
|
||||||
|
<CacheFilesExist Condition=" Exists('$(PaketRestoreCacheFile)') And Exists('$(PaketLockFilePath)') ">true</CacheFilesExist>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- Read the hash of the lockfile -->
|
||||||
|
<GetFileHash Condition=" '$(MSBuildSupportsHashing)' == 'true' And '$(CacheFilesExist)' == 'true' " Files="$(PaketLockFilePath)" Algorithm="SHA256" HashEncoding="hex" >
|
||||||
|
<Output TaskParameter="Hash" PropertyName="PaketRestoreLockFileHash" />
|
||||||
|
</GetFileHash>
|
||||||
|
<!-- Read the hash of the cache, which is json, but a very simple key value object -->
|
||||||
|
<PropertyGroup Condition=" '$(MSBuildSupportsHashing)' == 'true' And '$(CacheFilesExist)' == 'true' ">
|
||||||
|
<PaketRestoreCachedContents>$([System.IO.File]::ReadAllText('$(PaketRestoreCacheFile)'))</PaketRestoreCachedContents>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup Condition=" '$(MSBuildSupportsHashing)' == 'true' And '$(CacheFilesExist)' == 'true' ">
|
||||||
|
<!-- Parse our simple 'paket.restore.cached' json ...-->
|
||||||
|
<PaketRestoreCachedSplitObject Include="$([System.Text.RegularExpressions.Regex]::Split(`$(PaketRestoreCachedContents)`, `{|}|,`))"></PaketRestoreCachedSplitObject>
|
||||||
|
<!-- Keep Key, Value ItemGroup-->
|
||||||
|
<PaketRestoreCachedKeyValue Include="@(PaketRestoreCachedSplitObject)"
|
||||||
|
Condition=" $([System.Text.RegularExpressions.Regex]::Split(`%(Identity)`, `": "`).Length) > 1 ">
|
||||||
|
<Key>$([System.Text.RegularExpressions.Regex]::Split(`%(Identity)`, `": "`)[0].Replace(`"`, ``).Replace(` `, ``))</Key>
|
||||||
|
<Value>$([System.Text.RegularExpressions.Regex]::Split(`%(Identity)`, `": "`)[1].Replace(`"`, ``).Replace(` `, ``))</Value>
|
||||||
|
</PaketRestoreCachedKeyValue>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Condition=" '$(MSBuildSupportsHashing)' == 'true' And '$(CacheFilesExist)' == 'true' ">
|
||||||
|
<!-- Retrieve the hashes we are interested in -->
|
||||||
|
<PackagesDownloadedHash Condition=" '%(PaketRestoreCachedKeyValue.Key)' == 'packagesDownloadedHash' ">%(PaketRestoreCachedKeyValue.Value)</PackagesDownloadedHash>
|
||||||
|
<ProjectsRestoredHash Condition=" '%(PaketRestoreCachedKeyValue.Key)' == 'projectsRestoredHash' ">%(PaketRestoreCachedKeyValue.Value)</ProjectsRestoredHash>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(MSBuildSupportsHashing)' == 'true' And '$(CacheFilesExist)' == 'true' ">
|
||||||
|
<!-- If the restore file doesn't exist we need to restore, otherwise only if hashes don't match -->
|
||||||
|
<PaketRestoreRequired>true</PaketRestoreRequired>
|
||||||
|
<PaketRestoreRequired Condition=" '$(PaketRestoreLockFileHash)' == '$(ProjectsRestoredHash)' ">false</PaketRestoreRequired>
|
||||||
|
<PaketRestoreRequired Condition=" '$(PaketRestoreLockFileHash)' == '' ">true</PaketRestoreRequired>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This value should match the version in the props generated by paket
|
||||||
|
If they differ, this means we need to do a restore in order to ensure correct dependencies
|
||||||
|
-->
|
||||||
|
<PropertyGroup Condition="'$(PaketPropsVersion)' != '5.185.3' ">
|
||||||
|
<PaketRestoreRequired>true</PaketRestoreRequired>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- Do a global restore if required -->
|
||||||
|
<Warning Text="This version of MSBuild (we assume '$(DetectedMSBuildVersion)' or older) doesn't support GetFileHash, so paket fast restore is disabled." Condition=" '$(MSBuildSupportsHashing)' != 'true' " />
|
||||||
|
<Error Text="Stop build because of PAKET_ERROR_ON_MSBUILD_EXEC and we always call the bootstrapper" Condition=" '$(PAKET_ERROR_ON_MSBUILD_EXEC)' == 'true' AND '$(PaketBootstrapperStyle)' == 'classic' AND Exists('$(PaketBootStrapperExePath)') AND !(Exists('$(PaketExePath)'))" />
|
||||||
|
<Exec Command='$(PaketBootStrapperCommand)' Condition=" '$(PaketBootstrapperStyle)' == 'classic' AND Exists('$(PaketBootStrapperExePath)') AND !(Exists('$(PaketExePath)'))" ContinueOnError="false" />
|
||||||
|
<Error Text="Stop build because of PAKET_ERROR_ON_MSBUILD_EXEC and we need a full restore (hashes don't match)" Condition=" '$(PAKET_ERROR_ON_MSBUILD_EXEC)' == 'true' AND '$(PaketRestoreRequired)' == 'true' AND '$(PaketDisableGlobalRestore)' != 'true'" />
|
||||||
|
<Exec Command='$(PaketCommand) restore' Condition=" '$(PaketRestoreRequired)' == 'true' AND '$(PaketDisableGlobalRestore)' != 'true' " ContinueOnError="false" />
|
||||||
|
|
||||||
|
<!-- Step 2 Detect project specific changes -->
|
||||||
|
<ItemGroup>
|
||||||
|
<MyTargetFrameworks Condition="'$(TargetFramework)' != '' " Include="$(TargetFramework)"></MyTargetFrameworks>
|
||||||
|
<!-- Don't include all frameworks when msbuild explicitly asks for a single one -->
|
||||||
|
<MyTargetFrameworks Condition="'$(TargetFrameworks)' != '' AND '$(TargetFramework)' == '' " Include="$(TargetFrameworks)"></MyTargetFrameworks>
|
||||||
|
<PaketResolvedFilePaths Include="@(MyTargetFrameworks -> '$(PaketIntermediateOutputPath)\$(MSBuildProjectFile).%(Identity).paket.resolved')"></PaketResolvedFilePaths>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<PaketReferencesCachedFilePath>$(PaketIntermediateOutputPath)\$(MSBuildProjectFile).paket.references.cached</PaketReferencesCachedFilePath>
|
||||||
|
<!-- MyProject.fsproj.paket.references has the highest precedence -->
|
||||||
|
<PaketOriginalReferencesFilePath>$(MSBuildProjectFullPath).paket.references</PaketOriginalReferencesFilePath>
|
||||||
|
<!-- MyProject.paket.references -->
|
||||||
|
<PaketOriginalReferencesFilePath Condition=" !Exists('$(PaketOriginalReferencesFilePath)')">$(MSBuildProjectDirectory)\$(MSBuildProjectName).paket.references</PaketOriginalReferencesFilePath>
|
||||||
|
<!-- paket.references -->
|
||||||
|
<PaketOriginalReferencesFilePath Condition=" !Exists('$(PaketOriginalReferencesFilePath)')">$(MSBuildProjectDirectory)\paket.references</PaketOriginalReferencesFilePath>
|
||||||
|
|
||||||
|
<DoAllResolvedFilesExist>false</DoAllResolvedFilesExist>
|
||||||
|
<DoAllResolvedFilesExist Condition="Exists(%(PaketResolvedFilePaths.Identity))">true</DoAllResolvedFilesExist>
|
||||||
|
<PaketRestoreRequired>true</PaketRestoreRequired>
|
||||||
|
<PaketRestoreRequiredReason>references-file-or-cache-not-found</PaketRestoreRequiredReason>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- Step 2 a Detect changes in references file -->
|
||||||
|
<PropertyGroup Condition="Exists('$(PaketOriginalReferencesFilePath)') AND Exists('$(PaketReferencesCachedFilePath)') ">
|
||||||
|
<PaketRestoreCachedHash>$([System.IO.File]::ReadAllText('$(PaketReferencesCachedFilePath)'))</PaketRestoreCachedHash>
|
||||||
|
<PaketRestoreReferencesFileHash>$([System.IO.File]::ReadAllText('$(PaketOriginalReferencesFilePath)'))</PaketRestoreReferencesFileHash>
|
||||||
|
<PaketRestoreRequiredReason>references-file</PaketRestoreRequiredReason>
|
||||||
|
<PaketRestoreRequired Condition=" '$(PaketRestoreReferencesFileHash)' == '$(PaketRestoreCachedHash)' ">false</PaketRestoreRequired>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="!Exists('$(PaketOriginalReferencesFilePath)') AND !Exists('$(PaketReferencesCachedFilePath)') ">
|
||||||
|
<!-- If both don't exist there is nothing to do. -->
|
||||||
|
<PaketRestoreRequired>false</PaketRestoreRequired>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- Step 2 b detect relevant changes in project file (new targetframework) -->
|
||||||
|
<PropertyGroup Condition=" '$(DoAllResolvedFilesExist)' != 'true' ">
|
||||||
|
<PaketRestoreRequired>true</PaketRestoreRequired>
|
||||||
|
<PaketRestoreRequiredReason>target-framework '$(TargetFramework)' or '$(TargetFrameworks)' files @(PaketResolvedFilePaths)</PaketRestoreRequiredReason>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- Step 3 Restore project specific stuff if required -->
|
||||||
|
<Message Condition=" '$(PaketRestoreRequired)' == 'true' " Importance="low" Text="Detected a change ('$(PaketRestoreRequiredReason)') in the project file '$(MSBuildProjectFullPath)', calling paket restore" />
|
||||||
|
<Error Text="Stop build because of PAKET_ERROR_ON_MSBUILD_EXEC and we detected a change ('$(PaketRestoreRequiredReason)') in the project file '$(MSBuildProjectFullPath)'" Condition=" '$(PAKET_ERROR_ON_MSBUILD_EXEC)' == 'true' AND '$(PaketRestoreRequired)' == 'true' " />
|
||||||
|
<Exec Command='$(PaketCommand) restore --project "$(MSBuildProjectFullPath)" --output-path "$(PaketIntermediateOutputPath)" --target-framework "$(TargetFrameworks)"' Condition=" '$(PaketRestoreRequired)' == 'true' AND '$(TargetFramework)' == '' " ContinueOnError="false" />
|
||||||
|
<Exec Command='$(PaketCommand) restore --project "$(MSBuildProjectFullPath)" --output-path "$(PaketIntermediateOutputPath)" --target-framework "$(TargetFramework)"' Condition=" '$(PaketRestoreRequired)' == 'true' AND '$(TargetFramework)' != '' " ContinueOnError="false" />
|
||||||
|
|
||||||
|
<!-- This shouldn't actually happen, but just to be sure. -->
|
||||||
|
<PropertyGroup>
|
||||||
|
<DoAllResolvedFilesExist>false</DoAllResolvedFilesExist>
|
||||||
|
<DoAllResolvedFilesExist Condition="Exists(%(PaketResolvedFilePaths.Identity))">true</DoAllResolvedFilesExist>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Error Condition=" '$(DoAllResolvedFilesExist)' != 'true' AND '$(ResolveNuGetPackages)' != 'False' " Text="One Paket file '@(PaketResolvedFilePaths)' is missing while restoring $(MSBuildProjectFile). Please delete 'paket-files/paket.restore.cached' and call 'paket restore'." />
|
||||||
|
|
||||||
|
<!-- Step 4 forward all msbuild properties (PackageReference, DotNetCliToolReference) to msbuild -->
|
||||||
|
<ReadLinesFromFile Condition="($(DesignTimeBuild) != true OR '$(PaketPropsLoaded)' != 'true') AND '@(PaketResolvedFilePaths)' != ''" File="%(PaketResolvedFilePaths.Identity)" >
|
||||||
|
<Output TaskParameter="Lines" ItemName="PaketReferencesFileLines"/>
|
||||||
|
</ReadLinesFromFile>
|
||||||
|
|
||||||
|
<ItemGroup Condition="($(DesignTimeBuild) != true OR '$(PaketPropsLoaded)' != 'true') AND '@(PaketReferencesFileLines)' != '' " >
|
||||||
|
<PaketReferencesFileLinesInfo Include="@(PaketReferencesFileLines)" >
|
||||||
|
<Splits>$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',').Length)</Splits>
|
||||||
|
<PackageName>$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[0])</PackageName>
|
||||||
|
<PackageVersion>$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[1])</PackageVersion>
|
||||||
|
<AllPrivateAssets>$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[4])</AllPrivateAssets>
|
||||||
|
<CopyLocal Condition="'$(Splits)' == '6'">$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[5])</CopyLocal>
|
||||||
|
</PaketReferencesFileLinesInfo>
|
||||||
|
<PackageReference Include="%(PaketReferencesFileLinesInfo.PackageName)">
|
||||||
|
<Version>%(PaketReferencesFileLinesInfo.PackageVersion)</Version>
|
||||||
|
<PrivateAssets Condition=" ('%(PaketReferencesFileLinesInfo.AllPrivateAssets)' == 'true') Or ('$(PackAsTool)' == 'true') ">All</PrivateAssets>
|
||||||
|
<ExcludeAssets Condition=" '%(PaketReferencesFileLinesInfo.Splits)' == '6' And %(PaketReferencesFileLinesInfo.CopyLocal) == 'false'">runtime</ExcludeAssets>
|
||||||
|
<ExcludeAssets Condition=" '%(PaketReferencesFileLinesInfo.Splits)' != '6' And %(PaketReferencesFileLinesInfo.AllPrivateAssets) == 'exclude'">runtime</ExcludeAssets>
|
||||||
|
<Publish Condition=" '$(PackAsTool)' == 'true' ">true</Publish>
|
||||||
|
<AllowExplicitVersion>true</AllowExplicitVersion>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<PaketCliToolFilePath>$(PaketIntermediateOutputPath)/$(MSBuildProjectFile).paket.clitools</PaketCliToolFilePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ReadLinesFromFile File="$(PaketCliToolFilePath)" >
|
||||||
|
<Output TaskParameter="Lines" ItemName="PaketCliToolFileLines"/>
|
||||||
|
</ReadLinesFromFile>
|
||||||
|
|
||||||
|
<ItemGroup Condition=" '@(PaketCliToolFileLines)' != '' " >
|
||||||
|
<PaketCliToolFileLinesInfo Include="@(PaketCliToolFileLines)" >
|
||||||
|
<PackageName>$([System.String]::Copy('%(PaketCliToolFileLines.Identity)').Split(',')[0])</PackageName>
|
||||||
|
<PackageVersion>$([System.String]::Copy('%(PaketCliToolFileLines.Identity)').Split(',')[1])</PackageVersion>
|
||||||
|
</PaketCliToolFileLinesInfo>
|
||||||
|
<DotNetCliToolReference Include="%(PaketCliToolFileLinesInfo.PackageName)">
|
||||||
|
<Version>%(PaketCliToolFileLinesInfo.PackageVersion)</Version>
|
||||||
|
</DotNetCliToolReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Disabled for now until we know what to do with runtime deps - https://github.com/fsprojects/Paket/issues/2964
|
||||||
|
<PropertyGroup>
|
||||||
|
<RestoreConfigFile>$(PaketIntermediateOutputPath)/$(MSBuildProjectFile).NuGet.Config</RestoreConfigFile>
|
||||||
|
</PropertyGroup> -->
|
||||||
|
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="PaketDisableDirectPack" AfterTargets="_IntermediatePack" BeforeTargets="GenerateNuspec" Condition="('$(IsPackable)' == '' Or '$(IsPackable)' == 'true') And Exists('$(PaketIntermediateOutputPath)/$(MSBuildProjectFile).references')" >
|
||||||
|
<PropertyGroup>
|
||||||
|
<ContinuePackingAfterGeneratingNuspec>false</ContinuePackingAfterGeneratingNuspec>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="PaketOverrideNuspec" AfterTargets="GenerateNuspec" Condition="('$(IsPackable)' == '' Or '$(IsPackable)' == 'true') And Exists('$(PaketIntermediateOutputPath)/$(MSBuildProjectFile).references')" >
|
||||||
|
<ItemGroup>
|
||||||
|
<_NuspecFilesNewLocation Include="$(PaketIntermediateOutputPath)\$(Configuration)\*.nuspec"/>
|
||||||
|
<MSBuildMajorVersion Include="$(DetectedMSBuildVersion.Replace(`-`, `.`).Split(`.`)[0])" />
|
||||||
|
<MSBuildMinorVersion Include="$(DetectedMSBuildVersion.Replace(`-`, `.`).Split(`.`)[1])" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<PaketProjectFile>$(MSBuildProjectDirectory)/$(MSBuildProjectFile)</PaketProjectFile>
|
||||||
|
<ContinuePackingAfterGeneratingNuspec>true</ContinuePackingAfterGeneratingNuspec>
|
||||||
|
<UseMSBuild16_0_Pack>false</UseMSBuild16_0_Pack>
|
||||||
|
<UseMSBuild16_0_Pack Condition=" '@(MSBuildMajorVersion)' >= '16' ">true</UseMSBuild16_0_Pack>
|
||||||
|
<UseMSBuild15_9_Pack>false</UseMSBuild15_9_Pack>
|
||||||
|
<UseMSBuild15_9_Pack Condition=" '@(MSBuildMajorVersion)' == '15' AND '@(MSBuildMinorVersion)' > '8' ">true</UseMSBuild15_9_Pack>
|
||||||
|
<UseMSBuild15_8_Pack>false</UseMSBuild15_8_Pack>
|
||||||
|
<UseMSBuild15_8_Pack Condition=" '$(NuGetToolVersion)' != '4.0.0' AND (! $(UseMSBuild15_9_Pack)) AND (! $(UseMSBuild16_0_Pack)) ">true</UseMSBuild15_8_Pack>
|
||||||
|
<UseNuGet4_Pack>false</UseNuGet4_Pack>
|
||||||
|
<UseNuGet4_Pack Condition=" (! $(UseMSBuild15_8_Pack)) AND (! $(UseMSBuild15_9_Pack)) AND (! $(UseMSBuild16_0_Pack)) ">true</UseNuGet4_Pack>
|
||||||
|
<AdjustedNuspecOutputPath>$(PaketIntermediateOutputPath)\$(Configuration)</AdjustedNuspecOutputPath>
|
||||||
|
<AdjustedNuspecOutputPath Condition="@(_NuspecFilesNewLocation) == ''">$(PaketIntermediateOutputPath)</AdjustedNuspecOutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<_NuspecFiles Include="$(AdjustedNuspecOutputPath)\*.$(PackageVersion.Split(`+`)[0]).nuspec"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Error Text="Error Because of PAKET_ERROR_ON_MSBUILD_EXEC (not calling fix-nuspecs)" Condition=" '$(PAKET_ERROR_ON_MSBUILD_EXEC)' == 'true' " />
|
||||||
|
<Exec Condition="@(_NuspecFiles) != ''" Command='$(PaketCommand) fix-nuspecs files "@(_NuspecFiles)" project-file "$(PaketProjectFile)" ' />
|
||||||
|
<Error Condition="@(_NuspecFiles) == ''" Text='Could not find nuspec files in "$(AdjustedNuspecOutputPath)" (Version: "$(PackageVersion)"), therefore we cannot call "paket fix-nuspecs" and have to error out!' />
|
||||||
|
|
||||||
|
<ConvertToAbsolutePath Condition="@(_NuspecFiles) != ''" Paths="@(_NuspecFiles)">
|
||||||
|
<Output TaskParameter="AbsolutePaths" PropertyName="NuspecFileAbsolutePath" />
|
||||||
|
</ConvertToAbsolutePath>
|
||||||
|
|
||||||
|
<!-- Call Pack -->
|
||||||
|
<PackTask Condition="$(UseMSBuild16_0_Pack)"
|
||||||
|
PackItem="$(PackProjectInputFile)"
|
||||||
|
PackageFiles="@(_PackageFiles)"
|
||||||
|
PackageFilesToExclude="@(_PackageFilesToExclude)"
|
||||||
|
PackageVersion="$(PackageVersion)"
|
||||||
|
PackageId="$(PackageId)"
|
||||||
|
Title="$(Title)"
|
||||||
|
Authors="$(Authors)"
|
||||||
|
Description="$(Description)"
|
||||||
|
Copyright="$(Copyright)"
|
||||||
|
RequireLicenseAcceptance="$(PackageRequireLicenseAcceptance)"
|
||||||
|
LicenseUrl="$(PackageLicenseUrl)"
|
||||||
|
ProjectUrl="$(PackageProjectUrl)"
|
||||||
|
IconUrl="$(PackageIconUrl)"
|
||||||
|
ReleaseNotes="$(PackageReleaseNotes)"
|
||||||
|
Tags="$(PackageTags)"
|
||||||
|
DevelopmentDependency="$(DevelopmentDependency)"
|
||||||
|
BuildOutputInPackage="@(_BuildOutputInPackage)"
|
||||||
|
TargetPathsToSymbols="@(_TargetPathsToSymbols)"
|
||||||
|
SymbolPackageFormat="symbols.nupkg"
|
||||||
|
TargetFrameworks="@(_TargetFrameworks)"
|
||||||
|
AssemblyName="$(AssemblyName)"
|
||||||
|
PackageOutputPath="$(PackageOutputAbsolutePath)"
|
||||||
|
IncludeSymbols="$(IncludeSymbols)"
|
||||||
|
IncludeSource="$(IncludeSource)"
|
||||||
|
PackageTypes="$(PackageType)"
|
||||||
|
IsTool="$(IsTool)"
|
||||||
|
RepositoryUrl="$(RepositoryUrl)"
|
||||||
|
RepositoryType="$(RepositoryType)"
|
||||||
|
SourceFiles="@(_SourceFiles->Distinct())"
|
||||||
|
NoPackageAnalysis="$(NoPackageAnalysis)"
|
||||||
|
MinClientVersion="$(MinClientVersion)"
|
||||||
|
Serviceable="$(Serviceable)"
|
||||||
|
FrameworkAssemblyReferences="@(_FrameworkAssemblyReferences)"
|
||||||
|
ContinuePackingAfterGeneratingNuspec="$(ContinuePackingAfterGeneratingNuspec)"
|
||||||
|
NuspecOutputPath="$(AdjustedNuspecOutputPath)"
|
||||||
|
IncludeBuildOutput="$(IncludeBuildOutput)"
|
||||||
|
BuildOutputFolders="$(BuildOutputTargetFolder)"
|
||||||
|
ContentTargetFolders="$(ContentTargetFolders)"
|
||||||
|
RestoreOutputPath="$(RestoreOutputAbsolutePath)"
|
||||||
|
NuspecFile="$(NuspecFileAbsolutePath)"
|
||||||
|
NuspecBasePath="$(NuspecBasePath)"
|
||||||
|
NuspecProperties="$(NuspecProperties)"
|
||||||
|
PackageLicenseFile="$(PackageLicenseFile)"
|
||||||
|
PackageLicenseExpression="$(PackageLicenseExpression)"
|
||||||
|
PackageLicenseExpressionVersion="$(PackageLicenseExpressionVersion)" />
|
||||||
|
|
||||||
|
<PackTask Condition="$(UseMSBuild15_9_Pack)"
|
||||||
|
PackItem="$(PackProjectInputFile)"
|
||||||
|
PackageFiles="@(_PackageFiles)"
|
||||||
|
PackageFilesToExclude="@(_PackageFilesToExclude)"
|
||||||
|
PackageVersion="$(PackageVersion)"
|
||||||
|
PackageId="$(PackageId)"
|
||||||
|
Title="$(Title)"
|
||||||
|
Authors="$(Authors)"
|
||||||
|
Description="$(Description)"
|
||||||
|
Copyright="$(Copyright)"
|
||||||
|
RequireLicenseAcceptance="$(PackageRequireLicenseAcceptance)"
|
||||||
|
LicenseUrl="$(PackageLicenseUrl)"
|
||||||
|
ProjectUrl="$(PackageProjectUrl)"
|
||||||
|
IconUrl="$(PackageIconUrl)"
|
||||||
|
ReleaseNotes="$(PackageReleaseNotes)"
|
||||||
|
Tags="$(PackageTags)"
|
||||||
|
DevelopmentDependency="$(DevelopmentDependency)"
|
||||||
|
BuildOutputInPackage="@(_BuildOutputInPackage)"
|
||||||
|
TargetPathsToSymbols="@(_TargetPathsToSymbols)"
|
||||||
|
SymbolPackageFormat="symbols.nupkg"
|
||||||
|
TargetFrameworks="@(_TargetFrameworks)"
|
||||||
|
AssemblyName="$(AssemblyName)"
|
||||||
|
PackageOutputPath="$(PackageOutputAbsolutePath)"
|
||||||
|
IncludeSymbols="$(IncludeSymbols)"
|
||||||
|
IncludeSource="$(IncludeSource)"
|
||||||
|
PackageTypes="$(PackageType)"
|
||||||
|
IsTool="$(IsTool)"
|
||||||
|
RepositoryUrl="$(RepositoryUrl)"
|
||||||
|
RepositoryType="$(RepositoryType)"
|
||||||
|
SourceFiles="@(_SourceFiles->Distinct())"
|
||||||
|
NoPackageAnalysis="$(NoPackageAnalysis)"
|
||||||
|
MinClientVersion="$(MinClientVersion)"
|
||||||
|
Serviceable="$(Serviceable)"
|
||||||
|
FrameworkAssemblyReferences="@(_FrameworkAssemblyReferences)"
|
||||||
|
ContinuePackingAfterGeneratingNuspec="$(ContinuePackingAfterGeneratingNuspec)"
|
||||||
|
NuspecOutputPath="$(AdjustedNuspecOutputPath)"
|
||||||
|
IncludeBuildOutput="$(IncludeBuildOutput)"
|
||||||
|
BuildOutputFolder="$(BuildOutputTargetFolder)"
|
||||||
|
ContentTargetFolders="$(ContentTargetFolders)"
|
||||||
|
RestoreOutputPath="$(RestoreOutputAbsolutePath)"
|
||||||
|
NuspecFile="$(NuspecFileAbsolutePath)"
|
||||||
|
NuspecBasePath="$(NuspecBasePath)"
|
||||||
|
NuspecProperties="$(NuspecProperties)"/>
|
||||||
|
|
||||||
|
<PackTask Condition="$(UseMSBuild15_8_Pack)"
|
||||||
|
PackItem="$(PackProjectInputFile)"
|
||||||
|
PackageFiles="@(_PackageFiles)"
|
||||||
|
PackageFilesToExclude="@(_PackageFilesToExclude)"
|
||||||
|
PackageVersion="$(PackageVersion)"
|
||||||
|
PackageId="$(PackageId)"
|
||||||
|
Title="$(Title)"
|
||||||
|
Authors="$(Authors)"
|
||||||
|
Description="$(Description)"
|
||||||
|
Copyright="$(Copyright)"
|
||||||
|
RequireLicenseAcceptance="$(PackageRequireLicenseAcceptance)"
|
||||||
|
LicenseUrl="$(PackageLicenseUrl)"
|
||||||
|
ProjectUrl="$(PackageProjectUrl)"
|
||||||
|
IconUrl="$(PackageIconUrl)"
|
||||||
|
ReleaseNotes="$(PackageReleaseNotes)"
|
||||||
|
Tags="$(PackageTags)"
|
||||||
|
DevelopmentDependency="$(DevelopmentDependency)"
|
||||||
|
BuildOutputInPackage="@(_BuildOutputInPackage)"
|
||||||
|
TargetPathsToSymbols="@(_TargetPathsToSymbols)"
|
||||||
|
TargetFrameworks="@(_TargetFrameworks)"
|
||||||
|
AssemblyName="$(AssemblyName)"
|
||||||
|
PackageOutputPath="$(PackageOutputAbsolutePath)"
|
||||||
|
IncludeSymbols="$(IncludeSymbols)"
|
||||||
|
IncludeSource="$(IncludeSource)"
|
||||||
|
PackageTypes="$(PackageType)"
|
||||||
|
IsTool="$(IsTool)"
|
||||||
|
RepositoryUrl="$(RepositoryUrl)"
|
||||||
|
RepositoryType="$(RepositoryType)"
|
||||||
|
SourceFiles="@(_SourceFiles->Distinct())"
|
||||||
|
NoPackageAnalysis="$(NoPackageAnalysis)"
|
||||||
|
MinClientVersion="$(MinClientVersion)"
|
||||||
|
Serviceable="$(Serviceable)"
|
||||||
|
FrameworkAssemblyReferences="@(_FrameworkAssemblyReferences)"
|
||||||
|
ContinuePackingAfterGeneratingNuspec="$(ContinuePackingAfterGeneratingNuspec)"
|
||||||
|
NuspecOutputPath="$(AdjustedNuspecOutputPath)"
|
||||||
|
IncludeBuildOutput="$(IncludeBuildOutput)"
|
||||||
|
BuildOutputFolder="$(BuildOutputTargetFolder)"
|
||||||
|
ContentTargetFolders="$(ContentTargetFolders)"
|
||||||
|
RestoreOutputPath="$(RestoreOutputAbsolutePath)"
|
||||||
|
NuspecFile="$(NuspecFileAbsolutePath)"
|
||||||
|
NuspecBasePath="$(NuspecBasePath)"
|
||||||
|
NuspecProperties="$(NuspecProperties)"/>
|
||||||
|
|
||||||
|
<PackTask Condition="$(UseNuGet4_Pack)"
|
||||||
|
PackItem="$(PackProjectInputFile)"
|
||||||
|
PackageFiles="@(_PackageFiles)"
|
||||||
|
PackageFilesToExclude="@(_PackageFilesToExclude)"
|
||||||
|
PackageVersion="$(PackageVersion)"
|
||||||
|
PackageId="$(PackageId)"
|
||||||
|
Title="$(Title)"
|
||||||
|
Authors="$(Authors)"
|
||||||
|
Description="$(Description)"
|
||||||
|
Copyright="$(Copyright)"
|
||||||
|
RequireLicenseAcceptance="$(PackageRequireLicenseAcceptance)"
|
||||||
|
LicenseUrl="$(PackageLicenseUrl)"
|
||||||
|
ProjectUrl="$(PackageProjectUrl)"
|
||||||
|
IconUrl="$(PackageIconUrl)"
|
||||||
|
ReleaseNotes="$(PackageReleaseNotes)"
|
||||||
|
Tags="$(PackageTags)"
|
||||||
|
TargetPathsToAssemblies="@(_TargetPathsToAssemblies->'%(FinalOutputPath)')"
|
||||||
|
TargetPathsToSymbols="@(_TargetPathsToSymbols)"
|
||||||
|
TargetFrameworks="@(_TargetFrameworks)"
|
||||||
|
AssemblyName="$(AssemblyName)"
|
||||||
|
PackageOutputPath="$(PackageOutputAbsolutePath)"
|
||||||
|
IncludeSymbols="$(IncludeSymbols)"
|
||||||
|
IncludeSource="$(IncludeSource)"
|
||||||
|
PackageTypes="$(PackageType)"
|
||||||
|
IsTool="$(IsTool)"
|
||||||
|
RepositoryUrl="$(RepositoryUrl)"
|
||||||
|
RepositoryType="$(RepositoryType)"
|
||||||
|
SourceFiles="@(_SourceFiles->Distinct())"
|
||||||
|
NoPackageAnalysis="$(NoPackageAnalysis)"
|
||||||
|
MinClientVersion="$(MinClientVersion)"
|
||||||
|
Serviceable="$(Serviceable)"
|
||||||
|
AssemblyReferences="@(_References)"
|
||||||
|
ContinuePackingAfterGeneratingNuspec="$(ContinuePackingAfterGeneratingNuspec)"
|
||||||
|
NuspecOutputPath="$(AdjustedNuspecOutputPath)"
|
||||||
|
IncludeBuildOutput="$(IncludeBuildOutput)"
|
||||||
|
BuildOutputFolder="$(BuildOutputTargetFolder)"
|
||||||
|
ContentTargetFolders="$(ContentTargetFolders)"
|
||||||
|
RestoreOutputPath="$(RestoreOutputAbsolutePath)"
|
||||||
|
NuspecFile="$(NuspecFileAbsolutePath)"
|
||||||
|
NuspecBasePath="$(NuspecBasePath)"
|
||||||
|
NuspecProperties="$(NuspecProperties)"/>
|
||||||
|
</Target>
|
||||||
|
<!--/+:cnd:noEmit-->
|
||||||
|
</Project>
|
||||||
17
.vscode/extensions.json
vendored
Normal file
17
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||||
|
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||||
|
|
||||||
|
// List of extensions which should be recommended for users of this workspace.
|
||||||
|
"recommendations": [
|
||||||
|
"ionide.ionide-fsharp",
|
||||||
|
"ms-vscode.csharp",
|
||||||
|
"editorconfig.editorconfig",
|
||||||
|
"msjsdiag.debugger-for-chrome",
|
||||||
|
"ms-vscode-remote.remote-containers"
|
||||||
|
],
|
||||||
|
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||||
|
"unwantedRecommendations": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
51
.vscode/launch.json
vendored
Normal file
51
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Debug Server",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "Build Server",
|
||||||
|
"program": "${workspaceFolder}/src/Server/bin/Debug/netcoreapp2.2/Server.dll",
|
||||||
|
"args": [],
|
||||||
|
"logging": {
|
||||||
|
"moduleLoad": false
|
||||||
|
},
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"console": "internalConsole",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Debug Client",
|
||||||
|
"type": "chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "Watch Client",
|
||||||
|
"url": "http://localhost:8080",
|
||||||
|
"webRoot": "${workspaceFolder}/src/Client",
|
||||||
|
"sourceMaps": true,
|
||||||
|
"sourceMapPathOverrides": {
|
||||||
|
"webpack:///*": "${workspaceFolder}/*",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Watch SAFE App",
|
||||||
|
"type": "chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "Watch Client and Server",
|
||||||
|
"url": "http://localhost:8080",
|
||||||
|
"env": {
|
||||||
|
"vsCodeSession":"true"
|
||||||
|
},
|
||||||
|
"webRoot": "${workspaceFolder}/src/Client",
|
||||||
|
"sourceMaps": true,
|
||||||
|
"sourceMapPathOverrides": {
|
||||||
|
"webpack:///*": "${workspaceFolder}/*",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"compounds": [
|
||||||
|
{
|
||||||
|
"name": "Debug SAFE App",
|
||||||
|
"configurations": [ "Debug Server", "Debug Client" ],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
81
.vscode/tasks.json
vendored
Normal file
81
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
// for the documentation about the tasks.json format
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "Build Server",
|
||||||
|
"command": "dotnet",
|
||||||
|
"args": [ "build" ],
|
||||||
|
"type": "shell",
|
||||||
|
"options": { "cwd": "${workspaceFolder}/src/Server" },
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": [ "$msCompile" ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Watch Client and Server",
|
||||||
|
"command": "fake",
|
||||||
|
"args": [ "build", "-t", "Run" ],
|
||||||
|
"type": "shell",
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"env": {
|
||||||
|
"vsCodeSession": "true"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"group": "build",
|
||||||
|
"isBackground": true,
|
||||||
|
"problemMatcher": {
|
||||||
|
"fileLocation": "absolute",
|
||||||
|
"background": {
|
||||||
|
"beginsPattern": { "regexp": "run Run" },
|
||||||
|
"endsPattern": { "regexp": "i 「wdm」: Compiled|ℹ 「wdm」: Compiled|The terminal process terminated" },
|
||||||
|
"activeOnStart": true
|
||||||
|
},
|
||||||
|
"pattern": {
|
||||||
|
"regexp": "^(.*)\\((\\d+),(\\d+)\\): \\((\\d+),(\\d+)\\) (warning|error) FABLE: (.*)$",
|
||||||
|
"file": 1,
|
||||||
|
"line": 2,
|
||||||
|
"column": 3,
|
||||||
|
"endLine": 4,
|
||||||
|
"endColumn": 5,
|
||||||
|
"severity": 6,
|
||||||
|
"message": 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Watch Client",
|
||||||
|
"command": "fake",
|
||||||
|
"args": [ "build", "-t", "Run" ],
|
||||||
|
"type": "shell",
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"env": {
|
||||||
|
"vsCodeSession": "true",
|
||||||
|
"safeClientOnly": "true"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"group": "build",
|
||||||
|
"isBackground": true,
|
||||||
|
"problemMatcher": {
|
||||||
|
"fileLocation": "absolute",
|
||||||
|
"background": {
|
||||||
|
"beginsPattern": { "regexp": "run Run" },
|
||||||
|
"endsPattern": { "regexp": "i 「wdm」: Compiled|ℹ 「wdm」: Compiled|The terminal process terminated" },
|
||||||
|
"activeOnStart": true
|
||||||
|
},
|
||||||
|
"pattern": {
|
||||||
|
"regexp": "^(.*)\\((\\d+),(\\d+)\\): \\((\\d+),(\\d+)\\) (warning|error) FABLE: (.*)$",
|
||||||
|
"file": 1,
|
||||||
|
"line": 2,
|
||||||
|
"column": 3,
|
||||||
|
"endLine": 4,
|
||||||
|
"endColumn": 5,
|
||||||
|
"severity": 6,
|
||||||
|
"message": 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
37
README.md
Normal file
37
README.md
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# SAFE Template
|
||||||
|
|
||||||
|
This template can be used to generate a full-stack web application using the [SAFE Stack](https://safe-stack.github.io/). It was created using the dotnet [SAFE Template](https://safe-stack.github.io/docs/template-overview/). If you want to learn more about the template why not start with the [quick start](https://safe-stack.github.io/docs/quickstart/) guide?
|
||||||
|
|
||||||
|
## Install pre-requisites
|
||||||
|
|
||||||
|
You'll need to install the following pre-requisites in order to build SAFE applications
|
||||||
|
|
||||||
|
* The [.NET Core SDK](https://www.microsoft.com/net/download)
|
||||||
|
* [FAKE 5](https://fake.build/) installed as a [global tool](https://fake.build/fake-gettingstarted.html#Install-FAKE)
|
||||||
|
* The [Yarn](https://yarnpkg.com/lang/en/docs/install/) package manager (you an also use `npm` but the usage of `yarn` is encouraged).
|
||||||
|
* [Node LTS](https://nodejs.org/en/download/) installed for the front end components.
|
||||||
|
* If you're running on OSX or Linux, you'll also need to install [Mono](https://www.mono-project.com/docs/getting-started/install/).
|
||||||
|
|
||||||
|
## Work with the application
|
||||||
|
|
||||||
|
To concurrently run the server and the client components in watch mode use the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
fake build -t Run
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## SAFE Stack Documentation
|
||||||
|
|
||||||
|
You will find more documentation about the used F# components at the following places:
|
||||||
|
|
||||||
|
* [Saturn](https://saturnframework.org/docs/)
|
||||||
|
* [Fable](https://fable.io/docs/)
|
||||||
|
* [Elmish](https://elmish.github.io/elmish/)
|
||||||
|
* [Fulma](https://fulma.github.io/Fulma/)
|
||||||
|
|
||||||
|
If you want to know more about the full Azure Stack and all of it's components (including Azure) visit the official [SAFE documentation](https://safe-stack.github.io/docs/).
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
* **fake not found** - If you fail to execute `fake` from command line after installing it as a global tool, you might need to add it to your `PATH` manually: (e.g. `export PATH="$HOME/.dotnet/tools:$PATH"` on unix) - [related GitHub issue](https://github.com/dotnet/cli/issues/9321)
|
||||||
2
RELEASE_NOTES.md
Normal file
2
RELEASE_NOTES.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
### 0.0.1 - 2019-10-05
|
||||||
|
* Initial release
|
||||||
127
build.fsx
Normal file
127
build.fsx
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
#r "paket: groupref build //"
|
||||||
|
#load "./.fake/build.fsx/intellisense.fsx"
|
||||||
|
|
||||||
|
#if !FAKE
|
||||||
|
#r "netstandard"
|
||||||
|
#r "Facades/netstandard" // https://github.com/ionide/ionide-vscode-fsharp/issues/839#issuecomment-396296095
|
||||||
|
#endif
|
||||||
|
|
||||||
|
open System
|
||||||
|
|
||||||
|
open Fake.Core
|
||||||
|
open Fake.DotNet
|
||||||
|
open Fake.IO
|
||||||
|
|
||||||
|
Target.initEnvironment ()
|
||||||
|
|
||||||
|
let serverPath = Path.getFullName "./src/Server"
|
||||||
|
let clientPath = Path.getFullName "./src/Client"
|
||||||
|
let clientDeployPath = Path.combine clientPath "deploy"
|
||||||
|
let deployDir = Path.getFullName "./deploy"
|
||||||
|
|
||||||
|
let release = ReleaseNotes.load "RELEASE_NOTES.md"
|
||||||
|
|
||||||
|
let platformTool tool winTool =
|
||||||
|
let tool = if Environment.isUnix then tool else winTool
|
||||||
|
match ProcessUtils.tryFindFileOnPath tool with
|
||||||
|
| Some t -> t
|
||||||
|
| _ ->
|
||||||
|
let errorMsg =
|
||||||
|
tool + " was not found in path. " +
|
||||||
|
"Please install it and make sure it's available from your path. " +
|
||||||
|
"See https://safe-stack.github.io/docs/quickstart/#install-pre-requisites for more info"
|
||||||
|
failwith errorMsg
|
||||||
|
|
||||||
|
let nodeTool = platformTool "node" "node.exe"
|
||||||
|
let yarnTool = platformTool "yarn" "yarn.cmd"
|
||||||
|
|
||||||
|
let runTool cmd args workingDir =
|
||||||
|
let arguments = args |> String.split ' ' |> Arguments.OfArgs
|
||||||
|
Command.RawCommand (cmd, arguments)
|
||||||
|
|> CreateProcess.fromCommand
|
||||||
|
|> CreateProcess.withWorkingDirectory workingDir
|
||||||
|
|> CreateProcess.ensureExitCode
|
||||||
|
|> Proc.run
|
||||||
|
|> ignore
|
||||||
|
|
||||||
|
let runDotNet cmd workingDir =
|
||||||
|
let result =
|
||||||
|
DotNet.exec (DotNet.Options.withWorkingDirectory workingDir) cmd ""
|
||||||
|
if result.ExitCode <> 0 then failwithf "'dotnet %s' failed in %s" cmd workingDir
|
||||||
|
|
||||||
|
let openBrowser url =
|
||||||
|
//https://github.com/dotnet/corefx/issues/10361
|
||||||
|
Command.ShellCommand url
|
||||||
|
|> CreateProcess.fromCommand
|
||||||
|
|> CreateProcess.ensureExitCodeWithMessage "opening browser failed"
|
||||||
|
|> Proc.run
|
||||||
|
|> ignore
|
||||||
|
|
||||||
|
|
||||||
|
Target.create "Clean" (fun _ ->
|
||||||
|
[ deployDir
|
||||||
|
clientDeployPath ]
|
||||||
|
|> Shell.cleanDirs
|
||||||
|
)
|
||||||
|
|
||||||
|
Target.create "InstallClient" (fun _ ->
|
||||||
|
printfn "Node version:"
|
||||||
|
runTool nodeTool "--version" __SOURCE_DIRECTORY__
|
||||||
|
printfn "Yarn version:"
|
||||||
|
runTool yarnTool "--version" __SOURCE_DIRECTORY__
|
||||||
|
runTool yarnTool "install --frozen-lockfile" __SOURCE_DIRECTORY__
|
||||||
|
)
|
||||||
|
|
||||||
|
Target.create "Build" (fun _ ->
|
||||||
|
runDotNet "build" serverPath
|
||||||
|
Shell.regexReplaceInFileWithEncoding
|
||||||
|
"let app = \".+\""
|
||||||
|
("let app = \"" + release.NugetVersion + "\"")
|
||||||
|
System.Text.Encoding.UTF8
|
||||||
|
(Path.combine clientPath "Version.fs")
|
||||||
|
runTool yarnTool "webpack-cli -p" __SOURCE_DIRECTORY__
|
||||||
|
)
|
||||||
|
|
||||||
|
Target.create "Run" (fun _ ->
|
||||||
|
let server = async {
|
||||||
|
runDotNet "watch run" serverPath
|
||||||
|
}
|
||||||
|
let client = async {
|
||||||
|
runTool yarnTool "webpack-dev-server" __SOURCE_DIRECTORY__
|
||||||
|
}
|
||||||
|
let browser = async {
|
||||||
|
do! Async.Sleep 5000
|
||||||
|
openBrowser "http://localhost:8080"
|
||||||
|
}
|
||||||
|
|
||||||
|
let vsCodeSession = Environment.hasEnvironVar "vsCodeSession"
|
||||||
|
let safeClientOnly = Environment.hasEnvironVar "safeClientOnly"
|
||||||
|
|
||||||
|
let tasks =
|
||||||
|
[ if not safeClientOnly then yield server
|
||||||
|
yield client
|
||||||
|
if not vsCodeSession then yield browser ]
|
||||||
|
|
||||||
|
tasks
|
||||||
|
|> Async.Parallel
|
||||||
|
|> Async.RunSynchronously
|
||||||
|
|> ignore
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
open Fake.Core.TargetOperators
|
||||||
|
|
||||||
|
"Clean"
|
||||||
|
==> "InstallClient"
|
||||||
|
==> "Build"
|
||||||
|
|
||||||
|
|
||||||
|
"Clean"
|
||||||
|
==> "InstallClient"
|
||||||
|
==> "Run"
|
||||||
|
|
||||||
|
Target.runOrDefaultWithArguments "Build"
|
||||||
44
lunchrun-web-safe.sln
Normal file
44
lunchrun-web-safe.sln
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 15
|
||||||
|
VisualStudioVersion = 15.0.27004.2005
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Client", "src\Client\Client.fsproj", "{73E8E820-C8AA-47CC-BB2B-152CA4D0B855}"
|
||||||
|
EndProject
|
||||||
|
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Server", "src\Server\Server.fsproj", "{73E8E820-C8AA-47CC-BB2B-152CA4D0B856}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{08CCFCF6-2248-43ED-A6EF-E972A2DA0E6A}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
build.fsx = build.fsx
|
||||||
|
package.json = package.json
|
||||||
|
paket.dependencies = paket.dependencies
|
||||||
|
paket.lock = paket.lock
|
||||||
|
README.md = README.md
|
||||||
|
webpack.config.js = webpack.config.js
|
||||||
|
yarn.lock = yarn.lock
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{73E8E820-C8AA-47CC-BB2B-152CA4D0B855}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{73E8E820-C8AA-47CC-BB2B-152CA4D0B855}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{73E8E820-C8AA-47CC-BB2B-152CA4D0B855}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{73E8E820-C8AA-47CC-BB2B-152CA4D0B855}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{73E8E820-C8AA-47CC-BB2B-152CA4D0B856}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{73E8E820-C8AA-47CC-BB2B-152CA4D0B856}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{73E8E820-C8AA-47CC-BB2B-152CA4D0B856}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{73E8E820-C8AA-47CC-BB2B-152CA4D0B856}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {7A0AA30E-4CD9-4359-9513-BA68E2E85245}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
33
package.json
Normal file
33
package.json
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.4.4",
|
||||||
|
"@babel/plugin-transform-runtime": "^7.4.4",
|
||||||
|
"@babel/polyfill": "^7.4.4",
|
||||||
|
"@babel/preset-env": "^7.4.4",
|
||||||
|
"@babel/runtime": "^7.4.4",
|
||||||
|
"@fortawesome/fontawesome-free": "^5.10.2",
|
||||||
|
"babel-loader": "^8.0.5",
|
||||||
|
"bulma": "^0.7.1",
|
||||||
|
"copy-webpack-plugin": "^4.6.0",
|
||||||
|
"core-js": "^3.2.1",
|
||||||
|
"css-loader": "^2.0.1",
|
||||||
|
"fable-compiler": "^2.3.3",
|
||||||
|
"fable-loader": "^2.1.8",
|
||||||
|
"file-loader": "^4.2.0",
|
||||||
|
"html-webpack-plugin": "^3.2.0",
|
||||||
|
"mini-css-extract-plugin": "^0.5.0",
|
||||||
|
"open-sans-fonts": "^1.5.1",
|
||||||
|
"react": "^16.9.0",
|
||||||
|
"react-dom": "^16.9.0",
|
||||||
|
"remotedev": "^0.2.9",
|
||||||
|
"sass": "^1.22.10",
|
||||||
|
"sass-loader": "^7.3.1",
|
||||||
|
"style-loader": "^0.23.1",
|
||||||
|
"terser": "^4.2.1",
|
||||||
|
"webpack": "^4.39.0",
|
||||||
|
"webpack-cli": "^3.3.7",
|
||||||
|
"webpack-dev-server": "^3.8.0",
|
||||||
|
"whatwg-fetch": "^3.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
35
paket.dependencies
Normal file
35
paket.dependencies
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
group Server
|
||||||
|
source https://api.nuget.org/v3/index.json
|
||||||
|
framework: netcoreapp2.2
|
||||||
|
storage: none
|
||||||
|
|
||||||
|
nuget FSharp.Core
|
||||||
|
nuget Saturn
|
||||||
|
nuget Thoth.Json.Giraffe
|
||||||
|
|
||||||
|
group Client
|
||||||
|
source https://api.nuget.org/v3/index.json
|
||||||
|
framework: netstandard2.0
|
||||||
|
storage: none
|
||||||
|
|
||||||
|
nuget Fable.Core ~> 3
|
||||||
|
nuget Fable.Elmish ~> 3
|
||||||
|
nuget Fable.Elmish.Debugger ~> 3
|
||||||
|
nuget Fable.Elmish.HMR ~> 4
|
||||||
|
nuget Fable.Elmish.React ~> 3
|
||||||
|
nuget Thoth.Fetch ~> 1
|
||||||
|
nuget Fable.React ~> 5
|
||||||
|
nuget Fulma ~> 2
|
||||||
|
nuget Fable.FontAwesome.Free ~> 2
|
||||||
|
|
||||||
|
group Build
|
||||||
|
source https://api.nuget.org/v3/index.json
|
||||||
|
framework: netstandard2.0
|
||||||
|
storage: none
|
||||||
|
|
||||||
|
nuget FSharp.Core
|
||||||
|
nuget Fake.Core.ReleaseNotes
|
||||||
|
nuget Fake.Core.Target
|
||||||
|
nuget Fake.DotNet.Cli
|
||||||
|
nuget Fake.IO.FileSystem
|
||||||
|
|
||||||
1661
paket.lock
Normal file
1661
paket.lock
Normal file
File diff suppressed because it is too large
Load Diff
77
src/Client/Client.fs
Normal file
77
src/Client/Client.fs
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
module Client
|
||||||
|
|
||||||
|
open Elmish
|
||||||
|
open Elmish.React
|
||||||
|
open Fable.React
|
||||||
|
open Fable.React.Props
|
||||||
|
open Fetch.Types
|
||||||
|
open Thoth.Fetch
|
||||||
|
open Fulma
|
||||||
|
open Thoth.Json
|
||||||
|
open Browser.Types
|
||||||
|
open Shared
|
||||||
|
|
||||||
|
let [<Literal>] ENTER_KEY = 13.
|
||||||
|
|
||||||
|
let onEnter msg dispatch =
|
||||||
|
OnKeyDown (fun ev ->
|
||||||
|
if ev.keyCode = ENTER_KEY then
|
||||||
|
dispatch msg)
|
||||||
|
|
||||||
|
let targetValue (ev: Event) =
|
||||||
|
(ev.target :?> HTMLInputElement).value
|
||||||
|
|
||||||
|
type Model = { Run: Run }
|
||||||
|
|
||||||
|
type Msg =
|
||||||
|
| StartRun
|
||||||
|
| UpdateName of string
|
||||||
|
|
||||||
|
//let initialCounter () = Fetch.fetchAs<Counter> "/api/init"
|
||||||
|
|
||||||
|
let init () : Model * Cmd<Msg> =
|
||||||
|
let initialModel = { Run = { Name = "george" } }
|
||||||
|
initialModel, Cmd.none
|
||||||
|
|
||||||
|
let update (msg : Msg) (currentModel : Model) : Model * Cmd<Msg> =
|
||||||
|
match msg with
|
||||||
|
| StartRun ->
|
||||||
|
let nextModel = { currentModel with Run = { Name = currentModel.Run.Name + " saved" } }
|
||||||
|
nextModel, Cmd.none
|
||||||
|
| UpdateName newName ->
|
||||||
|
let nextModel = { currentModel with Run = { Name = newName }}
|
||||||
|
nextModel, Cmd.none
|
||||||
|
|
||||||
|
let view (model : Model) (dispatch : Msg -> unit) =
|
||||||
|
Columns.columns []
|
||||||
|
[ Column.column [ Column.Offset (Screen.All, Column.Is3)
|
||||||
|
Column.Width (Screen.All, Column.Is6) ]
|
||||||
|
[ Box.box' []
|
||||||
|
[ Heading.h1 [] [ str "lunch run" ]
|
||||||
|
p [] [ str "Start a lunch run today!" ]
|
||||||
|
Field.div []
|
||||||
|
[ Control.div []
|
||||||
|
[ Input.text [ Input.Placeholder "lunch run name"
|
||||||
|
Input.Value model.Run.Name
|
||||||
|
Input.OnChange (fun ev -> targetValue ev |> UpdateName |> dispatch)
|
||||||
|
Input.Props [ onEnter StartRun dispatch ] ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
open Elmish.Debug
|
||||||
|
open Elmish.HMR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Program.mkProgram init update view
|
||||||
|
#if DEBUG
|
||||||
|
|> Program.withConsoleTrace
|
||||||
|
#endif
|
||||||
|
|> Program.withReactBatched "elmish-app"
|
||||||
|
#if DEBUG
|
||||||
|
|> Program.withDebugger
|
||||||
|
#endif
|
||||||
|
|> Program.run
|
||||||
16
src/Client/Client.fsproj
Normal file
16
src/Client/Client.fsproj
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<DefineConstants>FABLE_COMPILER</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="index.html" />
|
||||||
|
<None Include="paket.references" />
|
||||||
|
<None Include="style.scss" />
|
||||||
|
<Compile Include="..\Shared\Shared.fs" />
|
||||||
|
<Compile Include="Version.fs" />
|
||||||
|
<Compile Include="Client.fs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="..\..\.paket\Paket.Restore.targets" />
|
||||||
|
</Project>
|
||||||
5
src/Client/Version.fs
Normal file
5
src/Client/Version.fs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module Version
|
||||||
|
|
||||||
|
let template = "1.18.0"
|
||||||
|
|
||||||
|
let app = "0.0.1"
|
||||||
14
src/Client/index.html
Normal file
14
src/Client/index.html
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>lunch run!</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link rel="shortcut icon" type="image/png" href="/favicon.png"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="elmish-app"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
10
src/Client/paket.references
Normal file
10
src/Client/paket.references
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
group Client
|
||||||
|
FSharp.Core
|
||||||
|
Fable.Core
|
||||||
|
Fable.Elmish.Debugger
|
||||||
|
Fable.Elmish.React
|
||||||
|
Fable.Elmish.HMR
|
||||||
|
Thoth.Fetch
|
||||||
|
Fulma
|
||||||
|
Fable.FontAwesome.Free
|
||||||
|
|
||||||
BIN
src/Client/public/favicon.png
Normal file
BIN
src/Client/public/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 810 B |
17
src/Client/style.scss
Normal file
17
src/Client/style.scss
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
@charset "utf-8";
|
||||||
|
|
||||||
|
// FontAwesome
|
||||||
|
$fa_font_path: "~@fortawesome/fontawesome-free/webfonts";
|
||||||
|
@import '~@fortawesome/fontawesome-free/scss/fontawesome.scss';
|
||||||
|
@import '~@fortawesome/fontawesome-free/scss/regular.scss';
|
||||||
|
@import '~@fortawesome/fontawesome-free/scss/solid.scss';
|
||||||
|
@import '~@fortawesome/fontawesome-free/scss/brands.scss';
|
||||||
|
|
||||||
|
// OpenSans
|
||||||
|
$FontPathOpenSans: "~open-sans-fonts/open-sans";
|
||||||
|
@import '~open-sans-fonts/open-sans';
|
||||||
|
$family-primary: 'Open Sans';
|
||||||
|
|
||||||
|
// Bulma
|
||||||
|
@import "~bulma/bulma";
|
||||||
|
|
||||||
37
src/Server/Server.fs
Normal file
37
src/Server/Server.fs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
open System.IO
|
||||||
|
open System.Threading.Tasks
|
||||||
|
|
||||||
|
open Microsoft.AspNetCore.Builder
|
||||||
|
open Microsoft.Extensions.DependencyInjection
|
||||||
|
open FSharp.Control.Tasks.V2
|
||||||
|
open Giraffe
|
||||||
|
open Saturn
|
||||||
|
open Shared
|
||||||
|
|
||||||
|
|
||||||
|
let tryGetEnv = System.Environment.GetEnvironmentVariable >> function null | "" -> None | x -> Some x
|
||||||
|
|
||||||
|
let publicPath = Path.GetFullPath "../Client/public"
|
||||||
|
|
||||||
|
let port =
|
||||||
|
"SERVER_PORT"
|
||||||
|
|> tryGetEnv |> Option.map uint16 |> Option.defaultValue 8085us
|
||||||
|
|
||||||
|
// let webApp = router {
|
||||||
|
// get "/api/init" (fun next ctx ->
|
||||||
|
// task {
|
||||||
|
// let counter = {Value = 7}
|
||||||
|
// return! json counter next ctx
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
let app = application {
|
||||||
|
url ("http://0.0.0.0:" + port.ToString() + "/")
|
||||||
|
//use_router webApp
|
||||||
|
memory_cache
|
||||||
|
use_static publicPath
|
||||||
|
use_json_serializer(Thoth.Json.Giraffe.ThothSerializer())
|
||||||
|
use_gzip
|
||||||
|
}
|
||||||
|
|
||||||
|
run app
|
||||||
13
src/Server/Server.fsproj
Normal file
13
src/Server/Server.fsproj
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="paket.references" />
|
||||||
|
<Compile Include="..\Shared\Shared.fs" />
|
||||||
|
<Compile Include="Server.fs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="..\..\.paket\Paket.Restore.targets" />
|
||||||
|
</Project>
|
||||||
4
src/Server/paket.references
Normal file
4
src/Server/paket.references
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
group Server
|
||||||
|
FSharp.Core
|
||||||
|
Saturn
|
||||||
|
Thoth.Json.Giraffe
|
||||||
5
src/Shared/Shared.fs
Normal file
5
src/Shared/Shared.fs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
namespace Shared
|
||||||
|
|
||||||
|
type Run = { Name : string }
|
||||||
|
|
||||||
|
|
||||||
165
webpack.config.js
Normal file
165
webpack.config.js
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
// Template for webpack.config.js in Fable projects
|
||||||
|
// Find latest version in https://github.com/fable-compiler/webpack-config-template
|
||||||
|
|
||||||
|
// In most cases, you'll only need to edit the CONFIG object (after dependencies)
|
||||||
|
// See below if you need better fine-tuning of Webpack options
|
||||||
|
|
||||||
|
// Dependencies. Also required: core-js, fable-loader, fable-compiler, @babel/core,
|
||||||
|
// @babel/preset-env, babel-loader, sass, sass-loader, css-loader, style-loader, file-loader
|
||||||
|
var path = require('path');
|
||||||
|
var webpack = require('webpack');
|
||||||
|
var HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
|
var CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||||
|
var MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||||
|
|
||||||
|
var CONFIG = {
|
||||||
|
// The tags to include the generated JS and CSS will be automatically injected in the HTML template
|
||||||
|
// See https://github.com/jantimon/html-webpack-plugin
|
||||||
|
indexHtmlTemplate: './src/Client/index.html',
|
||||||
|
fsharpEntry: './src/Client/Client.fsproj',
|
||||||
|
cssEntry: './src/Client/style.scss',
|
||||||
|
outputDir: './src/Client/deploy',
|
||||||
|
assetsDir: './src/Client/public',
|
||||||
|
devServerPort: 8080,
|
||||||
|
// When using webpack-dev-server, you may need to redirect some calls
|
||||||
|
// to a external API server. See https://webpack.js.org/configuration/dev-server/#devserver-proxy
|
||||||
|
devServerProxy: {
|
||||||
|
// redirect requests that start with /api/* to the server on port 8085
|
||||||
|
'/api/*': {
|
||||||
|
target: 'http://localhost:' + (process.env.SERVER_PROXY_PORT || "8085"),
|
||||||
|
changeOrigin: true
|
||||||
|
},
|
||||||
|
// redirect websocket requests that start with /socket/* to the server on the port 8085
|
||||||
|
'/socket/*': {
|
||||||
|
target: 'http://localhost:' + (process.env.SERVER_PROXY_PORT || "8085"),
|
||||||
|
ws: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Use babel-preset-env to generate JS compatible with most-used browsers.
|
||||||
|
// More info at https://babeljs.io/docs/en/next/babel-preset-env.html
|
||||||
|
babel: {
|
||||||
|
presets: [
|
||||||
|
['@babel/preset-env', {
|
||||||
|
modules: false,
|
||||||
|
// This adds polyfills when needed. Requires core-js dependency.
|
||||||
|
// See https://babeljs.io/docs/en/babel-preset-env#usebuiltins
|
||||||
|
useBuiltIns: 'usage',
|
||||||
|
corejs: 3
|
||||||
|
}]
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're running the webpack-dev-server, assume we're in development mode
|
||||||
|
var isProduction = !process.argv.find(v => v.indexOf('webpack-dev-server') !== -1);
|
||||||
|
console.log('Bundling for ' + (isProduction ? 'production' : 'development') + '...');
|
||||||
|
|
||||||
|
// The HtmlWebpackPlugin allows us to use a template for the index.html page
|
||||||
|
// and automatically injects <script> or <link> tags for generated bundles.
|
||||||
|
var commonPlugins = [
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
filename: 'index.html',
|
||||||
|
template: resolve(CONFIG.indexHtmlTemplate)
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// In development, split the JavaScript and CSS files in order to
|
||||||
|
// have a faster HMR support. In production bundle styles together
|
||||||
|
// with the code because the MiniCssExtractPlugin will extract the
|
||||||
|
// CSS in a separate files.
|
||||||
|
entry: isProduction ? {
|
||||||
|
app: [resolve(CONFIG.fsharpEntry), resolve(CONFIG.cssEntry)]
|
||||||
|
} : {
|
||||||
|
app: [resolve(CONFIG.fsharpEntry)],
|
||||||
|
style: [resolve(CONFIG.cssEntry)]
|
||||||
|
},
|
||||||
|
// Add a hash to the output file name in production
|
||||||
|
// to prevent browser caching if code changes
|
||||||
|
output: {
|
||||||
|
path: resolve(CONFIG.outputDir),
|
||||||
|
filename: isProduction ? '[name].[hash].js' : '[name].js'
|
||||||
|
},
|
||||||
|
mode: isProduction ? 'production' : 'development',
|
||||||
|
devtool: isProduction ? 'source-map' : 'eval-source-map',
|
||||||
|
optimization: {
|
||||||
|
splitChunks: {
|
||||||
|
chunks: 'all'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Besides the HtmlPlugin, we use the following plugins:
|
||||||
|
// PRODUCTION
|
||||||
|
// - MiniCssExtractPlugin: Extracts CSS from bundle to a different file
|
||||||
|
// To minify CSS, see https://github.com/webpack-contrib/mini-css-extract-plugin#minimizing-for-production
|
||||||
|
// - CopyWebpackPlugin: Copies static assets to output directory
|
||||||
|
// DEVELOPMENT
|
||||||
|
// - HotModuleReplacementPlugin: Enables hot reloading when code changes without refreshing
|
||||||
|
plugins: isProduction ?
|
||||||
|
commonPlugins.concat([
|
||||||
|
new MiniCssExtractPlugin({ filename: 'style.[hash].css' }),
|
||||||
|
new CopyWebpackPlugin([{ from: resolve(CONFIG.assetsDir) }]),
|
||||||
|
])
|
||||||
|
: commonPlugins.concat([
|
||||||
|
new webpack.HotModuleReplacementPlugin(),
|
||||||
|
]),
|
||||||
|
resolve: {
|
||||||
|
// See https://github.com/fable-compiler/Fable/issues/1490
|
||||||
|
symlinks: false
|
||||||
|
},
|
||||||
|
// Configuration for webpack-dev-server
|
||||||
|
devServer: {
|
||||||
|
publicPath: '/',
|
||||||
|
contentBase: resolve(CONFIG.assetsDir),
|
||||||
|
host: '0.0.0.0',
|
||||||
|
port: CONFIG.devServerPort,
|
||||||
|
proxy: CONFIG.devServerProxy,
|
||||||
|
hot: true,
|
||||||
|
inline: true
|
||||||
|
},
|
||||||
|
// - fable-loader: transforms F# into JS
|
||||||
|
// - babel-loader: transforms JS to old syntax (compatible with old browsers)
|
||||||
|
// - sass-loaders: transforms SASS/SCSS into JS
|
||||||
|
// - file-loader: Moves files referenced in the code (fonts, images) into output folder
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.fs(x|proj)?$/,
|
||||||
|
use: {
|
||||||
|
loader: 'fable-loader',
|
||||||
|
options: {
|
||||||
|
babel: CONFIG.babel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
use: {
|
||||||
|
loader: 'babel-loader',
|
||||||
|
options: CONFIG.babel
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(sass|scss|css)$/,
|
||||||
|
use: [
|
||||||
|
isProduction
|
||||||
|
? MiniCssExtractPlugin.loader
|
||||||
|
: 'style-loader',
|
||||||
|
'css-loader',
|
||||||
|
{
|
||||||
|
loader: 'sass-loader',
|
||||||
|
options: { implementation: require('sass') }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)(\?.*)?$/,
|
||||||
|
use: ['file-loader']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function resolve(filePath) {
|
||||||
|
return path.isAbsolute(filePath) ? filePath : path.join(__dirname, filePath);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user