Compare commits

..

19 Commits

Author SHA1 Message Date
Steve Sanderson
287c10fd2e Bump additional SPA templates package version to 1.0.0 2017-08-03 10:52:08 +01:00
Steve Sanderson
169ef12cd8 Change Microsoft.DotNet.Web.Spa.ProjectTemplates to use non-prerelease version number in NuGet package 2017-07-27 14:51:21 +01:00
Steve Sanderson
f5d58f3f2e Update AppVeyor build to use SDK 006857 2017-07-27 14:43:22 +01:00
Steve Sanderson
c2e4d4f261 Re-enable the "dotnet restore" postAction, like the stock templates 2017-07-27 14:41:55 +01:00
Steve Sanderson
50481fe23f Update templates to reference ASP.NET Core 2.0.0 final 2017-07-27 14:27:15 +01:00
Steve Sanderson
789ea5a320 Update to ASP.NET Core 2.0.0-rtm-26380 2017-07-19 14:24:32 +01:00
Steve Sanderson
c79db4e8e2 In React-Redux template, move Webpack config for images into sharedConfig so that adding images doesn't break the server build 2017-07-13 16:16:45 +01:00
Steve Sanderson
9528dd7432 Enable TS strict mode in all templates and generally clean up TS references 2017-07-13 10:11:59 +01:00
Stephan Troyer
b8c006a3e9 Update templates to support TypeScript 'strict' mode 2017-07-13 09:22:14 +01:00
Steve Sanderson
8b37dc8561 Update to ASP.NET Core 2.0.0-rtm-26272 2017-07-12 23:17:22 +01:00
Steve Sanderson
7b07fb66eb Update all templates to aspnet-webpack@2.0.1 2017-07-12 23:11:30 +01:00
Steve Sanderson
cdb04c74f9 Update aspnet-webpack to 2.0.1, automatically disabling the middleware if we detect the process doesn't have sufficient disk permissions 2017-07-12 23:06:05 +01:00
Steve Sanderson
a74941e3c8 Merge branch 'rel/2.0.0' into rel/2.0.0-templates 2017-07-12 15:30:14 +01:00
Steve Sanderson
dab0faea66 Update to AspNetCore 2.0.0-rtm-26219 2017-07-12 00:39:28 +01:00
Steve Sanderson
e65ecebac6 Make templates work with nonempty baseUrls (e.g., IIS virtual directories) 2017-07-11 23:56:51 +01:00
Steve Sanderson
bb0727c34c Update templates to newer aspnet NPM dependencies 2017-07-11 23:56:42 +01:00
Steve Sanderson
4903e12373 Publish aspnet-webpack-react as 3.0.0 since it's no longer beta 2017-07-11 23:55:50 +01:00
Steve Sanderson
56c806b34e Update aspnet-prerendering to 3.0.1, fixing the default "fetch" base URL to match the real application root URL 2017-07-11 23:55:49 +01:00
Steve Sanderson
8acba88160 Update aspnet-webpack to 2.0.0, now supporting HMR when apps are running in virtual directories 2017-07-11 18:57:52 +01:00
91 changed files with 2215 additions and 718 deletions

2
.gitignore vendored
View File

@@ -28,8 +28,6 @@ nuget.exe
.vs/
npm-debug.log
/.build/
global.json
*.g.targets
# The templates can't contain their own .gitignore files, because Yeoman has strange default handling for
# files with that name (https://github.com/npm/npm/issues/1862). So, each template instead has a template_gitignore

View File

@@ -1,4 +0,0 @@
<Project>
<Import Project="build\sources.props" />
<Import Project="build\dependencies.props" />
</Project>

View File

@@ -2,6 +2,8 @@
<configuration>
<packageSources>
<clear />
<!-- Restore sources should be defined in build/sources.props. -->
<add key="AspNetCore" value="https://dotnet.myget.org/F/aspnetcore-ci-release/api/v3/index.json" />
<add key="AspNetCoreTools" value="https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json" />
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>

View File

@@ -4,7 +4,7 @@ install:
- ps: Install-Product node 6.9.2 x64
# .NET Core SDK binaries
# Download .NET Core 2.0 Preview 3 SDK and add to PATH
- ps: $urlCurrent = "https://dotnetcli.azureedge.net/dotnet/Sdk/2.0.0-preview3-006729/dotnet-sdk-2.0.0-preview3-006729-win-x64.zip"
- ps: $urlCurrent = "https://dotnetcli.azureedge.net/dotnet/Sdk/2.0.0-preview3-006857/dotnet-sdk-2.0.0-preview3-006857-win-x64.zip"
- ps: $env:DOTNET_INSTALL_DIR = "$pwd\.dotnetsdk"
- ps: mkdir $env:DOTNET_INSTALL_DIR -Force | Out-Null
- ps: $tempFileCurrent = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())

219
build.ps1
View File

