├── .npmrc ├── global.json ├── ClientApp ├── store │ ├── api.js │ └── index.js ├── boot-app.js ├── router.js ├── routes.js ├── boot-server.js ├── app.js ├── components │ ├── app-root.vue │ ├── counter-example.vue │ ├── nav-menu.vue │ ├── fetch-data.vue │ └── home-page.vue └── css │ └── site.css ├── Views ├── _ViewStart.cshtml ├── _ViewImports.cshtml ├── Home │ └── Index.cshtml └── Shared │ ├── Error.cshtml │ └── _Layout.cshtml ├── .gitattributes ├── .babelrc ├── .editorconfig ├── appsettings.json ├── NuGet.config ├── Controllers ├── HomeController.cs └── SampleDataController.cs ├── Program.cs ├── web.config ├── .eslintrc.js ├── LICENSE.md ├── Vue2Spa.sln ├── Services ├── Hubs │ ├── CounterHub.cs │ └── WeatherHub.cs └── HostedService.cs ├── Vue2Spa.csproj ├── package.json ├── Startup.cs ├── webpack.config.vendor.js ├── webpack.config.js ├── README.md ├── .gitignore └── clientapp └── signalr.min.js /.npmrc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { "version": "2.1.300" } 3 | } -------------------------------------------------------------------------------- /ClientApp/store/api.js: -------------------------------------------------------------------------------- 1 | export function test() { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @addTagHelper "*, Microsoft.AspNetCore.Mvc.TagHelpers" 2 | @addTagHelper "*, Microsoft.AspNetCore.SpaServices" 3 | -------------------------------------------------------------------------------- /ClientApp/boot-app.js: -------------------------------------------------------------------------------- 1 | import './css/site.css' 2 | import 'core-js/es6/promise' 3 | import 'core-js/es6/array' 4 | 5 | import { app } from './app' 6 | 7 | app.$mount('#app') 8 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-2"], 3 | "plugins": [ 4 | "transform-runtime", 5 | "transform-async-to-generator" 6 | ], 7 | "comments": false 8 | } 9 | -------------------------------------------------------------------------------- /Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ ViewData["Title"] = "Home Page"; } 2 | 3 |
4 | 5 | @section scripts { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Error"; 3 | } 4 | 5 |

Error.

6 |

An error occurred while processing your request.

7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": {}, 3 | "Logging": { 4 | "IncludeScopes": false, 5 | "LogLevel": { 6 | "Default": "Debug", 7 | "System": "Information", 8 | "Microsoft": "Information" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ClientApp/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | 4 | import { routes } from './routes' 5 | 6 | Vue.use(VueRouter); 7 | 8 | let router = new VueRouter({ 9 | mode: 'history', 10 | routes 11 | }) 12 | 13 | export default router 14 | -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace Vue2SpaSignalR.Controllers 4 | { 5 | public class HomeController : Controller 6 | { 7 | public IActionResult Index() 8 | { 9 | return View(); 10 | } 11 | 12 | public IActionResult Error() 13 | { 14 | return View(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | 4 | namespace Vue2SpaSignalR 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | BuildWebHost(args).Run(); 11 | } 12 | 13 | public static IWebHost BuildWebHost(string[] args) => 14 | WebHost.CreateDefaultBuilder(args) 15 | .UseStartup() 16 | .Build(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ClientApp/routes.js: -------------------------------------------------------------------------------- 1 | import CounterExample from 'components/counter-example' 2 | import FetchData from 'components/fetch-data' 3 | import HomePage from 'components/home-page' 4 | 5 | export const routes = [ 6 | { path: '/', component: HomePage, display: 'Home', style: 'glyphicon glyphicon-home' }, 7 | { path: '/counter', component: CounterExample, display: 'Counter', style: 'glyphicon glyphicon-education' }, 8 | { path: '/fetch-data', component: FetchData, display: 'Fetch data', style: 'glyphicon glyphicon-th-list' } 9 | ] -------------------------------------------------------------------------------- /ClientApp/boot-server.js: -------------------------------------------------------------------------------- 1 | var prerendering = require('aspnet-prerendering'); 2 | 3 | module.exports = prerendering.createServerRenderer(function (params) { 4 | return new Promise(function (resolve, reject) { 5 | var result = '

Loading...

' 6 | + '

Current time in Node is: ' + new Date() + '

' 7 | + '

Request path is: ' + params.location.path + '

' 8 | + '

Absolute URL is: ' + params.absoluteUrl + '

'; 9 | 10 | resolve({ html: result }); 11 | }); 12 | }); -------------------------------------------------------------------------------- /web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ClientApp/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | Vue.use(Vuex) 5 | 6 | // TYPES 7 | const MAIN_SET_COUNTER = 'MAIN_SET_COUNTER' 8 | 9 | // STATE 10 | const state = { 11 | counter: 0 12 | } 13 | 14 | // MUTATIONS 15 | const mutations = { 16 | [MAIN_SET_COUNTER](state, obj) { 17 | state.counter = obj.counter 18 | } 19 | } 20 | 21 | // ACTIONS 22 | const actions = ({ 23 | setCounter({ commit }, obj) { 24 | commit(MAIN_SET_COUNTER, obj) 25 | } 26 | }) 27 | 28 | export default new Vuex.Store({ 29 | state, 30 | mutations, 31 | actions 32 | }); 33 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: 'babel-eslint', 4 | parserOptions: { 5 | sourceType: 'module' 6 | }, 7 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style 8 | extends: 'standard', 9 | // required to lint *.vue files 10 | plugins: [ 11 | 'html' 12 | ], 13 | // add your custom rules here 14 | 'rules': { 15 | // allow paren-less arrow functions 16 | 'arrow-parens': 0, 17 | // allow async-await 18 | 'generator-star-spacing': 0, 19 | // allow debugger during development 20 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ClientApp/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import axios from 'axios' 3 | import router from './router' 4 | import store from './store' 5 | import { sync } from 'vuex-router-sync' 6 | import App from 'components/app-root' 7 | 8 | import 'bootstrap' 9 | 10 | import jquery from 'jquery' 11 | window.$ = jquery 12 | window.jQuery = jquery 13 | 14 | var signalR = require('./signalr.min.js'); 15 | 16 | Vue.prototype.$http = axios; 17 | Vue.prototype.$signalR = signalR; 18 | 19 | sync(store, router); 20 | 21 | const app = new Vue({ 22 | store, 23 | router, 24 | ...App 25 | }); 26 | 27 | export { 28 | app, 29 | router, 30 | store 31 | } 32 | -------------------------------------------------------------------------------- /Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | @ViewData["Title"] - aspnetcore_Vue_starter 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | @RenderBody() 17 | 18 | 19 | @RenderSection("scripts", required: false) 20 | 21 | 22 | -------------------------------------------------------------------------------- /ClientApp/components/app-root.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 35 | 36 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Mark Pieszak 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Vue2Spa.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.12 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vue2Spa", "Vue2Spa.csproj", "{B5FE715F-AB99-4FA6-AEC1-D3B644C76DF7}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {B5FE715F-AB99-4FA6-AEC1-D3B644C76DF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {B5FE715F-AB99-4FA6-AEC1-D3B644C76DF7}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {B5FE715F-AB99-4FA6-AEC1-D3B644C76DF7}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {B5FE715F-AB99-4FA6-AEC1-D3B644C76DF7}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {04E0BE98-0A7D-4CAD-901A-079384E6D51E} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Services/Hubs/CounterHub.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Microsoft.AspNetCore.SignalR; 5 | 6 | namespace Vue2SpaSignalR.Services.Hubs 7 | { 8 | public class CounterHub : Hub 9 | { 10 | 11 | } 12 | 13 | public class Counter : HostedService 14 | { 15 | public Counter(IHubContext context) 16 | { 17 | Clients = context.Clients; 18 | } 19 | 20 | private IHubClients Clients { get; } 21 | 22 | protected override async Task ExecuteAsync(CancellationToken cancellationToken) 23 | { 24 | int counter = 0; 25 | 26 | while (true) 27 | { 28 | await Clients.All.SendAsync("increment", counter); 29 | 30 | var task = Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); 31 | 32 | try 33 | { 34 | await task; 35 | } 36 | catch (TaskCanceledException) 37 | { 38 | break; 39 | } 40 | 41 | counter++; 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ClientApp/components/counter-example.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 39 | 40 | 42 | -------------------------------------------------------------------------------- /ClientApp/components/nav-menu.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 39 | 40 | -------------------------------------------------------------------------------- /Controllers/SampleDataController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Microsoft.AspNetCore.Mvc; 5 | 6 | namespace Vue2SpaSignalR.Controllers 7 | { 8 | [Route("api/[controller]")] 9 | public class SampleDataController : Controller 10 | { 11 | private static string[] Summaries = new[] 12 | { 13 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" 14 | }; 15 | 16 | [HttpGet("[action]")] 17 | public IEnumerable WeatherForecasts() 18 | { 19 | var rng = new Random(); 20 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast 21 | { 22 | DateFormatted = DateTime.Now.AddDays(index).ToString("d"), 23 | TemperatureC = rng.Next(-20, 55), 24 | Summary = Summaries[rng.Next(Summaries.Length)] 25 | }); 26 | } 27 | 28 | public class WeatherForecast 29 | { 30 | public string DateFormatted { get; set; } 31 | public int TemperatureC { get; set; } 32 | public string Summary { get; set; } 33 | 34 | public int TemperatureF 35 | { 36 | get 37 | { 38 | return 32 + (int)(TemperatureC / 0.5556); 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Vue2Spa.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netcoreapp2.1 4 | Vue2SpaSignalR 5 | Vue2SpaSignalR 6 | 7.1 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | %(DistFiles.Identity) 29 | PreserveNewest 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aspnetcore-vuejs", 3 | "description": "ASP.NET Core & VueJS Starter project", 4 | "author": "Mark Pieszak", 5 | "scripts": { 6 | "dev": "cross-env ASPNETCORE_ENVIRONMENT=Development NODE_ENV=development dotnet run", 7 | "build": "cross-env NODE_ENV=production webpack --progress --hide-modules", 8 | "install": "webpack --config webpack.config.vendor.js" 9 | }, 10 | "dependencies": { 11 | "axios": "^0.15.3", 12 | "core-js": "^2.4.1", 13 | "font-awesome": "^4.6.3", 14 | "vue": "^2.1.6", 15 | "vue-template-compiler": "^2.1.6", 16 | "vue-router": "^2.1.1", 17 | "vue-server-renderer": "^2.1.6", 18 | "vuex": "^2.1.1", 19 | "vuex-router-sync": "^4.0.1", 20 | "@aspnet/signalr": "^1.0.0" 21 | }, 22 | "devDependencies": { 23 | "aspnet-webpack": "^2.0.1", 24 | "babel-core": "^6.21.0", 25 | "babel-loader": "^6.2.10", 26 | "babel-plugin-transform-async-to-generator": "^6.22.0", 27 | "babel-plugin-transform-runtime": "^6.15.0", 28 | "babel-preset-es2015": "^6.18.0", 29 | "babel-preset-stage-2": "^6.18.0", 30 | "babel-register": "^6.18.0", 31 | "bootstrap": "^3.3.6", 32 | "cross-env": "^3.1.3", 33 | "css-loader": "^0.26.1", 34 | "event-source-polyfill": "^0.0.7", 35 | "extract-text-webpack-plugin": "^2.0.0-rc", 36 | "file-loader": "^0.9.0", 37 | "jquery": "^2.2.1", 38 | "node-sass": "^4.1.0", 39 | "optimize-css-assets-webpack-plugin": "^1.3.1", 40 | "sass-loader": "^4.1.0", 41 | "style-loader": "^0.13.1", 42 | "url-loader": "^0.5.7", 43 | "vue-loader": "^10.0.2", 44 | "webpack": "^2.2.0", 45 | "webpack-hot-middleware": "^2.12.2" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ClientApp/css/site.css: -------------------------------------------------------------------------------- 1 | .main-nav li .glyphicon { 2 | margin-right: 10px; 3 | } 4 | 5 | /* Highlighting rules for nav menu items */ 6 | .main-nav li a.active, 7 | .main-nav li a.active:hover, 8 | .main-nav li a.active:focus { 9 | background-color: #4189C7; 10 | color: white; 11 | } 12 | 13 | /* Keep the nav menu independent of scrolling and on top of other items */ 14 | .main-nav { 15 | position: fixed; 16 | top: 0; 17 | left: 0; 18 | right: 0; 19 | z-index: 1; 20 | } 21 | 22 | @media (max-width: 767px) { 23 | /* On small screens, the nav menu spans the full width of the screen. Leave a space for it. */ 24 | body { 25 | padding-top: 50px; 26 | } 27 | } 28 | 29 | @media (min-width: 768px) { 30 | /* On small screens, convert the nav menu to a vertical sidebar */ 31 | .main-nav { 32 | height: 100%; 33 | width: calc(25% - 20px); 34 | } 35 | .main-nav .navbar { 36 | border-radius: 0px; 37 | border-width: 0px; 38 | height: 100%; 39 | } 40 | .main-nav .navbar-header { 41 | float: none; 42 | } 43 | .main-nav .navbar-collapse { 44 | border-top: 1px solid #444; 45 | padding: 0px; 46 | } 47 | .main-nav .navbar ul { 48 | float: none; 49 | } 50 | .main-nav .navbar li { 51 | float: none; 52 | font-size: 15px; 53 | margin: 6px; 54 | } 55 | .main-nav .navbar li a { 56 | padding: 10px 16px; 57 | border-radius: 4px; 58 | } 59 | .main-nav .navbar a { 60 | /* If a menu item's text is too long, truncate it */ 61 | width: 100%; 62 | white-space: nowrap; 63 | overflow: hidden; 64 | text-overflow: ellipsis; 65 | } 66 | } -------------------------------------------------------------------------------- /ClientApp/components/fetch-data.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 57 | 58 | 60 | -------------------------------------------------------------------------------- /Services/HostedService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Microsoft.Extensions.Hosting; 7 | 8 | namespace Vue2SpaSignalR.Services 9 | { 10 | public abstract class HostedService : IHostedService 11 | { 12 | // Example untested base class code kindly provided by David Fowler: https://gist.github.com/davidfowl/a7dd5064d9dcf35b6eae1a7953d615e3 13 | 14 | private Task _executingTask; 15 | private CancellationTokenSource _cts; 16 | 17 | public Task StartAsync(CancellationToken cancellationToken) 18 | { 19 | // Create a linked token so we can trigger cancellation outside of this token's cancellation 20 | _cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); 21 | 22 | // Store the task we're executing 23 | _executingTask = ExecuteAsync(_cts.Token); 24 | 25 | // If the task is completed then return it, otherwise it's running 26 | return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask; 27 | } 28 | 29 | public async Task StopAsync(CancellationToken cancellationToken) 30 | { 31 | // Stop called without start 32 | if (_executingTask == null) 33 | { 34 | return; 35 | } 36 | 37 | // Signal cancellation to the executing method 38 | _cts.Cancel(); 39 | 40 | // Wait until the task completes or the stop token triggers 41 | await Task.WhenAny(_executingTask, Task.Delay(-1, cancellationToken)); 42 | 43 | // Throw if cancellation triggered 44 | cancellationToken.ThrowIfCancellationRequested(); 45 | } 46 | 47 | // Derived classes should override this and execute a long running method until 48 | // cancellation is requested 49 | protected abstract Task ExecuteAsync(CancellationToken cancellationToken); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.SpaServices.Webpack; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Hosting; 6 | using Vue2SpaSignalR.Services.Hubs; 7 | 8 | namespace Vue2SpaSignalR 9 | { 10 | public class Startup 11 | { 12 | public Startup(IConfiguration configuration) 13 | { 14 | Configuration = configuration; 15 | } 16 | 17 | public IConfiguration Configuration { get; } 18 | 19 | public void ConfigureServices(IServiceCollection services) 20 | { 21 | services.AddMvc(); 22 | 23 | services.AddSignalR(); 24 | 25 | services.AddSingleton(); 26 | services.AddSingleton(); 27 | } 28 | 29 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) 30 | { 31 | if (env.IsDevelopment()) 32 | { 33 | app.UseDeveloperExceptionPage(); 34 | app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions 35 | { 36 | HotModuleReplacement = true 37 | }); 38 | } 39 | else 40 | { 41 | app.UseExceptionHandler("/Home/Error"); 42 | } 43 | 44 | app.UseStaticFiles(); 45 | app.UseSignalR(routes => 46 | { 47 | routes.MapHub("/count"); 48 | routes.MapHub("/weather"); 49 | }); 50 | 51 | app.UseMvc(routes => 52 | { 53 | routes.MapRoute( 54 | name: "default", 55 | template: "{controller=Home}/{action=Index}/{id?}"); 56 | 57 | routes.MapSpaFallbackRoute( 58 | name: "spa-fallback", 59 | defaults: new { controller = "Home", action = "Index" }); 60 | }); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /webpack.config.vendor.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 4 | var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin'); 5 | 6 | module.exports = (env) => { 7 | const extractCSS = new ExtractTextPlugin('vendor.css'); 8 | const isDevBuild = !(env && env.prod); 9 | return [{ 10 | stats: { modules: false }, 11 | resolve: { 12 | extensions: ['.js'] 13 | }, 14 | module: { 15 | rules: [ 16 | { test: /\.(png|woff|woff2|eot|ttf|svg)(\?|$)/, use: 'url-loader?limit=100000' }, 17 | { test: /\.css(\?|$)/, use: extractCSS.extract(['css-loader']) } 18 | ] 19 | }, 20 | entry: { 21 | vendor: ['bootstrap', 'bootstrap/dist/css/bootstrap.css', 'event-source-polyfill', 'vue', 'vuex', 'axios', 'vue-router', 'jquery'], 22 | }, 23 | output: { 24 | path: path.join(__dirname, 'wwwroot', 'dist'), 25 | publicPath: '/dist/', 26 | filename: '[name].js', 27 | library: '[name]_[hash]', 28 | }, 29 | plugins: [ 30 | extractCSS, 31 | // Compress extracted CSS. 32 | new OptimizeCSSPlugin({ 33 | cssProcessorOptions: { 34 | safe: true 35 | } 36 | }), 37 | new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }), // Maps these identifiers to the jQuery package (because Bootstrap expects it to be a global variable) 38 | new webpack.DllPlugin({ 39 | path: path.join(__dirname, 'wwwroot', 'dist', '[name]-manifest.json'), 40 | name: '[name]_[hash]' 41 | }), 42 | new webpack.DefinePlugin({ 43 | 'process.env.NODE_ENV': isDevBuild ? '"development"' : '"production"' 44 | }) 45 | ].concat(isDevBuild ? [] : [ 46 | new webpack.optimize.UglifyJsPlugin() 47 | ]) 48 | }]; 49 | }; 50 | -------------------------------------------------------------------------------- /Services/Hubs/WeatherHub.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.SignalR; 6 | 7 | 8 | namespace Vue2SpaSignalR.Services.Hubs 9 | { 10 | public class WeatherHub : Hub 11 | { 12 | 13 | } 14 | 15 | public class Weather : HostedService 16 | { 17 | public Weather(IHubContext context) 18 | { 19 | Clients = context.Clients; 20 | } 21 | 22 | private IHubClients Clients { get; } 23 | 24 | private static readonly string[] Summaries = { 25 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" 26 | }; 27 | 28 | public async Task UpdateWeatherForecasts() 29 | { 30 | var rng = new Random(); 31 | var randomWeatherForescast = Enumerable.Range(1, 5).Select(index => new WeatherForecast 32 | { 33 | DateFormatted = DateTime.Now.AddDays(index).ToString("d"), 34 | TemperatureC = rng.Next(-20, 55), 35 | Summary = Summaries[rng.Next(Summaries.Length)] 36 | }); 37 | 38 | await Clients.All.SendAsync("weather", randomWeatherForescast); 39 | } 40 | 41 | protected override async Task ExecuteAsync(CancellationToken cancellationToken) 42 | { 43 | while (true) 44 | { 45 | await UpdateWeatherForecasts(); 46 | 47 | var task = Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); 48 | try 49 | { 50 | await task; 51 | } 52 | catch (TaskCanceledException) 53 | { 54 | return; 55 | } 56 | } 57 | } 58 | 59 | public class WeatherForecast 60 | { 61 | public string DateFormatted { get; set; } 62 | public int TemperatureC { get; set; } 63 | public string Summary { get; set; } 64 | 65 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 4 | const bundleOutputDir = './wwwroot/dist'; 5 | 6 | module.exports = (env) => { 7 | const isDevBuild = !(env && env.prod); 8 | return [{ 9 | stats: { modules: false }, 10 | entry: { 'main': './ClientApp/boot-app.js' }, 11 | resolve: { 12 | extensions: ['.js', '.vue'], 13 | alias: { 14 | 'vue$': 'vue/dist/vue', 15 | 'components': path.resolve(__dirname, './ClientApp/components'), 16 | 'views': path.resolve(__dirname, './ClientApp/views'), 17 | 'utils': path.resolve(__dirname, './ClientApp/utils'), 18 | 'api': path.resolve(__dirname, './ClientApp/store/api') 19 | } 20 | }, 21 | output: { 22 | path: path.join(__dirname, bundleOutputDir), 23 | filename: '[name].js', 24 | publicPath: '/dist/' 25 | }, 26 | module: { 27 | rules: [ 28 | { test: /\.vue$/, include: /ClientApp/, use: 'vue-loader' }, 29 | { test: /\.js$/, include: /ClientApp/, use: 'babel-loader' }, 30 | { test: /\.css$/, use: isDevBuild ? ['style-loader', 'css-loader'] : ExtractTextPlugin.extract({ use: 'css-loader' }) }, 31 | { test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' } 32 | ] 33 | }, 34 | plugins: [ 35 | new webpack.DllReferencePlugin({ 36 | context: __dirname, 37 | manifest: require('./wwwroot/dist/vendor-manifest.json') 38 | }) 39 | ].concat(isDevBuild ? [ 40 | // Plugins that apply in development builds only 41 | new webpack.SourceMapDevToolPlugin({ 42 | filename: '[file].map', // Remove this line if you prefer inline source maps 43 | moduleFilenameTemplate: path.relative(bundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk 44 | }) 45 | ] : [ 46 | // Plugins that apply in production builds only 47 | new webpack.optimize.UglifyJsPlugin(), 48 | new ExtractTextPlugin('site.css') 49 | ]) 50 | }]; 51 | }; 52 | -------------------------------------------------------------------------------- /ClientApp/components/home-page.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 39 | 40 | 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Asp.NETCore 2.1 Vue 2 SignalR Starter 2 | 3 | This repo contains an aspnetcore + Vue.js 2 + SignalR Alpha starter template (VS2017). The template is based 4 | on the [aspnetcore-Vue-starter Template](https://github.com/MarkPieszak/aspnetcore-Vue-starter) 5 | 6 | _Looking for the original starter templates? [click here](https://blogs.msdn.microsoft.com/webdev/2017/02/14/building-single-page-applications-on-asp-net-core-with-javascriptservices/)_ 7 | 8 | _Looking for aspnetcore & Angular 2.x+ Universal starter? [click here](https://github.com/MarkPieszak/aspnetcore-angular2-universal)_ 9 | 10 | _Looking for SignalR source code? [click here](https://github.com/aspnet/SignalR)_ 11 | 12 | --- 13 | 14 | # Table of Contents 15 | 16 | * [Features](#features) 17 | * [Prerequisites](#prerequisites) 18 | * [Installation - Getting Started!](#installation) 19 | * [Special Thanks](#special-thanks) 20 | * [License](#license) 21 | * [Social Media](#follow-me-online) 22 | 23 | # Features 24 | 25 | - **ASP.NET Core 2.1** 26 | - Web API 27 | - **VueJS 2** 28 | - Vuex (State Store) 29 | - **Webpack 2** 30 | - HMR (Hot Module Replacement/Reloading) 31 | - **Bootstrap** 32 | - **SignalR RC1** 33 | 34 | 35 | # Prerequisites: 36 | * nodejs > 6 37 | * VS2017 38 | * dotnet core 2.1 39 | 40 | # Installation / Getting Started: 41 | * Clone this repo 42 | * At the repo's root directory run `dotnet restore` 43 | * Restore Node dependencies by running `npm install` 44 | * Run the application (`dotnet run` or `npm run dev`) 45 | 46 | or 47 | 48 | * Run the application in VSCode or Visual Studio 2017 (Hit `F5`) 49 | * Browse to [http://localhost:5000](http://localhost:5000) 50 | 51 | # Extras 52 | 53 | - Get Chrome DevTools for Vue [here](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd) 54 | 55 | # Found a Bug? Want to Contribute? 56 | 57 | Nothing's ever perfect, but please let me know by creating an issue (make sure there isn't an existing one about it already), and we'll try and work out a fix for it! If you have any good ideas, or want to contribute, feel free to either make an Issue with the Proposal, or just make a PR from your Fork. 58 | 59 | ---- 60 | 61 | ### Special Thanks 62 | 63 | Many thanks go out to Steve Sanderson (@SteveSandersonMS) from Microsoft and his amazing work on [JavaScriptServices](https://blogs.msdn.microsoft.com/webdev/2017/02/14/building-single-page-applications-on-asp-net-core-with-javascriptservices/) and integrating the world of Node with ASP.NET Core. 64 | 65 | [Mark Pieszak](https://github.com/MarkPieszak) for creating the original template that this was based on. 66 | 67 | [David Fowler](https://github.com/davidfowl) for SignalR and for reviewing and improving this starter template. 68 | 69 | # License 70 | 71 | [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](/LICENSE) 72 | 73 | Copyright (c) 2016-2017 [Eric Malamisura](https://github.com/elucidsoft) 74 | 75 | ### Follow me online: 76 | 77 | Twitter: [@emalamisura](http://twitter.com/emalamisura) 78 | 79 | ---- 80 | 81 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | npm-debug.log 4 | 5 | /Properties/launchSettings.json 6 | 7 | package-lock.json 8 | 9 | ## Ignore Visual Studio temporary files, build results, and 10 | ## files generated by popular Visual Studio add-ons. 11 | 12 | # User-specific files 13 | *.suo 14 | *.user 15 | *.userosscache 16 | *.sln.docstates 17 | 18 | # User-specific files (MonoDevelop/Xamarin Studio) 19 | *.userprefs 20 | 21 | # Build results 22 | [Dd]ebug/ 23 | [Dd]ebugPublic/ 24 | [Rr]elease/ 25 | [Rr]eleases/ 26 | x64/ 27 | x86/ 28 | build/ 29 | bld/ 30 | bin/ 31 | Bin/ 32 | obj/ 33 | Obj/ 34 | 35 | # Visual Studio 2015 cache/options directory 36 | .vs/ 37 | /wwwroot/dist/** 38 | 39 | # Workaround for https://github.com/aspnet/JavaScriptServices/issues/235 40 | !/wwwroot/dist/_placeholder.txt 41 | 42 | /yarn.lock 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUNIT 49 | *.VisualState.xml 50 | TestResult.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # DNX 58 | project.lock.json 59 | artifacts/ 60 | 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.pch 68 | *.pdb 69 | *.pgc 70 | *.pgd 71 | *.rsp 72 | *.sbr 73 | *.tlb 74 | *.tli 75 | *.tlh 76 | *.tmp 77 | *.tmp_proj 78 | *.log 79 | *.vspscc 80 | *.vssscc 81 | .builds 82 | *.pidb 83 | *.svclog 84 | *.scc 85 | 86 | # Chutzpah Test files 87 | _Chutzpah* 88 | 89 | # Visual C++ cache files 90 | ipch/ 91 | *.aps 92 | *.ncb 93 | *.opendb 94 | *.opensdf 95 | *.sdf 96 | *.cachefile 97 | 98 | # Visual Studio profiler 99 | *.psess 100 | *.vsp 101 | *.vspx 102 | *.sap 103 | 104 | # TFS 2012 Local Workspace 105 | $tf/ 106 | 107 | # Guidance Automation Toolkit 108 | *.gpState 109 | 110 | # ReSharper is a .NET coding add-in 111 | _ReSharper*/ 112 | *.[Rr]e[Ss]harper 113 | *.DotSettings.user 114 | 115 | # JustCode is a .NET coding add-in 116 | .JustCode 117 | 118 | # TeamCity is a build add-in 119 | _TeamCity* 120 | 121 | # DotCover is a Code Coverage Tool 122 | *.dotCover 123 | 124 | # NCrunch 125 | _NCrunch_* 126 | .*crunch*.local.xml 127 | nCrunchTemp_* 128 | 129 | # MightyMoose 130 | *.mm.* 131 | AutoTest.Net/ 132 | 133 | # Web workbench (sass) 134 | .sass-cache/ 135 | 136 | # Installshield output folder 137 | [Ee]xpress/ 138 | 139 | # DocProject is a documentation generator add-in 140 | DocProject/buildhelp/ 141 | DocProject/Help/*.HxT 142 | DocProject/Help/*.HxC 143 | DocProject/Help/*.hhc 144 | DocProject/Help/*.hhk 145 | DocProject/Help/*.hhp 146 | DocProject/Help/Html2 147 | DocProject/Help/html 148 | 149 | # Click-Once directory 150 | publish/ 151 | 152 | # Publish Web Output 153 | *.[Pp]ublish.xml 154 | *.azurePubxml 155 | # TODO: Comment the next line if you want to checkin your web deploy settings 156 | # but database connection strings (with potential passwords) will be unencrypted 157 | *.pubxml 158 | *.publishproj 159 | 160 | # NuGet Packages 161 | *.nupkg 162 | # The packages folder can be ignored because of Package Restore 163 | **/packages/* 164 | # except build/, which is used as an MSBuild target. 165 | !**/packages/build/ 166 | # Uncomment if necessary however generally it will be regenerated when needed 167 | #!**/packages/repositories.config 168 | 169 | # Microsoft Azure Build Output 170 | csx/ 171 | *.build.csdef 172 | 173 | # Microsoft Azure Emulator 174 | ecf/ 175 | rcf/ 176 | 177 | # Microsoft Azure ApplicationInsights config file 178 | ApplicationInsights.config 179 | 180 | # Windows Store app package directory 181 | AppPackages/ 182 | BundleArtifacts/ 183 | 184 | # Visual Studio cache files 185 | # files ending in .cache can be ignored 186 | *.[Cc]ache 187 | # but keep track of directories ending in .cache 188 | !*.[Cc]ache/ 189 | 190 | # Others 191 | ClientBin/ 192 | ~$* 193 | *~ 194 | *.dbmdl 195 | *.dbproj.schemaview 196 | *.pfx 197 | *.publishsettings 198 | orleans.codegen.cs 199 | 200 | # Workaround for https://github.com/aspnet/JavaScriptServices/issues/235 201 | /node_modules/** 202 | !/node_modules/_placeholder.txt 203 | 204 | # RIA/Silverlight projects 205 | Generated_Code/ 206 | 207 | # Backup & report files from converting an old project file 208 | # to a newer Visual Studio version. Backup files are not needed, 209 | # because we have git ;-) 210 | _UpgradeReport_Files/ 211 | Backup*/ 212 | UpgradeLog*.XML 213 | UpgradeLog*.htm 214 | 215 | # SQL Server files 216 | *.mdf 217 | *.ldf 218 | 219 | # Business Intelligence projects 220 | *.rdl.data 221 | *.bim.layout 222 | *.bim_*.settings 223 | 224 | # Microsoft Fakes 225 | FakesAssemblies/ 226 | 227 | # GhostDoc plugin setting file 228 | *.GhostDoc.xml 229 | 230 | # Node.js Tools for Visual Studio 231 | .ntvs_analysis.dat 232 | 233 | # Visual Studio 6 build log 234 | *.plg 235 | 236 | # Visual Studio 6 workspace options file 237 | *.opt 238 | 239 | # Visual Studio LightSwitch build output 240 | **/*.HTMLClient/GeneratedArtifacts 241 | **/*.DesktopClient/GeneratedArtifacts 242 | **/*.DesktopClient/ModelManifest.xml 243 | **/*.Server/GeneratedArtifacts 244 | **/*.Server/ModelManifest.xml 245 | _Pvt_Extensions 246 | 247 | # Paket dependency manager 248 | .paket/paket.exe 249 | 250 | # FAKE - F# Make 251 | .fake/ 252 | 253 | .vscode/ 254 | -------------------------------------------------------------------------------- /clientapp/signalr.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @overview ASP.NET Core SignalR JavaScript Client. 3 | * @version 1.0.0. 4 | * @license 5 | * Copyright (c) .NET Foundation. All rights reserved. 6 | * Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 7 | */ 8 | (function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory():typeof define==="function"&&define.amd?define(factory):global.signalR=factory()})(this,function(){"use strict";var commonjsGlobal=typeof window!=="undefined"?window:typeof global!=="undefined"?global:typeof self!=="undefined"?self:{};function commonjsRequire(){throw new Error("Dynamic requires are not currently supported by rollup-plugin-commonjs")}function unwrapExports(x){return x&&x.__esModule&&Object.prototype.hasOwnProperty.call(x,"default")?x["default"]:x}function createCommonjsModule(fn,module){return module={exports:{}},fn(module,module.exports),module.exports}var extendStatics=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(d,b){d.__proto__=b}||function(d,b){for(var p in b)if(b.hasOwnProperty(p))d[p]=b[p]};function __extends(d,b){extendStatics(d,b);function __(){this.constructor=d}d.prototype=b===null?Object.create(b):(__.prototype=b.prototype,new __)}var __assign=Object.assign||function __assign(t){for(var s,i=1,n=arguments.length;i=0;i--)if(d=decorators[i])r=(c<3?d(r):c>3?d(target,key,r):d(target,key))||r;return c>3&&r&&Object.defineProperty(target,key,r),r}function __param(paramIndex,decorator){return function(target,key){decorator(target,key,paramIndex)}}function __metadata(metadataKey,metadataValue){if(typeof Reflect==="object"&&typeof Reflect.metadata==="function")return Reflect.metadata(metadataKey,metadataValue)}function __awaiter(thisArg,_arguments,P,generator){return new(P||(P=Promise))(function(resolve,reject){function fulfilled(value){try{step(generator.next(value))}catch(e){reject(e)}}function rejected(value){try{step(generator["throw"](value))}catch(e){reject(e)}}function step(result){result.done?resolve(result.value):new P(function(resolve){resolve(result.value)}).then(fulfilled,rejected)}step((generator=generator.apply(thisArg,_arguments||[])).next())})}function __generator(thisArg,body){var _={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1]},trys:[],ops:[]},f,y,t,g;return g={next:verb(0),throw:verb(1),return:verb(2)},typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this}),g;function verb(n){return function(v){return step([n,v])}}function step(op){if(f)throw new TypeError("Generator is already executing.");while(_)try{if(f=1,y&&(t=y[op[0]&2?"return":op[0]?"throw":"next"])&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[0,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]=o.length)o=void 0;return{value:o&&o[i++],done:!o}}}}function __read(o,n){var m=typeof Symbol==="function"&&o[Symbol.iterator];if(!m)return o;var i=m.call(o),r,ar=[],e;try{while((n===void 0||n-- >0)&&!(r=i.next()).done)ar.push(r.value)}catch(error){e={error:error}}finally{try{if(r&&!r.done&&(m=i["return"]))m.call(i)}finally{if(e)throw e.error}}return ar}function __spread(){for(var ar=[],i=0;i1||resume(n,v)})}}function resume(n,v){try{step(g[n](v))}catch(e){settle(q[0][3],e)}}function step(r){r.value instanceof __await?Promise.resolve(r.value.v).then(fulfill,reject):settle(q[0][2],r)}function fulfill(value){resume("next",value)}function reject(value){resume("throw",value)}function settle(f,v){if(f(v),q.shift(),q.length)resume(q[0][0],q[0][1])}}function __asyncDelegator(o){var i,p;return i={},verb("next"),verb("throw",function(e){throw e}),verb("return"),i[Symbol.iterator]=function(){return this},i;function verb(n,f){if(o[n])i[n]=function(v){return(p=!p)?{value:__await(o[n](v)),done:n==="return"}:f?f(v):v}}}function __asyncValues(o){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var m=o[Symbol.asyncIterator];return m?m.call(o):typeof __values==="function"?__values(o):o[Symbol.iterator]()}function __makeTemplateObject(cooked,raw){if(Object.defineProperty){Object.defineProperty(cooked,"raw",{value:raw})}else{cooked.raw=raw}return cooked}function __importStar(mod){if(mod&&mod.__esModule)return mod;var result={};if(mod!=null)for(var k in mod)if(Object.hasOwnProperty.call(mod,k))result[k]=mod[k];result.default=mod;return result}function __importDefault(mod){return mod&&mod.__esModule?mod:{default:mod}}var tslib_1=Object.freeze({__extends:__extends,__assign:__assign,__rest:__rest,__decorate:__decorate,__param:__param,__metadata:__metadata,__awaiter:__awaiter,__generator:__generator,__exportStar:__exportStar,__values:__values,__read:__read,__spread:__spread,__await:__await,__asyncGenerator:__asyncGenerator,__asyncDelegator:__asyncDelegator,__asyncValues:__asyncValues,__makeTemplateObject:__makeTemplateObject,__importStar:__importStar,__importDefault:__importDefault});var es6Promise_auto=createCommonjsModule(function(module,exports){ 9 | /*! 10 | * @overview es6-promise - a tiny implementation of Promises/A+. 11 | * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) 12 | * @license Licensed under MIT license 13 | * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE 14 | * @version v4.2.2+97478eb6 15 | */ 16 | (function(global,factory){module.exports=factory()})(commonjsGlobal,function(){function objectOrFunction(x){var type=typeof x;return x!==null&&(type==="object"||type==="function")}function isFunction(x){return typeof x==="function"}var _isArray=void 0;if(Array.isArray){_isArray=Array.isArray}else{_isArray=function(x){return Object.prototype.toString.call(x)==="[object Array]"}}var isArray=_isArray;var len=0;var vertxNext=void 0;var customSchedulerFn=void 0;var asap=function asap(callback,arg){queue[len]=callback;queue[len+1]=arg;len+=2;if(len===2){if(customSchedulerFn){customSchedulerFn(flush)}else{scheduleFlush()}}};function setScheduler(scheduleFn){customSchedulerFn=scheduleFn}function setAsap(asapFn){asap=asapFn}var browserWindow=typeof window!=="undefined"?window:undefined;var browserGlobal=browserWindow||{};var BrowserMutationObserver=browserGlobal.MutationObserver||browserGlobal.WebKitMutationObserver;var isNode=typeof self==="undefined"&&typeof process!=="undefined"&&{}.toString.call(process)==="[object process]";var isWorker=typeof Uint8ClampedArray!=="undefined"&&typeof importScripts!=="undefined"&&typeof MessageChannel!=="undefined";function useNextTick(){return function(){return process.nextTick(flush)}}function useVertxTimer(){if(typeof vertxNext!=="undefined"){return function(){vertxNext(flush)}}return useSetTimeout()}function useMutationObserver(){var iterations=0;var observer=new BrowserMutationObserver(flush);var node=document.createTextNode("");observer.observe(node,{characterData:true});return function(){node.data=iterations=++iterations%2}}function useMessageChannel(){var channel=new MessageChannel;channel.port1.onmessage=flush;return function(){return channel.port2.postMessage(0)}}function useSetTimeout(){var globalSetTimeout=setTimeout;return function(){return globalSetTimeout(flush,1)}}var queue=new Array(1e3);function flush(){for(var i=0;i=200&&xhr.status<300){resolve(new HttpResponse(xhr.status,xhr.statusText,xhr.response||xhr.responseText))}else{reject(new Errors.HttpError(xhr.statusText,xhr.status))}};xhr.onerror=function(){_this.logger.log(ILogger.LogLevel.Warning,"Error from HTTP request. "+xhr.status+": "+xhr.statusText);reject(new Errors.HttpError(xhr.statusText,xhr.status))};xhr.ontimeout=function(){_this.logger.log(ILogger.LogLevel.Warning,"Timeout from HTTP request.");reject(new Errors.TimeoutError)};xhr.send(request.content||"")})};return DefaultHttpClient}(HttpClient);exports.DefaultHttpClient=DefaultHttpClient});unwrapExports(HttpClient_1);var HttpClient_2=HttpClient_1.HttpResponse;var HttpClient_3=HttpClient_1.HttpClient;var HttpClient_4=HttpClient_1.DefaultHttpClient;var TextMessageFormat_1=createCommonjsModule(function(module,exports){Object.defineProperty(exports,"__esModule",{value:true});var TextMessageFormat=function(){function TextMessageFormat(){}TextMessageFormat.write=function(output){return""+output+TextMessageFormat.RecordSeparator};TextMessageFormat.parse=function(input){if(input[input.length-1]!==TextMessageFormat.RecordSeparator){throw new Error("Message is incomplete.")}var messages=input.split(TextMessageFormat.RecordSeparator);messages.pop();return messages};TextMessageFormat.RecordSeparatorCode=30;TextMessageFormat.RecordSeparator=String.fromCharCode(TextMessageFormat.RecordSeparatorCode);return TextMessageFormat}();exports.TextMessageFormat=TextMessageFormat});unwrapExports(TextMessageFormat_1);var TextMessageFormat_2=TextMessageFormat_1.TextMessageFormat;var HandshakeProtocol_1=createCommonjsModule(function(module,exports){Object.defineProperty(exports,"__esModule",{value:true});var HandshakeProtocol=function(){function HandshakeProtocol(){}HandshakeProtocol.prototype.writeHandshakeRequest=function(handshakeRequest){return TextMessageFormat_1.TextMessageFormat.write(JSON.stringify(handshakeRequest))};HandshakeProtocol.prototype.parseHandshakeResponse=function(data){var responseMessage;var messageData;var remainingData;if(data instanceof ArrayBuffer){var binaryData=new Uint8Array(data);var separatorIndex=binaryData.indexOf(TextMessageFormat_1.TextMessageFormat.RecordSeparatorCode);if(separatorIndex===-1){throw new Error("Message is incomplete.")}var responseLength=separatorIndex+1;messageData=String.fromCharCode.apply(null,binaryData.slice(0,responseLength));remainingData=binaryData.byteLength>responseLength?binaryData.slice(responseLength).buffer:null}else{var textData=data;var separatorIndex=textData.indexOf(TextMessageFormat_1.TextMessageFormat.RecordSeparator);if(separatorIndex===-1){throw new Error("Message is incomplete.")}var responseLength=separatorIndex+1;messageData=textData.substring(0,responseLength);remainingData=textData.length>responseLength?textData.substring(responseLength):null}var messages=TextMessageFormat_1.TextMessageFormat.parse(messageData);responseMessage=JSON.parse(messages[0]);return[remainingData,responseMessage]};return HandshakeProtocol}();exports.HandshakeProtocol=HandshakeProtocol});unwrapExports(HandshakeProtocol_1);var HandshakeProtocol_2=HandshakeProtocol_1.HandshakeProtocol;var IHubProtocol=createCommonjsModule(function(module,exports){Object.defineProperty(exports,"__esModule",{value:true});var MessageType;(function(MessageType){MessageType[MessageType["Invocation"]=1]="Invocation";MessageType[MessageType["StreamItem"]=2]="StreamItem";MessageType[MessageType["Completion"]=3]="Completion";MessageType[MessageType["StreamInvocation"]=4]="StreamInvocation";MessageType[MessageType["CancelInvocation"]=5]="CancelInvocation";MessageType[MessageType["Ping"]=6]="Ping";MessageType[MessageType["Close"]=7]="Close"})(MessageType=exports.MessageType||(exports.MessageType={}))});unwrapExports(IHubProtocol);var IHubProtocol_1=IHubProtocol.MessageType;var Loggers=createCommonjsModule(function(module,exports){Object.defineProperty(exports,"__esModule",{value:true});var NullLogger=function(){function NullLogger(){}NullLogger.prototype.log=function(logLevel,message){};NullLogger.instance=new NullLogger;return NullLogger}();exports.NullLogger=NullLogger});unwrapExports(Loggers);var Loggers_1=Loggers.NullLogger;var Utils=createCommonjsModule(function(module,exports){Object.defineProperty(exports,"__esModule",{value:true});var Arg=function(){function Arg(){}Arg.isRequired=function(val,name){if(val===null||val===undefined){throw new Error("The '"+name+"' argument is required.")}};Arg.isIn=function(val,values,name){if(!(val in values)){throw new Error("Unknown "+name+" value: "+val+".")}};return Arg}();exports.Arg=Arg;function getDataDetail(data,includeContent){var length=null;if(data instanceof ArrayBuffer){length="Binary data of length "+data.byteLength;if(includeContent){length+=". Content: '"+formatArrayBuffer(data)+"'"}}else if(typeof data==="string"){length="String data of length "+data.length;if(includeContent){length+=". Content: '"+data+"'."}}return length}exports.getDataDetail=getDataDetail;function formatArrayBuffer(data){var view=new Uint8Array(data);var str="";view.forEach(function(num){var pad=num<16?"0":"";str+="0x"+pad+num.toString(16)+" "});return str.substr(0,str.length-1)}exports.formatArrayBuffer=formatArrayBuffer;function sendMessage(logger,transportName,httpClient,url,accessTokenFactory,content,logMessageContent){return tslib_1.__awaiter(this,void 0,void 0,function(){var headers,token,response,_a;return tslib_1.__generator(this,function(_b){switch(_b.label){case 0:return[4,accessTokenFactory()];case 1:token=_b.sent();if(token){headers=(_a={},_a["Authorization"]="Bearer "+token,_a)}logger.log(ILogger.LogLevel.Trace,"("+transportName+" transport) sending data. "+getDataDetail(content,logMessageContent)+".");return[4,httpClient.post(url,{content:content,headers:headers})];case 2:response=_b.sent();logger.log(ILogger.LogLevel.Trace,"("+transportName+" transport) request complete. Response status: "+response.statusCode+".");return[2]}})})}exports.sendMessage=sendMessage;function createLogger(logger){if(logger===undefined){return new ConsoleLogger(ILogger.LogLevel.Information)}if(logger===null){return Loggers.NullLogger.instance}if(logger.log){return logger}return new ConsoleLogger(logger)}exports.createLogger=createLogger;var Subject=function(){function Subject(cancelCallback){this.observers=[];this.cancelCallback=cancelCallback}Subject.prototype.next=function(item){for(var _i=0,_a=this.observers;_i<_a.length;_i++){var observer=_a[_i];observer.next(item)}};Subject.prototype.error=function(err){for(var _i=0,_a=this.observers;_i<_a.length;_i++){var observer=_a[_i];if(observer.error){observer.error(err)}}};Subject.prototype.complete=function(){for(var _i=0,_a=this.observers;_i<_a.length;_i++){var observer=_a[_i];if(observer.complete){observer.complete()}}};Subject.prototype.subscribe=function(observer){this.observers.push(observer);return new SubjectSubscription(this,observer)};return Subject}();exports.Subject=Subject;var SubjectSubscription=function(){function SubjectSubscription(subject,observer){this.subject=subject;this.observer=observer}SubjectSubscription.prototype.dispose=function(){var index=this.subject.observers.indexOf(this.observer);if(index>-1){this.subject.observers.splice(index,1)}if(this.subject.observers.length===0){this.subject.cancelCallback().catch(function(_){})}};return SubjectSubscription}();exports.SubjectSubscription=SubjectSubscription;var ConsoleLogger=function(){function ConsoleLogger(minimumLogLevel){this.minimumLogLevel=minimumLogLevel}ConsoleLogger.prototype.log=function(logLevel,message){if(logLevel>=this.minimumLogLevel){switch(logLevel){case ILogger.LogLevel.Critical:case ILogger.LogLevel.Error:console.error(ILogger.LogLevel[logLevel]+": "+message);break;case ILogger.LogLevel.Warning:console.warn(ILogger.LogLevel[logLevel]+": "+message);break;case ILogger.LogLevel.Information:console.info(ILogger.LogLevel[logLevel]+": "+message);break;default:console.log(ILogger.LogLevel[logLevel]+": "+message);break}}};return ConsoleLogger}();exports.ConsoleLogger=ConsoleLogger});unwrapExports(Utils);var Utils_1=Utils.Arg;var Utils_2=Utils.getDataDetail;var Utils_3=Utils.formatArrayBuffer;var Utils_4=Utils.sendMessage;var Utils_5=Utils.createLogger;var Utils_6=Utils.Subject;var Utils_7=Utils.SubjectSubscription;var Utils_8=Utils.ConsoleLogger;var HubConnection_1=createCommonjsModule(function(module,exports){Object.defineProperty(exports,"__esModule",{value:true});var DEFAULT_TIMEOUT_IN_MS=30*1e3;var HubConnection=function(){function HubConnection(connection,logger,protocol){var _this=this;Utils.Arg.isRequired(connection,"connection");Utils.Arg.isRequired(logger,"logger");Utils.Arg.isRequired(protocol,"protocol");this.serverTimeoutInMilliseconds=DEFAULT_TIMEOUT_IN_MS;this.logger=logger;this.protocol=protocol;this.connection=connection;this.handshakeProtocol=new HandshakeProtocol_1.HandshakeProtocol;this.connection.onreceive=function(data){return _this.processIncomingData(data)};this.connection.onclose=function(error){return _this.connectionClosed(error)};this.callbacks={};this.methods={};this.closedCallbacks=[];this.id=0}HubConnection.create=function(connection,logger,protocol){return new HubConnection(connection,logger,protocol)};HubConnection.prototype.start=function(){return tslib_1.__awaiter(this,void 0,void 0,function(){var handshakeRequest;return tslib_1.__generator(this,function(_a){switch(_a.label){case 0:handshakeRequest={protocol:this.protocol.name,version:this.protocol.version};this.logger.log(ILogger.LogLevel.Debug,"Starting HubConnection.");this.receivedHandshakeResponse=false;return[4,this.connection.start(this.protocol.transferFormat)];case 1:_a.sent();this.logger.log(ILogger.LogLevel.Debug,"Sending handshake request.");return[4,this.connection.send(this.handshakeProtocol.writeHandshakeRequest(handshakeRequest))];case 2:_a.sent();this.logger.log(ILogger.LogLevel.Information,"Using HubProtocol '"+this.protocol.name+"'.");this.cleanupTimeout();this.configureTimeout();return[2]}})})};HubConnection.prototype.stop=function(){this.logger.log(ILogger.LogLevel.Debug,"Stopping HubConnection.");this.cleanupTimeout();return this.connection.stop()};HubConnection.prototype.stream=function(methodName){var _this=this;var args=[];for(var _i=1;_i"));this.onclose(closeError)}this.logger.log(ILogger.LogLevel.Trace,"(LongPolling transport) Transport finished.");return[7];case 9:return[2]}})})};LongPollingTransport.prototype.send=function(data){return tslib_1.__awaiter(this,void 0,void 0,function(){return tslib_1.__generator(this,function(_a){if(!this.running){return[2,Promise.reject(new Error("Cannot send until the transport is connected"))]}return[2,Utils.sendMessage(this.logger,"LongPolling",this.httpClient,this.url,this.accessTokenFactory,data,this.logMessageContent)]})})};LongPollingTransport.prototype.stop=function(){return tslib_1.__awaiter(this,void 0,void 0,function(){var _this=this;var deleteOptions,token,response;return tslib_1.__generator(this,function(_a){switch(_a.label){case 0:_a.trys.push([0,,3,4]);this.running=false;this.logger.log(ILogger.LogLevel.Trace,"(LongPolling transport) sending DELETE request to "+this.url+".");deleteOptions={headers:{}};return[4,this.accessTokenFactory()];case 1:token=_a.sent();this.updateHeaderToken(deleteOptions,token);return[4,this.httpClient.delete(this.url,deleteOptions)];case 2:response=_a.sent();this.logger.log(ILogger.LogLevel.Trace,"(LongPolling transport) DELETE request accepted.");return[3,4];case 3:if(!this.stopped){this.shutdownTimer=setTimeout(function(){_this.logger.log(ILogger.LogLevel.Warning,"(LongPolling transport) server did not terminate after DELETE request, canceling poll.");_this.pollAbort.abort()},this.shutdownTimeout)}return[7];case 4:return[2]}})})};return LongPollingTransport}();exports.LongPollingTransport=LongPollingTransport});unwrapExports(LongPollingTransport_1);var LongPollingTransport_2=LongPollingTransport_1.LongPollingTransport;var ServerSentEventsTransport_1=createCommonjsModule(function(module,exports){Object.defineProperty(exports,"__esModule",{value:true});var ServerSentEventsTransport=function(){function ServerSentEventsTransport(httpClient,accessTokenFactory,logger,logMessageContent){this.httpClient=httpClient;this.accessTokenFactory=accessTokenFactory||function(){return null};this.logger=logger;this.logMessageContent=logMessageContent}ServerSentEventsTransport.prototype.connect=function(url,transferFormat){return tslib_1.__awaiter(this,void 0,void 0,function(){var _this=this;var token;return tslib_1.__generator(this,function(_a){switch(_a.label){case 0:Utils.Arg.isRequired(url,"url");Utils.Arg.isRequired(transferFormat,"transferFormat");Utils.Arg.isIn(transferFormat,ITransport.TransferFormat,"transferFormat");if(typeof EventSource==="undefined"){throw new Error("'EventSource' is not supported in your environment.")}this.logger.log(ILogger.LogLevel.Trace,"(SSE transport) Connecting");return[4,this.accessTokenFactory()];case 1:token=_a.sent();if(token){url+=(url.indexOf("?")<0?"?":"&")+("access_token="+encodeURIComponent(token))}this.url=url;return[2,new Promise(function(resolve,reject){var opened=false;if(transferFormat!==ITransport.TransferFormat.Text){reject(new Error("The Server-Sent Events transport only supports the 'Text' transfer format"))}var eventSource=new EventSource(url,{withCredentials:true});try{eventSource.onmessage=function(e){if(_this.onreceive){try{_this.logger.log(ILogger.LogLevel.Trace,"(SSE transport) data received. "+Utils.getDataDetail(e.data,_this.logMessageContent)+".");_this.onreceive(e.data)}catch(error){if(_this.onclose){_this.onclose(error)}return}}};eventSource.onerror=function(e){var error=new Error(e.message||"Error occurred");if(opened){_this.close(error)}else{reject(error)}};eventSource.onopen=function(){_this.logger.log(ILogger.LogLevel.Information,"SSE connected to "+_this.url);_this.eventSource=eventSource;opened=true;resolve()}}catch(e){return Promise.reject(e)}})]}})})};ServerSentEventsTransport.prototype.send=function(data){return tslib_1.__awaiter(this,void 0,void 0,function(){return tslib_1.__generator(this,function(_a){if(!this.eventSource){return[2,Promise.reject(new Error("Cannot send until the transport is connected"))]}return[2,Utils.sendMessage(this.logger,"SSE",this.httpClient,this.url,this.accessTokenFactory,data,this.logMessageContent)]})})};ServerSentEventsTransport.prototype.stop=function(){this.close();return Promise.resolve()};ServerSentEventsTransport.prototype.close=function(e){if(this.eventSource){this.eventSource.close();this.eventSource=null;if(this.onclose){this.onclose(e)}}};return ServerSentEventsTransport}();exports.ServerSentEventsTransport=ServerSentEventsTransport});unwrapExports(ServerSentEventsTransport_1);var ServerSentEventsTransport_2=ServerSentEventsTransport_1.ServerSentEventsTransport;var WebSocketTransport_1=createCommonjsModule(function(module,exports){Object.defineProperty(exports,"__esModule",{value:true});var WebSocketTransport=function(){function WebSocketTransport(accessTokenFactory,logger,logMessageContent){this.logger=logger;this.accessTokenFactory=accessTokenFactory||function(){return null};this.logMessageContent=logMessageContent}WebSocketTransport.prototype.connect=function(url,transferFormat){return tslib_1.__awaiter(this,void 0,void 0,function(){var _this=this;var token;return tslib_1.__generator(this,function(_a){switch(_a.label){case 0:Utils.Arg.isRequired(url,"url");Utils.Arg.isRequired(transferFormat,"transferFormat");Utils.Arg.isIn(transferFormat,ITransport.TransferFormat,"transferFormat");if(typeof WebSocket==="undefined"){throw new Error("'WebSocket' is not supported in your environment.")}this.logger.log(ILogger.LogLevel.Trace,"(WebSockets transport) Connecting");return[4,this.accessTokenFactory()];case 1:token=_a.sent();if(token){url+=(url.indexOf("?")<0?"?":"&")+("access_token="+encodeURIComponent(token))}return[2,new Promise(function(resolve,reject){url=url.replace(/^http/,"ws");var webSocket=new WebSocket(url);if(transferFormat===ITransport.TransferFormat.Binary){webSocket.binaryType="arraybuffer"}webSocket.onopen=function(event){_this.logger.log(ILogger.LogLevel.Information,"WebSocket connected to "+url);_this.webSocket=webSocket;resolve()};webSocket.onerror=function(event){reject(event.error)};webSocket.onmessage=function(message){_this.logger.log(ILogger.LogLevel.Trace,"(WebSockets transport) data received. "+Utils.getDataDetail(message.data,_this.logMessageContent)+".");if(_this.onreceive){_this.onreceive(message.data)}};webSocket.onclose=function(event){_this.logger.log(ILogger.LogLevel.Trace,"(WebSockets transport) socket closed.");if(_this.onclose){if(event.wasClean===false||event.code!==1e3){_this.onclose(new Error("Websocket closed with status code: "+event.code+" ("+event.reason+")"))}else{_this.onclose()}}}})]}})})};WebSocketTransport.prototype.send=function(data){if(this.webSocket&&this.webSocket.readyState===WebSocket.OPEN){this.logger.log(ILogger.LogLevel.Trace,"(WebSockets transport) sending data. "+Utils.getDataDetail(data,this.logMessageContent)+".");this.webSocket.send(data);return Promise.resolve()}return Promise.reject("WebSocket is not in the OPEN state")};WebSocketTransport.prototype.stop=function(){if(this.webSocket){this.webSocket.close();this.webSocket=null}return Promise.resolve()};return WebSocketTransport}();exports.WebSocketTransport=WebSocketTransport});unwrapExports(WebSocketTransport_1);var WebSocketTransport_2=WebSocketTransport_1.WebSocketTransport;var HttpConnection_1=createCommonjsModule(function(module,exports){Object.defineProperty(exports,"__esModule",{value:true});var MAX_REDIRECTS=100;var HttpConnection=function(){function HttpConnection(url,options){if(options===void 0){options={}}this.features={};Utils.Arg.isRequired(url,"url");this.logger=Utils.createLogger(options.logger);this.baseUrl=this.resolveUrl(url);options=options||{};options.accessTokenFactory=options.accessTokenFactory||function(){return null};options.logMessageContent=options.logMessageContent||false;this.httpClient=options.httpClient||new HttpClient_1.DefaultHttpClient(this.logger);this.connectionState=2;this.options=options}HttpConnection.prototype.start=function(transferFormat){transferFormat=transferFormat||ITransport.TransferFormat.Binary;Utils.Arg.isIn(transferFormat,ITransport.TransferFormat,"transferFormat");this.logger.log(ILogger.LogLevel.Debug,"Starting connection with transfer format '"+ITransport.TransferFormat[transferFormat]+"'.");if(this.connectionState!==2){return Promise.reject(new Error("Cannot start a connection that is not in the 'Disconnected' state."))}this.connectionState=0;this.startPromise=this.startInternal(transferFormat);return this.startPromise};HttpConnection.prototype.send=function(data){if(this.connectionState!==1){throw new Error("Cannot send data if the connection is not in the 'Connected' State.")}return this.transport.send(data)};HttpConnection.prototype.stop=function(error){return tslib_1.__awaiter(this,void 0,void 0,function(){var e_1;return tslib_1.__generator(this,function(_a){switch(_a.label){case 0:this.connectionState=2;_a.label=1;case 1:_a.trys.push([1,3,,4]);return[4,this.startPromise];case 2:_a.sent();return[3,4];case 3:e_1=_a.sent();return[3,4];case 4:if(!this.transport)return[3,6];this.stopError=error;return[4,this.transport.stop()];case 5:_a.sent();this.transport=null;_a.label=6;case 6:return[2]}})})};HttpConnection.prototype.startInternal=function(transferFormat){return tslib_1.__awaiter(this,void 0,void 0,function(){var _this=this;var url,negotiateResponse,redirects,_loop_1,this_1,state_1,e_2;return tslib_1.__generator(this,function(_a){switch(_a.label){case 0:url=this.baseUrl;this.accessTokenFactory=this.options.accessTokenFactory;_a.label=1;case 1:_a.trys.push([1,12,,13]);if(!this.options.skipNegotiation)return[3,5];if(!(this.options.transport===ITransport.HttpTransportType.WebSockets))return[3,3];this.transport=this.constructTransport(ITransport.HttpTransportType.WebSockets);return[4,this.transport.connect(url,transferFormat)];case 2:_a.sent();return[3,4];case 3:throw Error("Negotiation can only be skipped when using the WebSocket transport directly.");case 4:return[3,11];case 5:negotiateResponse=null;redirects=0;_loop_1=function(){var accessToken_1;return tslib_1.__generator(this,function(_a){switch(_a.label){case 0:return[4,this_1.getNegotiationResponse(url)];case 1:negotiateResponse=_a.sent();if(this_1.connectionState===2){return[2,{value:void 0}]}if(negotiateResponse.url){url=negotiateResponse.url}if(negotiateResponse.accessToken){accessToken_1=negotiateResponse.accessToken;this_1.accessTokenFactory=function(){return accessToken_1}}redirects++;return[2]}})};this_1=this;_a.label=6;case 6:return[5,_loop_1()];case 7:state_1=_a.sent();if(typeof state_1==="object")return[2,state_1.value];_a.label=8;case 8:if(negotiateResponse.url&&redirects=0){if(transport===ITransport.HttpTransportType.WebSockets&&typeof WebSocket==="undefined"||transport===ITransport.HttpTransportType.ServerSentEvents&&typeof EventSource==="undefined"){this.logger.log(ILogger.LogLevel.Debug,"Skipping transport '"+ITransport.HttpTransportType[transport]+"' because it is not supported in your environment.'")}else{this.logger.log(ILogger.LogLevel.Debug,"Selecting transport '"+ITransport.HttpTransportType[transport]+"'");return transport}}else{this.logger.log(ILogger.LogLevel.Debug,"Skipping transport '"+ITransport.HttpTransportType[transport]+"' because it does not support the requested transfer format '"+ITransport.TransferFormat[requestedTransferFormat]+"'.")}}else{this.logger.log(ILogger.LogLevel.Debug,"Skipping transport '"+ITransport.HttpTransportType[transport]+"' because it was disabled by the client.")}}return null};HttpConnection.prototype.isITransport=function(transport){return transport&&typeof transport==="object"&&"connect"in transport};HttpConnection.prototype.changeState=function(from,to){if(this.connectionState===from){this.connectionState=to;return true}return false};HttpConnection.prototype.stopConnection=function(error){return tslib_1.__awaiter(this,void 0,void 0,function(){return tslib_1.__generator(this,function(_a){this.transport=null;error=this.stopError||error;if(error){this.logger.log(ILogger.LogLevel.Error,"Connection disconnected with error '"+error+"'.")}else{this.logger.log(ILogger.LogLevel.Information,"Connection disconnected.")}this.connectionState=2;if(this.onclose){this.onclose(error)}return[2]})})};HttpConnection.prototype.resolveUrl=function(url){if(url.lastIndexOf("https://",0)===0||url.lastIndexOf("http://",0)===0){return url}if(typeof window==="undefined"||!window||!window.document){throw new Error("Cannot resolve '"+url+"'.")}var aTag=window.document.createElement("a");aTag.href=url;this.logger.log(ILogger.LogLevel.Information,"Normalizing '"+url+"' to '"+aTag.href+"'.");return aTag.href};HttpConnection.prototype.resolveNegotiateUrl=function(url){var index=url.indexOf("?");var negotiateUrl=url.substring(0,index===-1?url.length:index);if(negotiateUrl[negotiateUrl.length-1]!=="/"){negotiateUrl+="/"}negotiateUrl+="negotiate";negotiateUrl+=index===-1?"":url.substring(index);return negotiateUrl};return HttpConnection}();exports.HttpConnection=HttpConnection;function transportMatches(requestedTransport,actualTransport){return!requestedTransport||(actualTransport&requestedTransport)!==0}});unwrapExports(HttpConnection_1);var HttpConnection_2=HttpConnection_1.HttpConnection;var JsonHubProtocol_1=createCommonjsModule(function(module,exports){Object.defineProperty(exports,"__esModule",{value:true});var JSON_HUB_PROTOCOL_NAME="json";var JsonHubProtocol=function(){function JsonHubProtocol(){this.name=JSON_HUB_PROTOCOL_NAME;this.version=1;this.transferFormat=ITransport.TransferFormat.Text}JsonHubProtocol.prototype.parseMessages=function(input,logger){if(typeof input!=="string"){throw new Error("Invalid input for JSON hub protocol. Expected a string.")}if(!input){return[]}if(logger===null){logger=Loggers.NullLogger.instance}var messages=TextMessageFormat_1.TextMessageFormat.parse(input);var hubMessages=[];for(var _i=0,messages_1=messages;_i