@@ -1,186 +1,67 @@
#!/usr/bin/env powershell
#requires -version 4
$ErrorActionPreference = "Stop"
<#
.SYNOPSIS
Build this repository
.DESCRIPTION
Downloads korebuild if required. Then builds the repository.
.PARAMETER Path
The folder to build. Defaults to the folder containing this script.
.PARAMETER Channel
The channel of KoreBuild to download. Overrides the value from the config file.
.PARAMETER DotNetHome
The directory where .NET Core tools will be stored.
.PARAMETER ToolsSource
The base url where build tools can be downloaded. Overrides the value from the config file.
.PARAMETER Update
Updates KoreBuild to the latest version even if a lock file is present.
.PARAMETER ConfigFile
The path to the configuration file that stores values. Defaults to version.props.
.PARAMETER MSBuildArgs
Arguments to be passed to MSBuild
.NOTES
This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be.
When the lockfile is not present, KoreBuild will create one using latest available version from $Channel.
The $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set
in the file are overridden by command line parameters.
.EXAMPLE
Example config file:
```json
function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries)
{
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json",
"channel": "dev",
"toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools"
while($true)
{
try
{
Invoke-WebRequest $url -OutFile $downloadLocation
break
}
catch
{
$exceptionMessage = $_.Exception.Message
Write-Host "Failed to download '$url': $exceptionMessage"
if ($retries -gt 0) {
$retries--
Write-Host "Waiting 10 seconds before retrying. Retries left: $retries"
Start-Sleep -Seconds 10
}
else
{
$exception = $_.Exception
throw $exception
}
}
}
}
```
#>
[CmdletBinding(PositionalBinding = $false)]
param(
[string]$Path = $PSScriptRoot,
[Alias('c')]
[string]$Channel,
[Alias('d')]
[string]$DotNetHome,
[Alias('s')]
[string]$ToolsSource,
[Alias('u')]
[switch]$Update,
[string]$ConfigFile = $null,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]]$MSBuildArgs
)
Set-StrictMode -Version 2
$ErrorActionPreference = 'Stop'
cd $PSScriptRoot
#
# Functions
#
$repoFolder = $PSScriptRoot
$env:REPO_FOLDER = $repoFolder
function Get-KoreBuild {
$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/2.0.0.zip"
if ($env:KOREBUILD_ZIP)
{
$koreBuildZip=$env:KOREBUILD_ZIP
}
$lockFile = Join-Path $Path 'korebuild-lock.txt'
$buildFolder = ".build"
$buildFile="$buildFolder\KoreBuild.ps1"
if (!(Test-Path $lockFile) -or $Update) {
Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile
}
if (!(Test-Path $buildFolder)) {
Write-Host "Downloading KoreBuild from $koreBuildZip"
$version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1
if (!$version) {
Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'"
}
$version = $version.TrimStart('version:').Trim()
$korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version)
$tempFolder=$env:TEMP + "\KoreBuild-" + [guid]::NewGuid()
New-Item -Path "$tempFolder" -Type directory | Out-Null
if (!(Test-Path $korebuildPath)) {
Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version"
New-Item -ItemType Directory -Path $korebuildPath | Out-Null
$remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip"
$localZipFile="$tempFolder\korebuild.zip"
DownloadWithRetry -url $koreBuildZip -downloadLocation $localZipFile -retries 6
try {
$tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip"
Get-RemoteFile $remotePath $tmpfile
if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) {
# Use built-in commands where possible as they are cross-plat compatible
Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath
}
else {
# Fallback to old approach for old installations of PowerShell
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath)
}
}
catch {
Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore
throw
}
finally {
Remove-Item $tmpfile -ErrorAction Ignore
}
}
[System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder)
return $korebuildPath
}
New-Item -Path "$buildFolder" -Type directory | Out-Null
copy-item "$tempFolder\**\build\*" $buildFolder -Recurse
function Join-Paths([string]$path, [string[]]$childPaths) {
$childPaths | ForEach-Object { $path = Join-Path $path $_ }
return $path
}
function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) {
if ($RemotePath -notlike 'http*') {
Copy-Item $RemotePath $LocalPath
return
}
$retries = 10
while ($retries -gt 0) {
$retries -= 1
try {
Invoke-WebRequest -UseBasicParsing -Uri $RemotePath -OutFile $LocalPath
return
}
catch {
Write-Verbose "Request failed. $retries retries remaining"
}
}
Write-Error "Download failed: '$RemotePath'."
}
#
# Main
#
# Load configuration or set defaults
$Path = Resolve-Path $Path
if (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' }
if (Test-Path $ConfigFile) {
try {
$config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json
if ($config) {
if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel }
if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource}
}
} catch {
Write-Warning "$ConfigFile could not be read. Its settings will be ignored."
Write-Warning $Error[0]
# Cleanup
if (Test-Path $tempFolder) {
Remove-Item -Recurse -Force $tempFolder
}
}
if (!$DotNetHome) {
$DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } `
elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} `
elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}`
else { Join-Path $PSScriptRoot '.dotnet'}
}
if (!$Channel) { $Channel = 'dev' }
if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' }
# Execute
$korebuildPath = Get-KoreBuild
Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1')
try {
Install-Tools $ToolsSource $DotNetHome
Invoke-RepositoryBuild $Path @MSBuildArgs
}
finally {
Remove-Module 'KoreBuild' -ErrorAction Ignore
}
&"$buildFile" @args

252
build.sh
View File

@@ -1,220 +1,46 @@
#!/usr/bin/env bash
repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $repoFolder
set -euo pipefail
#
# variables
#
RESET="\033[0m"
RED="\033[0;31m"
YELLOW="\033[0;33m"
MAGENTA="\033[0;95m"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
[ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet"
config_file="$DIR/korebuild.json"
verbose=false
update=false
repo_path="$DIR"
channel=''
tools_source=''
#
# Functions
#
__usage() {
echo "Usage: $(basename "${BASH_SOURCE[0]}") [options] [[--] <MSBUILD_ARG>...]"
echo ""
echo "Arguments:"
echo " <MSBUILD_ARG>... Arguments passed to MSBuild. Variable number of arguments allowed."
echo ""
echo "Options:"
echo " --verbose Show verbose output."
echo " -c|--channel <CHANNEL> The channel of KoreBuild to download. Overrides the value from the config file.."
echo " --config-file <FILE> The path to the configuration file that stores values. Defaults to korebuild.json."
echo " -d|--dotnet-home <DIR> The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet."
echo " --path <PATH> The directory to build. Defaults to the directory containing the script."
echo " -s|--tools-source <URL> The base url where build tools can be downloaded. Overrides the value from the config file."
echo " -u|--update Update to the latest KoreBuild even if the lock file is present."
echo ""
echo "Description:"
echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be."
echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel."
if [[ "${1:-}" != '--no-exit' ]]; then
exit 2
fi
}
get_korebuild() {
local version
local lock_file="$repo_path/korebuild-lock.txt"
if [ ! -f "$lock_file" ] || [ "$update" = true ]; then
__get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file"
fi
version="$(grep 'version:*' -m 1 "$lock_file")"
if [[ "$version" == '' ]]; then
__error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'"
return 1
fi
version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version"
{
if [ ! -d "$korebuild_path" ]; then
mkdir -p "$korebuild_path"
local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip"
tmpfile="$(mktemp)"
echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}"
if __get_remote_file "$remote_path" "$tmpfile"; then
unzip -q -d "$korebuild_path" "$tmpfile"
fi
rm "$tmpfile" || true
fi
source "$korebuild_path/KoreBuild.sh"
} || {
if [ -d "$korebuild_path" ]; then
echo "Cleaning up after failed installation"
rm -rf "$korebuild_path" || true
fi
return 1
}
}
__error() {
echo -e "${RED}error: $*${RESET}" 1>&2
}
__warn() {
echo -e "${YELLOW}warning: $*${RESET}"
}
__machine_has() {
hash "$1" > /dev/null 2>&1
return $?
}
__get_remote_file() {
local remote_path=$1
local local_path=$2
if [[ "$remote_path" != 'http'* ]]; then
cp "$remote_path" "$local_path"
return 0
fi
local failed=false
if __machine_has wget; then
wget --tries 10 --quiet -O "$local_path" "$remote_path" || failed=true
else
failed=true
fi
if [ "$failed" = true ] && __machine_has curl; then
failed=false
curl --retry 10 -sSL -f --create-dirs -o "$local_path" "$remote_path" || failed=true
fi
if [ "$failed" = true ]; then
__error "Download failed: $remote_path" 1>&2
return 1
fi
}
#
# main
#
while [[ $# -gt 0 ]]; do
case $1 in
-\?|-h|--help)
__usage --no-exit
exit 0
;;
-c|--channel|-Channel)
shift
channel="${1:-}"
[ -z "$channel" ] && __usage
;;
--config-file|-ConfigFile)
shift
config_file="${1:-}"
[ -z "$config_file" ] && __usage
if [ ! -f "$config_file" ]; then
__error "Invalid value for --config-file. $config_file does not exist."
exit 1
fi
;;
-d|--dotnet-home|-DotNetHome)
shift
DOTNET_HOME="${1:-}"
[ -z "$DOTNET_HOME" ] && __usage
;;
--path|-Path)
shift
repo_path="${1:-}"
[ -z "$repo_path" ] && __usage
;;
-s|--tools-source|-ToolsSource)
shift
tools_source="${1:-}"
[ -z "$tools_source" ] && __usage
;;
-u|--update|-Update)
update=true
;;
--verbose|-Verbose)
verbose=true
;;
--)
shift
break
;;
*)
break
;;
esac
shift
done
if ! __machine_has unzip; then
__error 'Missing required command: unzip'
exit 1
koreBuildZip="https://github.com/aspnet/KoreBuild/archive/rel/2.0.0.zip"
if [ ! -z $KOREBUILD_ZIP ]; then
koreBuildZip=$KOREBUILD_ZIP
fi
if ! __machine_has curl && ! __machine_has wget; then
__error 'Missing required command. Either wget or curl is required.'
buildFolder=".build"
buildFile="$buildFolder/KoreBuild.sh"
if test ! -d $buildFolder; then
echo "Downloading KoreBuild from $koreBuildZip"
tempFolder="/tmp/KoreBuild-$(uuidgen)"
mkdir $tempFolder
localZipFile="$tempFolder/korebuild.zip"
retries=6
until (wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip 2>/dev/null)
do
echo "Failed to download '$koreBuildZip'"
if [ "$retries" -le 0 ]; then
exit 1
fi
retries=$((retries - 1))
echo "Waiting 10 seconds before retrying. Retries left: $retries"
sleep 10s
done
unzip -q -d $tempFolder $localZipFile
mkdir $buildFolder
cp -r $tempFolder/**/build/** $buildFolder
chmod +x $buildFile
# Cleanup
if test -d $tempFolder; then
rm -rf $tempFolder
fi
fi
[ -z "${config_file:-}" ] && config_file="$repo_path/korebuild.json"
if [ -f "$config_file" ]; then
if __machine_has jq ; then
if jq '.' "$config_file" >/dev/null ; then
config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")"
config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")"
else
__warn "$config_file is invalid JSON. Its settings will be ignored."
fi
elif __machine_has python ; then
if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then
config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")"
config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")"
else
__warn "$config_file is invalid JSON. Its settings will be ignored."
fi
else
__warn 'Missing required command: jq or pyton. Could not parse the JSON file. Its settings will be ignored.'
fi
[ ! -z "${config_channel:-}" ] && channel="$config_channel"
[ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source"
fi
[ -z "$channel" ] && channel='dev'
[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools'
get_korebuild
install_tools "$tools_source" "$DOTNET_HOME"
invoke_repository_build "$repo_path" "$@"
$buildFile -r $repoFolder "$@"

View File

@@ -1,4 +1,5 @@
<Project>
<Import Project="dependencies.props" />
<Import Project="..\version.props" />
<PropertyGroup>
@@ -8,11 +9,15 @@
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)Key.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PublicSign Condition="'$(OS)' != 'Windows_NT'">true</PublicSign>
<VersionSuffix Condition="'$(VersionSuffix)'!='' AND '$(BuildNumber)' != ''">$(VersionSuffix)-$(BuildNumber)</VersionSuffix>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Internal.AspNetCore.Sdk" Version="$(InternalAspNetCoreSdkPackageVersion)" PrivateAssets="All" />
<PackageReference Include="Internal.AspNetCore.Sdk" Version="$(InternalAspNetCoreSdkVersion)" PrivateAssets="All" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)'=='.NETFramework'">
<PackageReference Include="NETStandard.Library" Version="$(NETStandardImplicitPackageVersion)" />
</ItemGroup>
</Project>

View File

@@ -1,21 +1,12 @@
<Project>
<Project>
<PropertyGroup>
<InternalAspNetCoreSdkPackageVersion>2.0.2-rc1-15526</InternalAspNetCoreSdkPackageVersion>
<MicrosoftAspNetCoreDiagnosticsPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreDiagnosticsPackageVersion>
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>
<MicrosoftAspNetCoreHostingPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreHostingPackageVersion>
<MicrosoftAspNetCoreMvcPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreMvcPackageVersion>
<MicrosoftAspNetCoreMvcTagHelpersPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreMvcTagHelpersPackageVersion>
<MicrosoftAspNetCoreMvcViewFeaturesPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreMvcViewFeaturesPackageVersion>
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreServerIISIntegrationPackageVersion>
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreServerKestrelPackageVersion>
<MicrosoftAspNetCoreStaticFilesPackageVersion>2.0.1-rtm-105</MicrosoftAspNetCoreStaticFilesPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>2.0.0</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>2.0.0</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingDebugPackageVersion>2.0.0</MicrosoftExtensionsLoggingDebugPackageVersion>
<NewtonsoftJsonRuntimePackageVersion>10.0.1</NewtonsoftJsonRuntimePackageVersion>
<SystemThreadingTasksDataflowPackageVersion>4.8.0</SystemThreadingTasksDataflowPackageVersion>
<AspNetCoreVersion>2.0.0-*</AspNetCoreVersion>
<AutoMapperVersion>5.0.2</AutoMapperVersion>
<InternalAspNetCoreSdkVersion>2.0.1-*</InternalAspNetCoreSdkVersion>
<JsonNetVersion>10.0.1</JsonNetVersion>
<NETStandardImplicitPackageVersion>2.0.0-*</NETStandardImplicitPackageVersion>
<NETStandardLibraryNETFrameworkVersion>2.0.0-*</NETStandardLibraryNETFrameworkVersion>
<RuntimeFrameworkVersion Condition="'$(TargetFramework)'=='netcoreapp2.0'">2.0.0-*</RuntimeFrameworkVersion>
<ThreadingDataflowVersion>4.8.0-*</ThreadingDataflowVersion>
</PropertyGroup>
<Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " />
</Project>

View File

@@ -1,17 +0,0 @@
<Project>
<Import Project="$(DotNetRestoreSourcePropsPath)" Condition="'$(DotNetRestoreSourcePropsPath)' != ''"/>
<PropertyGroup>
<RestoreSources>$(DotNetRestoreSources)</RestoreSources>
<RestoreSources Condition="'$(DotNetBuildOffline)' != 'true' AND '$(AspNetUniverseBuildOffline)' != 'true' ">
$(RestoreSources);
https://dotnet.myget.org/F/aspnet-2-0-2-october2017-patch/api/v3/index.json;
https://dotnet.myget.org/F/aspnetcore-master/api/v3/index.json;
https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;
</RestoreSources>
<RestoreSources Condition="'$(DotNetBuildOffline)' != 'true'">
$(RestoreSources);
https://api.nuget.org/v3/index.json;
</RestoreSources>
</PropertyGroup>
</Project>

View File

@@ -1,2 +0,0 @@
version:2.0.2-rc1-15526
commithash:436afc3dc08f5e278431db807866cc5f032f4d7b

View File

@@ -1,4 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/rel/2.0.2/tools/korebuild.schema.json",
"channel": "rel/2.0.2"
}

View File

@@ -14,7 +14,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(AspNetCoreVersion)" />
</ItemGroup>
</Project>

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\build\common.props" />
@@ -13,13 +13,13 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="$(MicrosoftAspNetCoreDiagnosticsPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(MicrosoftAspNetCoreHostingPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(MicrosoftAspNetCoreMvcPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(MicrosoftAspNetCoreStaticFilesPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(MicrosoftExtensionsLoggingDebugPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(AspNetCoreVersion)" />
</ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\build\common.props" />
@@ -13,13 +13,13 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="$(MicrosoftAspNetCoreDiagnosticsPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(MicrosoftAspNetCoreHostingPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(MicrosoftAspNetCoreMvcPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(MicrosoftAspNetCoreStaticFilesPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(MicrosoftExtensionsLoggingDebugPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="$(AspNetCoreVersion)" />
</ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">

View File

@@ -16,7 +16,7 @@
<ItemGroup>
<ProjectReference Include="..\Microsoft.AspNetCore.NodeServices\Microsoft.AspNetCore.NodeServices.csproj" />
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="$(SystemThreadingTasksDataflowPackageVersion)" />
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="$(ThreadingDataflowVersion)" />
</ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">

View File

@@ -16,9 +16,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="$(MicrosoftAspNetCoreHostingAbstractionsPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonRuntimePackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Newtonsoft.Json" Version="$(JsonNetVersion)" />
</ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">

View File

@@ -14,8 +14,8 @@
<None Remove="node_modules\**\*" />
<EmbeddedResource Include="Content\**\*" />
<ProjectReference Include="..\Microsoft.AspNetCore.NodeServices\Microsoft.AspNetCore.NodeServices.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.TagHelpers" Version="$(MicrosoftAspNetCoreMvcTagHelpersPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="$(MicrosoftAspNetCoreMvcViewFeaturesPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.TagHelpers" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="$(AspNetCoreVersion)" />
</ItemGroup>
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">

View File

@@ -1,6 +1,6 @@
{
"name": "aspnet-prerendering",
"version": "2.0.6",
"version": "3.0.1",
"description": "Helpers for server-side rendering of JavaScript applications in ASP.NET Core projects. Works in conjunction with the Microsoft.AspNetCore.SpaServices NuGet package.",
"main": "index.js",
"scripts": {
@@ -17,7 +17,7 @@
"url": "https://github.com/aspnet/JavaScriptServices.git"
},
"dependencies": {
"domain-task": "^2.0.2"
"domain-task": "^3.0.0"
},
"devDependencies": {
"@types/node": "^6.0.42",

View File

@@ -26,6 +26,7 @@ export function createServerRenderer(bootFunc: BootFunc): RenderToStringFunc {
domainTasks: domainTaskCompletionPromise,
data: customDataParameter
};
const absoluteBaseUrl = params.origin + params.baseUrl; // Should be same value as page's <base href>
// Open a new domain that can track all the async tasks involved in the app's execution
domainTaskRun(/* code to run */ () => {
@@ -35,7 +36,7 @@ export function createServerRenderer(bootFunc: BootFunc): RenderToStringFunc {
bindPromiseContinuationsToDomain(domainTaskCompletionPromise, domain['active']);
// Make the base URL available to the 'domain-tasks/fetch' helper within this execution context
domainTaskBaseUrl(absoluteRequestUrl);
domainTaskBaseUrl(absoluteBaseUrl);
// Begin rendering, and apply a timeout
const bootFuncPromise = bootFunc(params);

View File

@@ -1,6 +1,6 @@
{
"name": "aspnet-webpack-react",
"version": "3.0.0-beta.1",
"version": "3.0.0",
"description": "Helpers for using Webpack with React in ASP.NET Core projects. Works in conjunction with the Microsoft.AspNetCore.SpaServices NuGet package.",
"main": "index.js",
"scripts": {

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "aspnet-webpack",
"version": "1.0.29",
"version": "2.0.1",
"description": "Helpers for using Webpack in ASP.NET Core projects. Works in conjunction with the Microsoft.AspNetCore.SpaServices NuGet package.",
"main": "index.js",
"scripts": {

View File

@@ -5,11 +5,11 @@ import * as fs from 'fs';
import * as path from 'path';
import * as querystring from 'querystring';
import { requireNewCopy } from './RequireNewCopy';
import { hasSufficientPermissions } from './WebpackTestPermissions';
export type CreateDevServerResult = {
Port: number,
PublicPaths: string[],
PublicPath: string // For backward compatibility with older verions of Microsoft.AspNetCore.SpaServices. Will be removed soon.
PublicPaths: string[]
};
export interface CreateDevServerCallback {
@@ -108,7 +108,7 @@ function attachWebpackDevMiddleware(app: any, webpackConfig: webpack.Configurati
const compiler = webpack(webpackConfig);
app.use(require('webpack-dev-middleware')(compiler, {
noInfo: true,
publicPath: webpackConfig.output.publicPath,
publicPath: ensureLeadingSlash(webpackConfig.output.publicPath),
watchOptions: webpackConfig.watchOptions
}));
@@ -195,6 +195,14 @@ function copyRecursiveToRealFsSync(from: typeof fs, rootDir: string, exclude: Re
});
}
function ensureLeadingSlash(value: string) {
if (value !== null && value.substring(0, 1) !== '/') {
value = '/' + value;
}
return value;
}
function pathJoinSafe(rootPath: string, filePath: string) {
// On Windows, MemoryFileSystem's readdirSync output produces directory entries like 'C:'
// which then trigger errors if you call statSync for them. Avoid this by detecting drive
@@ -216,6 +224,16 @@ function beginWebpackWatcher(webpackConfig: webpack.Configuration) {
export function createWebpackDevServer(callback: CreateDevServerCallback, optionsJson: string) {
const options: CreateDevServerOptions = JSON.parse(optionsJson);
// See the large comment in WebpackTestPermissions.ts for details about this
if (!hasSufficientPermissions()) {
console.log('WARNING: Webpack dev middleware is not enabled because the server process does not have sufficient permissions. You should either remove the UseWebpackDevMiddleware call from your code, or to make it work, give your server process user account permission to write to your application directory and to read all ancestor-level directories.');
callback(null, {
Port: 0,
PublicPaths: []
});
return;
}
// Read the webpack config's export, and normalize it into the more general 'array of configs' format
let webpackConfigExport: WebpackConfigFileExport = requireNewCopy(options.webpackConfigPath);
if (webpackConfigExport instanceof Function) {
@@ -257,22 +275,32 @@ export function createWebpackDevServer(callback: CreateDevServerCallback, option
if (!publicPath) {
throw new Error('To use the Webpack dev server, you must specify a value for \'publicPath\' on the \'output\' section of your webpack config (for any configuration that targets browsers)');
}
normalizedPublicPaths.push(removeTrailingSlash(publicPath));
const publicPathNoTrailingSlash = removeTrailingSlash(publicPath);
normalizedPublicPaths.push(publicPathNoTrailingSlash);
// Newer versions of Microsoft.AspNetCore.SpaServices will explicitly pass an HMR endpoint URL
// (because it's relative to the app's URL space root, which the client doesn't otherwise know).
// For back-compatibility, fall back on connecting directly to the underlying HMR server (though
// that won't work if the app is hosted on HTTPS because of the mixed-content rule, and we can't
// run the HMR server itself on HTTPS because in general it has no valid cert).
const hmrClientEndpoint = options.hotModuleReplacementEndpointUrl // The URL that we'll proxy (e.g., /__asp_webpack_hmr)
|| `http://localhost:${listener.address().port}/__webpack_hmr`; // Fall back on absolute URL to bypass proxying
const hmrServerEndpoint = options.hotModuleReplacementEndpointUrl
|| '/__webpack_hmr'; // URL is relative to webpack dev server root
// This is the URL the client will connect to, except that since it's a relative URL
// (no leading slash), Webpack will resolve it against the runtime <base href> URL
// plus it also adds the publicPath
const hmrClientEndpoint = removeLeadingSlash(options.hotModuleReplacementEndpointUrl);
// This is the URL inside the Webpack middleware Node server that we'll proxy to.
// We have to prefix with the public path because Webpack will add the publicPath
// when it resolves hmrClientEndpoint as a relative URL.
const hmrServerEndpoint = ensureLeadingSlash(publicPathNoTrailingSlash + options.hotModuleReplacementEndpointUrl);
// We always overwrite the 'path' option as it needs to match what the .NET side is expecting
const hmrClientOptions = options.suppliedOptions.HotModuleReplacementClientOptions || <StringMap<string>>{};
hmrClientOptions['path'] = hmrClientEndpoint;
const dynamicPublicPathKey = 'dynamicPublicPath';
if (!(dynamicPublicPathKey in hmrClientOptions)) {
// dynamicPublicPath default to true, so we can work with nonempty pathbases (virtual directories)
hmrClientOptions[dynamicPublicPathKey] = true;
} else {
// ... but you can set it to any other value explicitly if you want (e.g., false)
hmrClientOptions[dynamicPublicPathKey] = JSON.parse(hmrClientOptions[dynamicPublicPathKey]);
}
attachWebpackDevMiddleware(app, webpackConfig, enableHotModuleReplacement, enableReactHotModuleReplacement, hmrClientOptions, hmrServerEndpoint);
}
});
@@ -280,11 +308,7 @@ export function createWebpackDevServer(callback: CreateDevServerCallback, option
// Tell the ASP.NET app what addresses we're listening on, so that it can proxy requests here
callback(null, {
Port: listener.address().port,
PublicPaths: normalizedPublicPaths,
// For back-compatibility with older versions of Microsoft.AspNetCore.SpaServices, in the case where
// you have exactly one webpackConfigArray entry. This will be removed soon.
PublicPath: normalizedPublicPaths[0]
PublicPaths: normalizedPublicPaths
});
} catch (ex) {
callback(ex.stack, null);
@@ -292,6 +316,14 @@ export function createWebpackDevServer(callback: CreateDevServerCallback, option
});
}
function removeLeadingSlash(str: string) {
if (str.indexOf('/') === 0) {
str = str.substring(1);
}
return str;
}
function removeTrailingSlash(str: string) {
if (str.lastIndexOf('/') === str.length - 1) {
str = str.substring(0, str.length - 1);

View File

@@ -0,0 +1,58 @@
import * as fs from 'fs';
import * as path from 'path';
const isWindows = /^win/.test(process.platform);
// On Windows, Node (still as of v8.1.3) has an issue whereby, when locating JavaScript modules
// on disk, it walks up the directory hierarchy to the disk root, testing whether each directory
// is a symlink or not. This fails with an exception if the process doesn't have permission to
// read those directories. This is a problem when hosting in full IIS, because in typical cases
// the process does not have read permission for higher-level directories.
//
// NodeServices itself works around this by injecting a patched version of Node's 'lstat' API that
// suppresses these irrelevant errors during module loads. This covers most scenarios, but isn't
// enough to make Webpack dev middleware work, because typical Webpack configs use loaders such as
// 'awesome-typescript-loader', which works by forking a child process to do some of its work. The
// child process does not get the patched 'lstat', and hence fails. It's an especially bad failure,
// because the Webpack compiler doesn't even surface the exception - it just never completes the
// compilation process, causing the application to hang indefinitely.
//
// Additionally, Webpack dev middleware will want to write its output to disk, which is also going
// to fail in a typical IIS process, because you won't have 'write' permission to the app dir by
// default. We have to actually write the build output to disk (and not purely keep it in the in-
// memory file system) because the server-side prerendering Node instance is a separate process
// that only knows about code changes when it sees the compiled files on disk change.
//
// In the future, we'll hopefully get Node to fix its underlying issue, and figure out whether VS
// could give 'write' access to the app dir when launching sites in IIS. But until then, disable
// Webpack dev middleware if we detect the server process doesn't have the necessary permissions.
export function hasSufficientPermissions() {
if (isWindows) {
return canReadDirectoryAndAllAncestors(process.cwd());
} else {
return true;
}
}
function canReadDirectoryAndAllAncestors(dir: string): boolean {
if (!canReadDirectory(dir)) {
return false;
}
const parentDir = path.resolve(dir, '..');
if (parentDir === dir) {
// There are no more parent directories - we've reached the disk root
return true;
} else {
return canReadDirectoryAndAllAncestors(parentDir);
}
}
function canReadDirectory(dir: string): boolean {
try {
fs.statSync(dir);
return true;
} catch(ex) {
return false;
}
}

View File

@@ -9,17 +9,17 @@
</PropertyGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' == ''">
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' != ''">
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0-rtm-26190" />
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -10,12 +10,12 @@ import { AppComponent } from './components/app/app.component';
AppModuleShared
],
providers: [
{ provide: 'ORIGIN_URL', useFactory: getOriginUrl }
{ provide: 'BASE_URL', useFactory: getBaseUrl }
]
})
export class AppModule {
}
export function getOriginUrl() {
return location.origin;
export function getBaseUrl() {
return document.getElementsByTagName('base')[0].href;
}

View File

@@ -8,8 +8,8 @@ import { Http } from '@angular/http';
export class FetchDataComponent {
public forecasts: WeatherForecast[];
constructor(http: Http, @Inject('ORIGIN_URL') originUrl: string) {
http.get(originUrl + '/api/SampleData/WeatherForecasts').subscribe(result => {
constructor(http: Http, @Inject('BASE_URL') baseUrl: string) {
http.get(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => {
this.forecasts = result.json() as WeatherForecast[];
}, error => console.error(error));
}

View File

@@ -5,13 +5,13 @@ import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module.browser';
if (module['hot']) {
module['hot'].accept();
module['hot'].dispose(() => {
if (module.hot) {
module.hot.accept();
module.hot.dispose(() => {
// Before restarting the app, we create a new root element and dispose the old one
const oldRootElem = document.querySelector('app');
const newRootElem = document.createElement('app');
oldRootElem.parentNode.insertBefore(newRootElem, oldRootElem);
oldRootElem!.parentNode!.insertBefore(newRootElem, oldRootElem);
modulePromise.then(appModule => appModule.destroy());
});
} else {

View File

@@ -1,6 +1,7 @@
import 'reflect-metadata';
import 'zone.js';
import 'rxjs/add/operator/first';
import { APP_BASE_HREF } from '@angular/common';
import { enableProdMode, ApplicationRef, NgZone, ValueProvider } from '@angular/core';
import { platformDynamicServer, PlatformState, INITIAL_CONFIG } from '@angular/platform-server';
import { createServerRenderer, RenderResult } from 'aspnet-prerendering';
@@ -11,16 +12,17 @@ enableProdMode();
export default createServerRenderer(params => {
const providers = [
{ provide: INITIAL_CONFIG, useValue: { document: '<app></app>', url: params.url } },
{ provide: 'ORIGIN_URL', useValue: params.origin }
{ provide: APP_BASE_HREF, useValue: params.baseUrl },
{ provide: 'BASE_URL', useValue: params.origin + params.baseUrl },
];
return platformDynamicServer(providers).bootstrapModule(AppModule).then(moduleRef => {
const appRef = moduleRef.injector.get(ApplicationRef);
const appRef: ApplicationRef = moduleRef.injector.get(ApplicationRef);
const state = moduleRef.injector.get(PlatformState);
const zone = moduleRef.injector.get(NgZone);
return new Promise<RenderResult>((resolve, reject) => {
zone.onError.subscribe(errorInfo => reject(errorInfo));
zone.onError.subscribe((errorInfo: any) => reject(errorInfo));
appRef.isStable.first(isStable => isStable).subscribe(() => {
// Because 'onStable' fires before 'onError', we have to delay slightly before
// completing the request in case there's an error to report

View File

@@ -93,10 +93,10 @@
"resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.5.53.tgz",
"dev": true
},
"@types/node": {
"version": "8.0.8",
"from": "@types/node@8.0.8",
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.8.tgz"
"@types/webpack-env": {
"version": "1.13.0",
"from": "@types/webpack-env@1.13.0",
"resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.13.0.tgz"
},
"accepts": {
"version": "1.3.3",
@@ -274,14 +274,14 @@
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz"
},
"aspnet-prerendering": {
"version": "2.0.6",
"from": "aspnet-prerendering@>=2.0.5 <3.0.0",
"resolved": "https://registry.npmjs.org/aspnet-prerendering/-/aspnet-prerendering-2.0.6.tgz"
"version": "3.0.1",
"from": "aspnet-prerendering@3.0.1",
"resolved": "https://registry.npmjs.org/aspnet-prerendering/-/aspnet-prerendering-3.0.1.tgz"
},
"aspnet-webpack": {
"version": "1.0.29",
"from": "aspnet-webpack@>=1.0.29 <2.0.0",
"resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-1.0.29.tgz"
"version": "2.0.1",
"from": "aspnet-webpack@2.0.1",
"resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-2.0.1.tgz"
},
"assert": {
"version": "1.4.1",
@@ -932,9 +932,9 @@
"resolved": "https://registry.npmjs.org/domain-context/-/domain-context-0.5.1.tgz"
},
"domain-task": {
"version": "2.0.3",
"from": "domain-task@>=2.0.2 <3.0.0",
"resolved": "https://registry.npmjs.org/domain-task/-/domain-task-2.0.3.tgz"
"version": "3.0.3",
"from": "domain-task@>=3.0.0 <4.0.0",
"resolved": "https://registry.npmjs.org/domain-task/-/domain-task-3.0.3.tgz"
},
"ee-first": {
"version": "1.1.1",

View File

@@ -18,10 +18,10 @@
"@angular/platform-server": "4.2.5",
"@angular/router": "4.2.5",
"@ngtools/webpack": "1.5.0",
"@types/node": "8.0.8",
"@types/webpack-env": "1.13.0",
"angular2-template-loader": "0.6.2",
"aspnet-prerendering": "^2.0.5",
"aspnet-webpack": "^1.0.29",
"aspnet-prerendering": "^3.0.1",
"aspnet-webpack": "^2.0.1",
"awesome-typescript-loader": "3.2.1",
"bootstrap": "3.3.7",
"css": "2.2.1",

View File

@@ -1,13 +1,16 @@
{
"compilerOptions": {
"module": "es2015",
"moduleResolution": "node",
"target": "es5",
"sourceMap": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"skipDefaultLibCheck": true,
"skipLibCheck": true, // Workaround for https://github.com/angular/angular/issues/17863. Remove this if you upgrade to a fixed version of Angular.
"strict": true,
"lib": [ "es6", "dom" ],
"types": [ "node" ]
"types": [ "webpack-env" ]
},
"exclude": [ "bin", "node_modules" ],
"atom": { "rewriteTsconfig": false }

View File

@@ -13,7 +13,7 @@ module.exports = (env) => {
resolve: { extensions: [ '.js', '.ts' ] },
output: {
filename: '[name].js',
publicPath: '/dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
publicPath: 'dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
},
module: {
rules: [

View File

@@ -36,7 +36,7 @@ module.exports = (env) => {
]
},
output: {
publicPath: '/dist/',
publicPath: 'dist/',
filename: '[name].js',
library: '[name]_[hash]'
},

View File

@@ -9,17 +9,17 @@
</PropertyGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' == ''">
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' != ''">
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0-*" />
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
</ItemGroup>
<!--/-:cnd:noEmit -->

View File

@@ -6,7 +6,7 @@ export class Fetchdata {
public forecasts: WeatherForecast[];
constructor(http: HttpClient) {
http.fetch('/api/SampleData/WeatherForecasts')
http.fetch('api/SampleData/WeatherForecasts')
.then(result => result.json() as Promise<WeatherForecast[]>)
.then(data => {
this.forecasts = data;

View File

@@ -1,5 +1,6 @@
import 'isomorphic-fetch';
import { Aurelia, PLATFORM } from 'aurelia-framework';
import { HttpClient } from 'aurelia-fetch-client';
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap';
declare const IS_DEV_BUILD: boolean; // The value is supplied by Webpack during the build
@@ -11,5 +12,10 @@ export function configure(aurelia: Aurelia) {
aurelia.use.developmentLogging();
}
new HttpClient().configure(config => {
const baseUrl = document.getElementsByTagName('base')[0].href;
config.withBaseUrl(baseUrl);
});
aurelia.start().then(() => aurelia.setRoot(PLATFORM.moduleName('app/components/app/app')));
}

View File

@@ -2,10 +2,10 @@
"name": "WebApplicationBasic",
"version": "0.0.0",
"dependencies": {
"@types/node": {
"version": "7.0.32",
"from": "@types/node@>=7.0.12 <8.0.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.32.tgz",
"@types/webpack-env": {
"version": "1.13.0",
"from": "@types/webpack-env@>=1.13.0 <2.0.0",
"resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.13.0.tgz",
"dev": true
},
"acorn": {
@@ -113,9 +113,9 @@
"dev": true
},
"aspnet-webpack": {
"version": "1.0.29",
"from": "aspnet-webpack@>=1.0.28 <2.0.0",
"resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-1.0.29.tgz",
"version": "2.0.1",
"from": "aspnet-webpack@2.0.1",
"resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-2.0.1.tgz",
"dev": true
},
"assert": {

View File

@@ -14,8 +14,8 @@
"jquery": "^3.2.1"
},
"devDependencies": {
"@types/node": "^7.0.12",
"aspnet-webpack": "^1.0.28",
"@types/webpack-env": "^1.13.0",
"aspnet-webpack": "^2.0.1",
"aurelia-webpack-plugin": "^2.0.0-rc.2",
"css-loader": "^0.28.0",
"extract-text-webpack-plugin": "^2.1.0",

View File

@@ -1,13 +1,15 @@
{
"compilerOptions": {
"module": "es2015",
"moduleResolution": "node",
"target": "es5",
"sourceMap": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"skipDefaultLibCheck": true,
"strict": true,
"lib": [ "es2015", "dom" ],
"types": [ "node" ]
"types": [ "webpack-env" ]
},
"exclude": [ "bin", "node_modules" ],
"atom": { "rewriteTsconfig": false }

View File

@@ -14,7 +14,7 @@ module.exports = (env) => {
},
output: {
path: path.resolve(bundleOutputDir),
publicPath: '/dist/',
publicPath: 'dist/',
filename: '[name].js'
},
module: {

View File

@@ -38,7 +38,7 @@ module.exports = ({ prod } = {}) => {
},
output: {
path: path.join(__dirname, 'wwwroot', 'dist'),
publicPath: '/dist/',
publicPath: 'dist/',
filename: '[name].js',
library: '[name]_[hash]',
},

View File

@@ -1,19 +1,20 @@
import './css/site.css';
import 'bootstrap';
import * as ko from 'knockout';
import { createBrowserHistory } from 'history';
import './webpack-component-loader';
import AppRootComponent from './components/app-root/app-root';
const createHistory = require('history').createBrowserHistory;
const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href')!;
const basename = baseUrl.substring(0, baseUrl.length - 1); // History component needs no trailing slash
// Load and register the <app-root> component
ko.components.register('app-root', AppRootComponent);
// Tell Knockout to start up an instance of your application
ko.applyBindings({ history: createHistory() });
ko.applyBindings({ history: createBrowserHistory({ basename }), basename });
// Basic hot reloading support. Automatically reloads and restarts the Knockout app each time
// you modify source files. This will not preserve any application state other than the URL.
declare var module: any;
if (module.hot) {
module.hot.accept();
module.hot.dispose(() => ko.cleanNode(document.body));

View File

@@ -1,7 +1,7 @@
<div class='container-fluid'>
<div class='row'>
<div class='col-sm-3'>
<nav-menu params='route: route'></nav-menu>
<nav-menu params='router: router'></nav-menu>
</div>
<div class='col-sm-9' data-bind='component: { name: route().page, params: route }'></div>
</div>

View File

@@ -12,12 +12,12 @@ const routes: Route[] = [
class AppRootViewModel {
public route: KnockoutObservable<Route>;
private _router: Router;
public router: Router;
constructor(params: { history: History.History }) {
constructor(params: { history: History.History, basename: string }) {
// Activate the client-side router
this._router = new Router(params.history, routes)
this.route = this._router.currentRoute;
this.router = new Router(params.history, routes, params.basename);
this.route = this.router.currentRoute;
// Load and register all the KO components needed to handle the routes
// The optional 'bundle-loader?lazy!' prefix is a Webpack feature that causes the referenced modules
@@ -32,7 +32,7 @@ class AppRootViewModel {
// To support hot module replacement, this method unregisters the router and KO components.
// In production scenarios where hot module replacement is disabled, this would not be invoked.
public dispose() {
this._router.dispose();
this.router.dispose();
// TODO: Need a better API for this
Object.getOwnPropertyNames((<any>ko).components._allRegisteredComponents).forEach(componentName => {

View File

@@ -12,7 +12,7 @@ class FetchDataViewModel {
public forecasts = ko.observableArray<WeatherForecast>();
constructor() {
fetch('/api/SampleData/WeatherForecasts')
fetch('api/SampleData/WeatherForecasts')
.then(response => response.json() as Promise<WeatherForecast[]>)
.then(data => {
this.forecasts(data);

View File

@@ -13,17 +13,17 @@
<div class='navbar-collapse collapse'>
<ul class='nav navbar-nav'>
<li>
<a href='/' data-bind='css: { active: route().page === "home-page" }'>
<a data-bind='attr: { href: router.link("/") }, css: { active: route().page === "home-page" }'>
<span class='glyphicon glyphicon-home'></span> Home
</a>
</li>
<li>
<a href='/counter' data-bind='css: { active: route().page === "counter-example" }'>
<a data-bind='attr: { href: router.link("/counter") }, css: { active: route().page === "counter-example" }'>
<span class='glyphicon glyphicon-education'></span> Counter
</a>
</li>
<li>
<a href='/fetch-data' data-bind='css: { active: route().page === "fetch-data" }'>
<a data-bind='attr: { href: router.link("/fetch-data") }, css: { active: route().page === "fetch-data" }'>
<span class='glyphicon glyphicon-th-list'></span> Fetch data
</a>
</li>

View File

@@ -1,18 +1,20 @@
import * as ko from 'knockout';
import { Route } from '../../router';
import { Route, Router } from '../../router';
interface NavMenuParams {
route: KnockoutObservable<Route>;
router: Router;
}
class NavMenuViewModel {
public router: Router;
public route: KnockoutObservable<Route>;
constructor(params: NavMenuParams) {
// This viewmodel doesn't do anything except pass through the 'route' parameter to the view.
// You could remove this viewmodel entirely, and define 'nav-menu' as a template-only component.
// But in most apps, you'll want some viewmodel logic to determine what navigation options appear.
this.route = params.route;
this.router = params.router;
this.route = this.router.currentRoute;
}
}

View File

@@ -1,7 +1,7 @@
import * as ko from 'knockout';
import * as $ from 'jquery';
import * as History from 'history';
import crossroads = require('crossroads');
import * as crossroads from 'crossroads';
// This module configures crossroads.js, a routing library. If you prefer, you
// can use any other routing library (or none at all) as Knockout is designed to
@@ -16,13 +16,13 @@ export class Router {
private disposeHistory: () => void;
private clickEventListener: EventListener;
constructor(history: History.History, routes: Route[]) {
constructor(private history: History.History, routes: Route[], basename: string) {
// Reset and configure Crossroads so it matches routes and updates this.currentRoute
crossroads.removeAllRoutes();
crossroads.resetState();
crossroads.normalizeFn = crossroads.NORM_AS_OBJECT;
(crossroads as any).normalizeFn = crossroads.NORM_AS_OBJECT;
routes.forEach(route => {
crossroads.addRoute(route.url, (requestParams) => {
crossroads.addRoute(route.url, (requestParams: any) => {
this.currentRoute(ko.utils.extend(requestParams, route.params));
});
});
@@ -33,8 +33,9 @@ export class Router {
let target: any = evt.currentTarget;
if (target && target.tagName === 'A') {
let href = target.getAttribute('href');
if (href && href.charAt(0) == '/') {
history.push(href);
if (href && href.indexOf(basename + '/') === 0) {
const hrefAfterBasename = href.substring(basename.length);
history.push(hrefAfterBasename);
evt.preventDefault();
}
}
@@ -46,6 +47,10 @@ export class Router {
crossroads.parse((history as any).location.pathname);
}
public link(url: string): string {
return this.history.createHref({ pathname: url });
}
public dispose() {
this.disposeHistory();
$(document).off('click', 'a', this.clickEventListener);

View File

@@ -8,18 +8,18 @@ ko.components.loaders.unshift({
loadComponent: (name, componentConfig, callback) => {
if (typeof componentConfig === 'function') {
// It's a lazy-loaded Webpack bundle
(componentConfig as any)(loadedModule => {
(componentConfig as any)((loadedModule: any) => {
// Handle TypeScript-style default exports
if (loadedModule.__esModule && loadedModule.default) {
loadedModule = loadedModule.default;
}
// Pass the loaded module to KO's default loader
ko.components.defaultLoader.loadComponent(name, loadedModule, callback);
ko.components.defaultLoader.loadComponent!(name, loadedModule as KnockoutComponentTypes.ComponentConfig, callback);
});
} else {
// It's something else - let another component loader handle it
callback(null);
callback((null as any) as KnockoutComponentTypes.Definition); // workaround until https://github.com/DefinitelyTyped/DefinitelyTyped/pull/17999
}
}
});

View File

@@ -9,17 +9,17 @@
</PropertyGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' == ''">
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' != ''">
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0-*" />
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
</ItemGroup>
<!--/-:cnd:noEmit -->

View File

@@ -2,7 +2,7 @@
ViewData["Title"] = "Home Page";
}
<app-root params="history: history"></app-root>
<app-root params="history: history, basename: basename"></app-root>
@section scripts {
<script src="~/dist/main.js" asp-append-version="true"></script>

View File

@@ -21,9 +21,9 @@
"dev": true
},
"@types/history": {
"version": "2.0.48",
"from": "@types/history@>=2.0.38 <3.0.0",
"resolved": "https://registry.npmjs.org/@types/history/-/history-2.0.48.tgz",
"version": "4.6.0",
"from": "@types/history@4.6.0",
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.6.0.tgz",
"dev": true
},
"@types/jquery": {
@@ -38,30 +38,18 @@
"resolved": "https://registry.npmjs.org/@types/knockout/-/knockout-3.4.41.tgz",
"dev": true
},
"@types/react": {
"version": "15.0.31",
"from": "@types/react@*",
"resolved": "https://registry.npmjs.org/@types/react/-/react-15.0.31.tgz",
"dev": true
},
"@types/react-router": {
"version": "2.0.50",
"from": "@types/react-router@>=2.0.37 <3.0.0",
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-2.0.50.tgz",
"dev": true
},
"@types/requirejs": {
"version": "2.1.29",
"from": "@types/requirejs@>=2.1.26 <3.0.0",
"resolved": "https://registry.npmjs.org/@types/requirejs/-/requirejs-2.1.29.tgz",
"dev": true
},
"@types/signals": {
"version": "0.0.16",
"from": "@types/signals@0.0.16",
"resolved": "https://registry.npmjs.org/@types/signals/-/signals-0.0.16.tgz",
"dev": true
},
"@types/webpack-env": {
"version": "1.13.0",
"from": "@types/webpack-env@>=1.13.0 <2.0.0",
"resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.13.0.tgz",
"dev": true
},
"acorn": {
"version": "5.0.3",
"from": "acorn@>=5.0.0 <6.0.0",
@@ -167,9 +155,9 @@
"dev": true
},
"aspnet-webpack": {
"version": "1.0.29",
"from": "aspnet-webpack@>=1.0.27 <2.0.0",
"resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-1.0.29.tgz",
"version": "2.0.1",
"from": "aspnet-webpack@2.0.1",
"resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-2.0.1.tgz",
"dev": true
},
"assert": {

View File

@@ -6,13 +6,12 @@
"@types/core-js": "^0.9.34",
"@types/crossroads": "0.0.29",
"@types/es6-promise": "0.0.32",
"@types/history": "^2.0.38",
"@types/history": "^4.6.0",
"@types/jquery": "^2.0.32",
"@types/knockout": "^3.4.35",
"@types/react-router": "^2.0.37",
"@types/requirejs": "^2.1.26",
"@types/knockout": "^3.4.41",
"@types/signals": "0.0.16",
"aspnet-webpack": "^1.0.27",
"@types/webpack-env": "^1.13.0",
"aspnet-webpack": "^2.0.1",
"awesome-typescript-loader": "^3.0.0",
"bootstrap": "^3.3.6",
"bundle-loader": "^0.5.4",
@@ -21,7 +20,7 @@
"event-source-polyfill": "^0.0.7",
"extract-text-webpack-plugin": "^2.0.0-rc",
"file-loader": "^0.9.0",
"history": "^4.3.0",
"history": "^4.6.3",
"isomorphic-fetch": "^2.2.1",
"jquery": "^2.2.1",
"json-loader": "^0.5.4",

View File

@@ -1,10 +1,12 @@
{
"compilerOptions": {
"module": "es2015",
"moduleResolution": "node",
"target": "es5",
"sourceMap": true,
"skipDefaultLibCheck": true,
"types": ["es6-promise", "history", "requirejs"]
"strict": true,
"types": ["es6-promise", "webpack-env"]
},
"exclude": [
"bin",

View File

@@ -13,7 +13,7 @@ module.exports = (env) => {
output: {
path: path.join(__dirname, bundleOutputDir),
filename: '[name].js',
publicPath: '/dist/'
publicPath: 'dist/'
},
module: {
rules: [

View File

@@ -21,7 +21,7 @@ module.exports = (env) => {
},
output: {
path: path.join(__dirname, 'wwwroot', 'dist'),
publicPath: '/dist/',
publicPath: 'dist/',
filename: '[name].js',
library: '[name]_[hash]',
},

View File

@@ -12,7 +12,8 @@ import * as RoutesModule from './routes';
let routes = RoutesModule.routes;
// Create browser history to use in the Redux store
const history = createBrowserHistory();
const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href')!;
const history = createBrowserHistory({ basename: baseUrl });
// Get the application-wide store instance, prepopulating with state from the server where available.
const initialState = (window as any).initialReduxState as ApplicationState;

View File

@@ -12,15 +12,17 @@ export default createServerRenderer(params => {
return new Promise<RenderResult>((resolve, reject) => {
// Prepare Redux store with in-memory history, and dispatch a navigation event
// corresponding to the incoming URL
const basename = params.baseUrl.substring(0, params.baseUrl.length - 1); // Remove trailing slash
const urlAfterBasename = params.url.substring(basename.length);
const store = configureStore(createMemoryHistory());
store.dispatch(replace(params.location));
store.dispatch(replace(urlAfterBasename));
// Prepare an instance of the application and perform an inital render that will
// cause any async tasks (e.g., data access) to begin
const routerContext: any = {};
const app = (
<Provider store={ store }>
<StaticRouter context={ routerContext } location={ params.location.path } children={ routes } />
<StaticRouter basename={ basename } context={ routerContext } location={ params.location.path } children={ routes } />
</Provider>
);
renderToString(app);

View File

@@ -56,8 +56,8 @@ class FetchData extends React.Component<WeatherForecastProps, {}> {
}
private renderPagination() {
let prevStartDateIndex = this.props.startDateIndex - 5;
let nextStartDateIndex = this.props.startDateIndex + 5;
let prevStartDateIndex = (this.props.startDateIndex || 0) - 5;
let nextStartDateIndex = (this.props.startDateIndex || 0) + 5;
return <p className='clearfix text-center'>
<Link className='btn btn-default pull-left' to={ `/fetchdata/${ prevStartDateIndex }` }>Previous</Link>

View File

@@ -1,4 +1,4 @@
import { createStore, applyMiddleware, compose, combineReducers, GenericStoreEnhancer, Store } from 'redux';
import { createStore, applyMiddleware, compose, combineReducers, GenericStoreEnhancer, Store, StoreEnhancerStoreCreator, ReducersMapObject } from 'redux';
import thunk from 'redux-thunk';
import { routerReducer, routerMiddleware } from 'react-router-redux';
import * as StoreModule from './store';
@@ -12,7 +12,7 @@ export default function configureStore(history: History, initialState?: Applicat
const devToolsExtension = windowIfDefined && windowIfDefined.devToolsExtension as () => GenericStoreEnhancer;
const createStoreWithMiddleware = compose(
applyMiddleware(thunk, routerMiddleware(history)),
devToolsExtension ? devToolsExtension() : f => f
devToolsExtension ? devToolsExtension() : <S>(next: StoreEnhancerStoreCreator<S>) => next
)(createStore);
// Combine all reducers and instantiate the app-wide store instance
@@ -30,6 +30,6 @@ export default function configureStore(history: History, initialState?: Applicat
return store;
}
function buildRootReducer(allReducers) {
function buildRootReducer(allReducers: ReducersMapObject) {
return combineReducers<ApplicationState>(Object.assign({}, allReducers, { routing: routerReducer }));
}

View File

@@ -7,7 +7,7 @@ import { AppThunkAction } from './';
export interface WeatherForecastsState {
isLoading: boolean;
startDateIndex: number;
startDateIndex?: number;
forecasts: WeatherForecast[];
}
@@ -23,14 +23,14 @@ export interface WeatherForecast {
// They do not themselves have any side-effects; they just describe something that is going to happen.
interface RequestWeatherForecastsAction {
type: 'REQUEST_WEATHER_FORECASTS',
type: 'REQUEST_WEATHER_FORECASTS';
startDateIndex: number;
}
interface ReceiveWeatherForecastsAction {
type: 'RECEIVE_WEATHER_FORECASTS',
type: 'RECEIVE_WEATHER_FORECASTS';
startDateIndex: number;
forecasts: WeatherForecast[]
forecasts: WeatherForecast[];
}
// Declare a 'discriminated union' type. This guarantees that all references to 'type' properties contain one of the
@@ -45,7 +45,7 @@ export const actionCreators = {
requestWeatherForecasts: (startDateIndex: number): AppThunkAction<KnownAction> => (dispatch, getState) => {
// Only load data if it's something we don't already have (and are not already loading)
if (startDateIndex !== getState().weatherForecasts.startDateIndex) {
let fetchTask = fetch(`/api/SampleData/WeatherForecasts?startDateIndex=${ startDateIndex }`)
let fetchTask = fetch(`api/SampleData/WeatherForecasts?startDateIndex=${ startDateIndex }`)
.then(response => response.json() as Promise<WeatherForecast[]>)
.then(data => {
dispatch({ type: 'RECEIVE_WEATHER_FORECASTS', startDateIndex: startDateIndex, forecasts: data });
@@ -60,7 +60,7 @@ export const actionCreators = {
// ----------------
// REDUCER - For a given state and action, returns the new state. To support time travel, this must not mutate the old state.
const unloadedState: WeatherForecastsState = { startDateIndex: null, forecasts: [], isLoading: false };
const unloadedState: WeatherForecastsState = { forecasts: [], isLoading: false };
export const reducer: Reducer<WeatherForecastsState> = (state: WeatherForecastsState, incomingAction: Action) => {
const action = incomingAction as KnownAction;

View File

@@ -3,8 +3,8 @@ import * as Counter from './Counter';
// The top-level state object
export interface ApplicationState {
counter: Counter.CounterState,
weatherForecasts: WeatherForecasts.WeatherForecastsState
counter: Counter.CounterState;
weatherForecasts: WeatherForecasts.WeatherForecastsState;
}
// Whenever an action is dispatched, Redux will update each top-level application state property using

View File

@@ -9,17 +9,17 @@
</PropertyGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' == ''">
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' != ''">
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0-*" />
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -22,6 +22,11 @@
"from": "@types/react-dom@15.5.1",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-15.5.1.tgz"
},
"@types/react-hot-loader": {
"version": "3.0.3",
"from": "@types/react-hot-loader@3.0.3",
"resolved": "https://registry.npmjs.org/@types/react-hot-loader/-/react-hot-loader-3.0.3.tgz"
},
"@types/react-redux": {
"version": "4.4.45",
"from": "@types/react-redux@4.4.45",
@@ -170,26 +175,19 @@
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz"
},
"aspnet-prerendering": {
"version": "2.0.6",
"from": "aspnet-prerendering@>=2.0.5 <3.0.0",
"resolved": "https://registry.npmjs.org/aspnet-prerendering/-/aspnet-prerendering-2.0.6.tgz",
"dependencies": {
"domain-task": {
"version": "2.0.3",
"from": "domain-task@>=2.0.2 <3.0.0",
"resolved": "https://registry.npmjs.org/domain-task/-/domain-task-2.0.3.tgz"
}
}
"version": "3.0.1",
"from": "aspnet-prerendering@3.0.1",
"resolved": "https://registry.npmjs.org/aspnet-prerendering/-/aspnet-prerendering-3.0.1.tgz"
},
"aspnet-webpack": {
"version": "1.0.29",
"from": "aspnet-webpack@>=1.0.29 <2.0.0",
"resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-1.0.29.tgz"
"version": "2.0.1",
"from": "aspnet-webpack@2.0.1",
"resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-2.0.1.tgz"
},
"aspnet-webpack-react": {
"version": "3.0.0-beta.1",
"from": "aspnet-webpack-react@>=3.0.0-beta <4.0.0",
"resolved": "https://registry.npmjs.org/aspnet-webpack-react/-/aspnet-webpack-react-3.0.0-beta.1.tgz"
"version": "3.0.0",
"from": "aspnet-webpack-react@3.0.0",
"resolved": "https://registry.npmjs.org/aspnet-webpack-react/-/aspnet-webpack-react-3.0.0.tgz"
},
"assert": {
"version": "1.4.1",

View File

@@ -6,15 +6,16 @@
"@types/history": "4.6.0",
"@types/react": "15.0.35",
"@types/react-dom": "15.5.1",
"@types/react-hot-loader": "3.0.3",
"@types/react-redux": "4.4.45",
"@types/react-router": "4.0.12",
"@types/react-router-dom": "4.0.5",
"@types/react-router-redux": "5.0.3",
"@types/webpack": "2.2.15",
"@types/webpack-env": "1.13.0",
"aspnet-prerendering": "^2.0.5",
"aspnet-webpack": "^1.0.29",
"aspnet-webpack-react": "^3.0.0-beta",
"aspnet-prerendering": "^3.0.1",
"aspnet-webpack": "^2.0.1",
"aspnet-webpack-react": "^3.0.0",
"awesome-typescript-loader": "3.2.1",
"bootstrap": "3.3.7",
"css-loader": "0.28.4",

View File

@@ -1,21 +1,16 @@
{
"compilerOptions": {
"baseUrl": ".",
"module": "es2015",
"moduleResolution": "node",
"target": "es5",
"jsx": "react",
"experimentalDecorators": true,
"sourceMap": true,
"skipDefaultLibCheck": true,
"strict": true,
"lib": ["es6", "dom"],
"types": [ "webpack-env" ],
"paths": {
// Fix "Duplicate identifier" errors caused by multiple dependencies fetching their own copies of type definitions.
// We tell TypeScript which type definitions module to treat as the canonical one (instead of combining all of them).
"history": ["./node_modules/@types/history/index"],
"redux": ["./node_modules/@types/redux/index"],
"react": ["./node_modules/@types/react/index"]
}
"types": ["webpack-env"]
},
"exclude": [
"bin",

View File

@@ -13,11 +13,12 @@ module.exports = (env) => {
resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx'] },
output: {
filename: '[name].js',
publicPath: '/dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
publicPath: 'dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
},
module: {
rules: [
{ test: /\.tsx?$/, include: /ClientApp/, use: 'awesome-typescript-loader?silent=true' }
{ test: /\.tsx?$/, include: /ClientApp/, use: 'awesome-typescript-loader?silent=true' },
{ test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' }
]
},
plugins: [new CheckerPlugin()]
@@ -29,8 +30,7 @@ module.exports = (env) => {
entry: { 'main-client': './ClientApp/boot-client.tsx' },
module: {
rules: [
{ test: /\.css$/, use: ExtractTextPlugin.extract({ use: isDevBuild ? 'css-loader' : 'css-loader?minimize' }) },
{ test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' }
{ test: /\.css$/, use: ExtractTextPlugin.extract({ use: isDevBuild ? 'css-loader' : 'css-loader?minimize' }) }
]
},
output: { path: path.join(__dirname, clientBundleOutputDir) },

View File

@@ -33,7 +33,7 @@ module.exports = (env) => {
],
},
output: {
publicPath: '/dist/',
publicPath: 'dist/',
filename: '[name].js',
library: '[name]_[hash]',
},

View File

@@ -10,9 +10,10 @@ let routes = RoutesModule.routes;
function renderApp() {
// This code starts up the React app when it runs in a browser. It sets up the routing
// configuration and injects the app into a DOM element.
const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href')!;
ReactDOM.render(
<AppContainer>
<BrowserRouter children={ routes } />
<BrowserRouter children={ routes } basename={ baseUrl } />
</AppContainer>,
document.getElementById('react-app')
);

View File

@@ -1,10 +1,11 @@
import * as React from 'react';
import { RouteComponentProps } from 'react-router';
interface CounterState {
currentCount: number;
}
export class Counter extends React.Component<{}, CounterState> {
export class Counter extends React.Component<RouteComponentProps<{}>, CounterState> {
constructor() {
super();
this.state = { currentCount: 0 };

View File

@@ -1,4 +1,5 @@
import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import 'isomorphic-fetch';
interface FetchDataExampleState {
@@ -6,12 +7,12 @@ interface FetchDataExampleState {
loading: boolean;
}
export class FetchData extends React.Component<{}, FetchDataExampleState> {
export class FetchData extends React.Component<RouteComponentProps<{}>, FetchDataExampleState> {
constructor() {
super();
this.state = { forecasts: [], loading: true };
fetch('/api/SampleData/WeatherForecasts')
fetch('api/SampleData/WeatherForecasts')
.then(response => response.json() as Promise<WeatherForecast[]>)
.then(data => {
this.setState({ forecasts: data, loading: false });

View File

@@ -1,6 +1,7 @@
import * as React from 'react';
import { RouteComponentProps } from 'react-router';
export class Home extends React.Component<{}, {}> {
export class Home extends React.Component<RouteComponentProps<{}>, {}> {
public render() {
return <div>
<h1>Hello, world!</h1>

View File

@@ -9,17 +9,17 @@
</PropertyGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' == ''">
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' != ''">
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0-*" />
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
</ItemGroup>
<!--/-:cnd:noEmit -->

View File

@@ -20,12 +20,24 @@
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-15.5.1.tgz",
"dev": true
},
"@types/react-hot-loader": {
"version": "3.0.3",
"from": "@types/react-hot-loader@3.0.3",
"resolved": "https://registry.npmjs.org/@types/react-hot-loader/-/react-hot-loader-3.0.3.tgz",
"dev": true
},
"@types/react-router": {
"version": "4.0.12",
"from": "@types/react-router@4.0.12",
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-4.0.12.tgz",
"dev": true
},
"@types/react-router-dom": {
"version": "4.0.5",
"from": "@types/react-router-dom@4.0.5",
"resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-4.0.5.tgz",
"dev": true
},
"@types/webpack-env": {
"version": "1.13.0",
"from": "@types/webpack-env@1.13.0",
@@ -155,15 +167,15 @@
"dev": true
},
"aspnet-webpack": {
"version": "1.0.29",
"from": "aspnet-webpack@>=1.0.29 <2.0.0",
"resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-1.0.29.tgz",
"version": "2.0.1",
"from": "aspnet-webpack@2.0.1",
"resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-2.0.1.tgz",
"dev": true
},
"aspnet-webpack-react": {
"version": "3.0.0-beta.1",
"from": "aspnet-webpack-react@>=3.0.0-beta <4.0.0",
"resolved": "https://registry.npmjs.org/aspnet-webpack-react/-/aspnet-webpack-react-3.0.0-beta.1.tgz",
"version": "3.0.0",
"from": "aspnet-webpack-react@3.0.0",
"resolved": "https://registry.npmjs.org/aspnet-webpack-react/-/aspnet-webpack-react-3.0.0.tgz",
"dev": true
},
"assert": {

View File

@@ -6,10 +6,12 @@
"@types/history": "4.6.0",
"@types/react": "15.0.35",
"@types/react-dom": "15.5.1",
"@types/react-hot-loader": "3.0.3",
"@types/react-router": "4.0.12",
"@types/react-router-dom": "4.0.5",
"@types/webpack-env": "1.13.0",
"aspnet-webpack": "^1.0.29",
"aspnet-webpack-react": "^3.0.0-beta",
"aspnet-webpack": "^2.0.1",
"aspnet-webpack-react": "^3.0.0",
"awesome-typescript-loader": "3.2.1",
"bootstrap": "3.3.7",
"css-loader": "0.28.4",

View File

@@ -1,18 +1,14 @@
{
"compilerOptions": {
"baseUrl": ".",
"module": "es2015",
"moduleResolution": "node",
"target": "es5",
"jsx": "react",
"sourceMap": true,
"skipDefaultLibCheck": true,
"types": [ "webpack-env" ],
"paths": {
// Fix "Duplicate identifier" errors caused by multiple dependencies fetching their own copies of type definitions.
// We tell TypeScript which type definitions module to treat as the canonical one (instead of combining all of them).
"history": ["./node_modules/@types/history/index"],
"react": ["./node_modules/@types/react/index"]
}
"strict": true,
"types": ["webpack-env"]
},
"exclude": [
"bin",

View File

@@ -13,7 +13,7 @@ module.exports = (env) => {
output: {
path: path.join(__dirname, bundleOutputDir),
filename: '[name].js',
publicPath: '/dist/'
publicPath: 'dist/'
},
module: {
rules: [

View File

@@ -21,7 +21,7 @@ module.exports = (env) => {
},
output: {
path: path.join(__dirname, 'wwwroot', 'dist'),
publicPath: '/dist/',
publicPath: 'dist/',
filename: '[name].js',
library: '[name]_[hash]',
},

View File

@@ -13,7 +13,7 @@ export default class FetchDataComponent extends Vue {
forecasts: WeatherForecast[] = [];
mounted() {
fetch('/api/SampleData/WeatherForecasts')
fetch('api/SampleData/WeatherForecasts')
.then(response => response.json() as Promise<WeatherForecast[]>)
.then(data => {
this.forecasts = data;

View File

@@ -9,17 +9,17 @@
</PropertyGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' == ''">
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkOverride)' != ''">
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0-rtm-26190" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0-*" />
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
</ItemGroup>
<!--/-:cnd:noEmit -->

View File

@@ -2,10 +2,10 @@
"name": "WebApplicationBasic",
"version": "0.0.0",
"dependencies": {
"@types/requirejs": {
"version": "2.1.29",
"from": "@types/requirejs@>=2.1.28 <3.0.0",
"resolved": "https://registry.npmjs.org/@types/requirejs/-/requirejs-2.1.29.tgz",
"@types/webpack-env": {
"version": "1.13.0",
"from": "@types/webpack-env@>=1.13.0 <2.0.0",
"resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.13.0.tgz",
"dev": true
},
"abbrev": {
@@ -119,9 +119,9 @@
"dev": true
},
"aspnet-webpack": {
"version": "1.0.29",
"from": "aspnet-webpack@>=1.0.27 <2.0.0",
"resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-1.0.29.tgz",
"version": "2.0.1",
"from": "aspnet-webpack@2.0.1",
"resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-2.0.1.tgz",
"dev": true
},
"assert": {

View File

@@ -3,8 +3,8 @@
"private": true,
"version": "0.0.0",
"devDependencies": {
"@types/requirejs": "^2.1.28",
"aspnet-webpack": "^1.0.27",
"@types/webpack-env": "^1.13.0",
"aspnet-webpack": "^2.0.1",
"awesome-typescript-loader": "^3.0.0",
"bootstrap": "^3.3.6",
"css-loader": "^0.25.0",

View File

@@ -7,7 +7,8 @@
"target": "es5",
"sourceMap": true,
"skipDefaultLibCheck": true,
"types": ["requirejs"]
"strict": true,
"types": ["webpack-env"]
},
"exclude": [
"bin",

View File

@@ -23,7 +23,7 @@ module.exports = (env) => {
output: {
path: path.join(__dirname, bundleOutputDir),
filename: '[name].js',
publicPath: '/dist/'
publicPath: 'dist/'
},
plugins: [
new CheckerPlugin(),

View File

@@ -28,7 +28,7 @@ module.exports = (env) => {
},
output: {
path: path.join(__dirname, 'wwwroot', 'dist'),
publicPath: '/dist/',
publicPath: 'dist/',
filename: '[name].js',
library: '[name]_[hash]'
},

View File

@@ -91,20 +91,13 @@ function copyRecursive(sourceRoot: string, destRoot: string, matchGlob: string)
});
}
function leftPad(str: string, minLength: number, padChar: string) {
while (str.length < minLength) {
str = padChar + str;
}
return str;
}
function getBuildNumber(): string {
if (process.env.APPVEYOR_BUILD_NUMBER) {
return leftPad(process.env.APPVEYOR_BUILD_NUMBER, 6, '0');
return process.env.APPVEYOR_BUILD_NUMBER;
}
// For local builds, use timestamp
return 't-' + Math.floor((new Date().valueOf() - new Date(2017, 0, 1).valueOf()) / (60*1000));
return Math.floor((new Date().valueOf() - new Date(2017, 0, 1).valueOf()) / (60*1000)) + '-local';
}
function buildYeomanNpmPackage(outputRoot: string) {
@@ -206,10 +199,23 @@ function buildDotNetNewNuGetPackage(packageId: string) {
HostIdentifier: {
type: 'bind',
binding: 'HostIdentifier'
},
skipRestore: {
type: 'parameter',
datatype: 'bool',
description: 'If specified, skips the automatic restore of the project on create.',
defaultValue: 'false'
}
},
tags: { language: 'C#', type: 'project' },
postActions: [
{
condition: '(!skipRestore)',
description: 'Restore NuGet packages required by this project.',
manualInstructions: [{ text: 'Run \'dotnet restore\'' }],
actionId: '210D431B-A78B-4D2F-B762-4ED3E3EA9025',
continueOnError: true
},
/*
// Currently it doesn't appear to be possible to run `npm install` from a
// postAction, due to https://github.com/dotnet/templating/issues/849
@@ -245,7 +251,11 @@ function buildDotNetNewNuGetPackage(packageId: string) {
},
Framework: {
longName: 'framework'
}
},
skipRestore: {
longName: 'no-restore',
shortName: ''
},
}
}, null, 2));

View File

@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>Microsoft.DotNet.Web.Spa.ProjectTemplates</id>
<version>1.0.0-preview-{buildnumber}</version>
<version>1.0.{buildnumber}</version>
<description>Single Page Application templates for ASP.NET Core</description>
<authors>Microsoft</authors>
<language>en-US</language>

View File

@@ -1,6 +1,6 @@
{
"name": "generator-aspnetcore-spa",
"version": "0.9.4",
"version": "1.0.0",
"description": "Single-Page App templates for ASP.NET Core",
"author": "Microsoft",
"license": "Apache-2.0",

View File

@@ -1,9 +1,7 @@
<!-- This file may be overwritten by automation. Only values allowed here are VersionPrefix and VersionSuffix. -->
<Project>
<PropertyGroup>
<VersionPrefix>2.0.1</VersionPrefix>
<VersionPrefix>2.0.0</VersionPrefix>
<VersionSuffix>rtm</VersionSuffix>
<PackageVersion Condition="'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' == 'rtm' ">$(VersionPrefix)</PackageVersion>
<PackageVersion Condition="'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' != 'rtm' ">$(VersionPrefix)-$(VersionSuffix)-final</PackageVersion>
<VersionSuffix Condition="'$(VersionSuffix)' != '' And '$(BuildNumber)' != ''">$(VersionSuffix)-$(BuildNumber)</VersionSuffix>
</PropertyGroup>
</Project>