mirror of
https://github.com/aspnet/JavaScriptServices.git
synced 2025-12-23 10:08:57 +00:00
Compare commits
177 Commits
karma-test
...
v1.0.x
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd42deef7e | ||
|
|
939e0aeee0 | ||
|
|
28b8136fa6 | ||
|
|
3ff4447924 | ||
|
|
3b91ad9b39 | ||
|
|
bebf24952e | ||
|
|
834301e50d | ||
|
|
03774253eb | ||
|
|
a3cba50e88 | ||
|
|
9cfea61f1e | ||
|
|
157b74a0cd | ||
|
|
17f9ecec29 | ||
|
|
9f6b0b0573 | ||
|
|
dd97ae7316 | ||
|
|
ea2cfc277c | ||
|
|
fadb2b3127 | ||
|
|
69a0a29057 | ||
|
|
8401bbf33a | ||
|
|
e3a4fad951 | ||
|
|
3a4936dbf7 | ||
|
|
bbbcb5ef18 | ||
|
|
d6c6408457 | ||
|
|
9b048c54d4 | ||
|
|
cdd6c16dc6 | ||
|
|
4f15bd6c50 | ||
|
|
828ed07cef | ||
|
|
a734a31745 | ||
|
|
ea81671828 | ||
|
|
b3dbb6e0f1 | ||
|
|
11c45321aa | ||
|
|
fadcb586c6 | ||
|
|
2c97326721 | ||
|
|
1b4dd93fa6 | ||
|
|
7ee8a7b15e | ||
|
|
64903fe0c6 | ||
|
|
077f91847a | ||
|
|
7ee3346a72 | ||
|
|
f9145a43f6 | ||
|
|
da51cd588b | ||
|
|
54f222e88f | ||
|
|
6259b7b938 | ||
|
|
dfcaae6fda | ||
|
|
4b507004b1 | ||
|
|
bd86026bb9 | ||
|
|
996216c751 | ||
|
|
6bceb234d8 | ||
|
|
acfb253a40 | ||
|
|
3087352ea1 | ||
|
|
e60ea04f86 | ||
|
|
867e60d7fd | ||
|
|
8cf116bca8 | ||
|
|
3dc9ac979c | ||
|
|
bf71e3e71c | ||
|
|
c140b5014a | ||
|
|
de9460fba5 | ||
|
|
d858c09b7b | ||
|
|
ca6acc807d | ||
|
|
8285bb0c74 | ||
|
|
75abf1a2ab | ||
|
|
a427d5f0f0 | ||
|
|
e0c18ab269 | ||
|
|
f20ad391b6 | ||
|
|
496338ccca | ||
|
|
0615578d9a | ||
|
|
8c766c0382 | ||
|
|
85b8f033da | ||
|
|
6f44227917 | ||
|
|
3760d3724d | ||
|
|
99bf212cce | ||
|
|
418255e148 | ||
|
|
f6d7321243 | ||
|
|
a7ed0112db | ||
|
|
f26068b62b | ||
|
|
1543595c01 | ||
|
|
3d77a21bc6 | ||
|
|
ae0ffd4d11 | ||
|
|
0289f73a96 | ||
|
|
6a9b7accce | ||
|
|
a6d959b783 | ||
|
|
30a694450c | ||
|
|
d20a72b812 | ||
|
|
24773c8aa4 | ||
|
|
6c645879a8 | ||
|
|
d5055dbaf3 | ||
|
|
3568476cca | ||
|
|
93779a5e46 | ||
|
|
4fc1d60d67 | ||
|
|
1d76284e25 | ||
|
|
c33b227331 | ||
|
|
02315b41c0 | ||
|
|
4e291130a0 | ||
|
|
7f257e86e3 | ||
|
|
5c0505440d | ||
|
|
f13c2595b8 | ||
|
|
bc42e598f9 | ||
|
|
a0ebab1f28 | ||
|
|
ff396377b9 | ||
|
|
81d96766ee | ||
|
|
17801a3c16 | ||
|
|
0234b44355 | ||
|
|
18e8b7101c | ||
|
|
6126c4d480 | ||
|
|
53889c0fc1 | ||
|
|
5f070daac8 | ||
|
|
3270e28b3d | ||
|
|
42e88f7fc4 | ||
|
|
8968a24041 | ||
|
|
0a961a7bd0 | ||
|
|
a9ce762827 | ||
|
|
0d34dba4fd | ||
|
|
808592d3a0 | ||
|
|
d1228dc26a | ||
|
|
09b4135217 | ||
|
|
9bd9444485 | ||
|
|
4937fef28f | ||
|
|
e87aa1f088 | ||
|
|
30dfe5e8b5 | ||
|
|
46966322b7 | ||
|
|
adf4732191 | ||
|
|
7b227229b3 | ||
|
|
2241c55a90 | ||
|
|
85eba9ca27 | ||
|
|
46906e4ea8 | ||
|
|
57265509f7 | ||
|
|
7e88903bcc | ||
|
|
67fc64309f | ||
|
|
5a9d3cb189 | ||
|
|
f79936c104 | ||
|
|
e8594287db | ||
|
|
b55e444a55 | ||
|
|
9aaa519044 | ||
|
|
f9807c546d | ||
|
|
232e908ce8 | ||
|
|
5214a553a7 | ||
|
|
2ba5a0ac93 | ||
|
|
925f47fece | ||
|
|
80343e9f17 | ||
|
|
f7ef36bc74 | ||
|
|
50be444440 | ||
|
|
19684f2b7d | ||
|
|
cd18489f00 | ||
|
|
41f1f6fe82 | ||
|
|
ca99a2304c | ||
|
|
83cfb59c2d | ||
|
|
494c7b585c | ||
|
|
49a8536679 | ||
|
|
358ee2261e | ||
|
|
07a9c1685f | ||
|
|
4ea7eb195e | ||
|
|
85dfdd9b50 | ||
|
|
a91b6a6b5c | ||
|
|
a1c1bdb1e6 | ||
|
|
297b4dbd92 | ||
|
|
8f550c5706 | ||
|
|
243a9b4ef6 | ||
|
|
1e08548aa0 | ||
|
|
ce0d2089d2 | ||
|
|
b71d139eb5 | ||
|
|
2ee0078cfd | ||
|
|
591d548de7 | ||
|
|
06ad36f830 | ||
|
|
7a80d905b8 | ||
|
|
d76b013a56 | ||
|
|
7c316d5c74 | ||
|
|
b72435c5cc | ||
|
|
7f841ff840 | ||
|
|
80f740a9ed | ||
|
|
f071590fce | ||
|
|
bc2de2ad59 | ||
|
|
605090e909 | ||
|
|
67f7e7450f | ||
|
|
da662c55fa | ||
|
|
b4bec30b0f | ||
|
|
28550784ed | ||
|
|
1be9102aea | ||
|
|
c2c45b04df | ||
|
|
874575ba92 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -36,4 +36,6 @@ npm-debug.log
|
||||
# repo have to be excluded here.
|
||||
/templates/*/node_modules/
|
||||
/templates/*/wwwroot/dist/
|
||||
/templates/*/ClientApp/dist/
|
||||
/templates/*/yarn.lock
|
||||
.vscode/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25123.0
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{E6E88944-4800-40BA-8AF5-069EA3ADFEB8}"
|
||||
EndProject
|
||||
@@ -46,6 +46,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MusicStore", "samples\react
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Angular", "Angular", "{4867A616-83D6-48DC-964D-6AE743596631}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Aurelia", "templates\AureliaSpa\Aurelia.xproj", "{33D8DAD9-74F9-471D-8BAD-55F828FAA736}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "KnockoutSpa", "templates\KnockoutSpa\KnockoutSpa.xproj", "{85231B41-6998-49AE-ABD2-5124C83DBEF2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -108,6 +112,14 @@ Global
|
||||
{C870A92C-9E3F-4BF2-82B8-5758545A8B7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C870A92C-9E3F-4BF2-82B8-5758545A8B7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C870A92C-9E3F-4BF2-82B8-5758545A8B7C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{33D8DAD9-74F9-471D-8BAD-55F828FAA736}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{33D8DAD9-74F9-471D-8BAD-55F828FAA736}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{33D8DAD9-74F9-471D-8BAD-55F828FAA736}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{33D8DAD9-74F9-471D-8BAD-55F828FAA736}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{85231B41-6998-49AE-ABD2-5124C83DBEF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{85231B41-6998-49AE-ABD2-5124C83DBEF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{85231B41-6998-49AE-ABD2-5124C83DBEF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{85231B41-6998-49AE-ABD2-5124C83DBEF2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -126,5 +138,7 @@ Global
|
||||
{E0EBA813-4478-4C02-B11D-FB3793113FE4} = {E6E88944-4800-40BA-8AF5-069EA3ADFEB8}
|
||||
{C870A92C-9E3F-4BF2-82B8-5758545A8B7C} = {E0EBA813-4478-4C02-B11D-FB3793113FE4}
|
||||
{4867A616-83D6-48DC-964D-6AE743596631} = {E6E88944-4800-40BA-8AF5-069EA3ADFEB8}
|
||||
{33D8DAD9-74F9-471D-8BAD-55F828FAA736} = {727E6D58-6830-4792-96C6-E138A33959FB}
|
||||
{85231B41-6998-49AE-ABD2-5124C83DBEF2} = {727E6D58-6830-4792-96C6-E138A33959FB}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -20,7 +20,7 @@ This repo contains:
|
||||
* A Yeoman generator that creates preconfigured app starting points ([guide](http://blog.stevensanderson.com/2016/05/02/angular2-react-knockout-apps-on-aspnet-core/))
|
||||
* Samples and docs
|
||||
|
||||
Everything here is cross-platform, and works with .NET Core 1.0 (RTM) or later on Windows, Linux, or OS X.
|
||||
Everything here is cross-platform, and works with .NET Core 1.0.1 or later on Windows, Linux, or OS X.
|
||||
|
||||
## Creating new applications
|
||||
|
||||
@@ -69,8 +69,9 @@ Also in this repo, [the `samples` directory](https://github.com/aspnet/JavaScrip
|
||||
**To run the samples:**
|
||||
|
||||
* Clone this repo
|
||||
* Change directory to the same you want to run (e.g., `cd samples/angular/MusicStore`)
|
||||
* Restore dependencies (run `dotnet restore` and `npm install`).
|
||||
* At the repo's root directory (the one containing `src`, `samples`, etc.), run `dotnet restore`
|
||||
* Change directory to the sample you want to run (e.g., `cd samples/angular/MusicStore`)
|
||||
* Restore Node dependencies by running `npm install`
|
||||
* If you're trying to run the Angular 2 "Music Store" sample, then also run `gulp` (which you need to have installed globally). None of the other samples require this.
|
||||
* Run the application (`dotnet run`)
|
||||
* Browse to [http://localhost:5000](http://localhost:5000)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
var VERSION='0.1'
|
||||
var FULL_VERSION='0.1'
|
||||
var AUTHORS='Microsoft Open Technologies, Inc.'
|
||||
var SAMPLES_PROJECT_GLOB='templates/*/project.json'
|
||||
|
||||
use-standard-lifecycle
|
||||
k-standard-goals
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace MusicStore
|
||||
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IHostingEnvironment env)
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
|
||||
|
||||
// Initialize the sample data
|
||||
SampleData.InitializeMusicStoreDatabaseAsync(app.ApplicationServices).Wait();
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
"angular2": "2.0.0-beta.15",
|
||||
"angular2-aspnet": "^0.0.6",
|
||||
"angular2-universal": "0.98.1",
|
||||
"angular2-express-engine": "0.11.1",
|
||||
"angular2-hapi-engine": "0.11.1",
|
||||
"aspnet-prerendering": "^1.0.1",
|
||||
"bootstrap": "^3.3.5",
|
||||
"css": "^2.2.1",
|
||||
|
||||
@@ -5,52 +5,75 @@
|
||||
"preserveCompilationContext": true
|
||||
},
|
||||
"runtimeOptions": {
|
||||
"gcServer": true
|
||||
"configProperties": {
|
||||
"System.GC.Server": true
|
||||
}
|
||||
},
|
||||
"tooling": {
|
||||
"defaultNamespace": "MusicStore"
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.AngularServices": "1.0.0-*",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.1",
|
||||
"Microsoft.AspNetCore.Razor.Tools": {
|
||||
"version": "1.0.0-preview2-final",
|
||||
"type": "build"
|
||||
},
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Microsoft.EntityFrameworkCore.SQLite": "1.0.0",
|
||||
"Microsoft.AspNetCore.AngularServices": "1.0.0-*",
|
||||
"AutoMapper": "5.0.2"
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.0.0",
|
||||
"Microsoft.Extensions.Logging": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
|
||||
"AutoMapper": "5.0.2"
|
||||
},
|
||||
|
||||
"tools": {
|
||||
"Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final",
|
||||
"Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"publishOptions": {
|
||||
"exclude": [
|
||||
"include": [
|
||||
"appsettings.json",
|
||||
"ClientApp",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"**.xproj",
|
||||
"**.user",
|
||||
"**.vspscc"
|
||||
"typings",
|
||||
"Views",
|
||||
"tsconfig.json",
|
||||
"tsd.json",
|
||||
"web.config",
|
||||
"webpack.*.js",
|
||||
"wwwroot"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"prepublish": [ "npm install" ],
|
||||
"prepublish": [
|
||||
"npm install",
|
||||
"gulp"
|
||||
],
|
||||
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,8 @@ namespace Webpack.ActionResults
|
||||
_moduleExport,
|
||||
request.GetEncodedUrl(),
|
||||
request.Path + request.QueryString.Value,
|
||||
_dataToSupply
|
||||
_dataToSupply,
|
||||
/* timeoutMilliseconds */ 30000
|
||||
);
|
||||
|
||||
response.ContentType = "text/html";
|
||||
|
||||
@@ -2,7 +2,7 @@ module.exports = {
|
||||
devtool: 'inline-source-map',
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.less$/, loader: 'style!css!less' }
|
||||
{ test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@ var extractLESS = new ExtractTextPlugin('my-styles.css');
|
||||
module.exports = {
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.less$/, loader: extractLESS.extract(['css', 'less']) },
|
||||
{ test: /\.less$/, loader: extractLESS.extract(['css-loader', 'less-loader']) },
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
|
||||
1
samples/react/MusicStore/.gitignore
vendored
1
samples/react/MusicStore/.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
music-db.sqlite
|
||||
/wwwroot/dist/
|
||||
/node_modules/
|
||||
yarn.lock
|
||||
|
||||
@@ -5,19 +5,29 @@ import { match, RouterContext } from 'react-router';
|
||||
import createMemoryHistory from 'history/lib/createMemoryHistory';
|
||||
import { routes } from './routes';
|
||||
import configureStore from './configureStore';
|
||||
React;
|
||||
type BootResult = { html?: string, globals?: { [key: string]: any }, redirectUrl?: string};
|
||||
|
||||
export default function (params: any): Promise<{ html: string }> {
|
||||
return new Promise<{ html: string, globals: { [key: string]: any } }>((resolve, reject) => {
|
||||
return new Promise<BootResult>((resolve, reject) => {
|
||||
// Match the incoming request against the list of client-side routes
|
||||
match({ routes, location: params.location }, (error, redirectLocation, renderProps: any) => {
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
// If there's a redirection, just send this information back to the host application
|
||||
if (redirectLocation) {
|
||||
resolve({ redirectUrl: redirectLocation.pathname });
|
||||
return;
|
||||
}
|
||||
|
||||
// If it didn't match any route, renderProps will be undefined
|
||||
if (!renderProps) {
|
||||
throw new Error(`The location '${ params.url }' doesn't match any route configured in react-router.`);
|
||||
}
|
||||
|
||||
// Build an instance of the application
|
||||
const history = createMemoryHistory(params.url);
|
||||
const store = configureStore(history);
|
||||
const store = configureStore();
|
||||
const app = (
|
||||
<Provider store={ store }>
|
||||
<RouterContext {...renderProps} />
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
import './styles/styles.css';
|
||||
import 'bootstrap/dist/css/bootstrap.css';
|
||||
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import { browserHistory, Router } from 'react-router';
|
||||
import { Provider } from 'react-redux';
|
||||
React; // Need this reference otherwise TypeScript doesn't think we're using it and ignores the import
|
||||
|
||||
import './styles/styles.css';
|
||||
import 'bootstrap/dist/css/bootstrap.css';
|
||||
import configureStore from './configureStore';
|
||||
import { syncHistoryWithStore } from 'react-router-redux';
|
||||
import { routes } from './routes';
|
||||
import configureStore from './configureStore';
|
||||
import { ApplicationState } from './store';
|
||||
|
||||
// Get the application-wide store instance, prepopulating with state from the server where available.
|
||||
const initialState = (window as any).initialReduxState as ApplicationState;
|
||||
const store = configureStore(browserHistory, initialState);
|
||||
const store = configureStore(initialState);
|
||||
const history = syncHistoryWithStore(browserHistory, store);
|
||||
|
||||
// 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.
|
||||
ReactDOM.render(
|
||||
<Provider store={ store }>
|
||||
<Router history={ browserHistory } children={ routes } />
|
||||
<Router history={ history } children={ routes } />
|
||||
</Provider>,
|
||||
document.getElementById('react-app')
|
||||
);
|
||||
|
||||
@@ -1,28 +1,22 @@
|
||||
import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
|
||||
import * as thunkModule from 'redux-thunk';
|
||||
import { syncHistory, routeReducer } from 'react-router-redux';
|
||||
import { createStore, applyMiddleware, compose, combineReducers, GenericStoreEnhancer } from 'redux';
|
||||
import thunk from 'redux-thunk';
|
||||
import { routerReducer } from 'react-router-redux';
|
||||
import * as Store from './store';
|
||||
import { typedToPlain } from 'redux-typed';
|
||||
|
||||
export default function configureStore(history: HistoryModule.History, initialState?: Store.ApplicationState) {
|
||||
// Build middleware
|
||||
const thunk = (thunkModule as any).default; // Workaround for TypeScript not importing thunk module as expected
|
||||
const reduxRouterMiddleware = syncHistory(history);
|
||||
const middlewares = [thunk, reduxRouterMiddleware, typedToPlain];
|
||||
const devToolsExtension = null;//(window as any).devToolsExtension; // If devTools is installed, connect to it
|
||||
|
||||
const finalCreateStore = compose(
|
||||
applyMiddleware(...middlewares),
|
||||
export default function configureStore(initialState?: Store.ApplicationState) {
|
||||
// Build middleware. These are functions that can process the actions before they reach the store.
|
||||
const windowIfDefined = typeof window === 'undefined' ? null : window as any;
|
||||
// If devTools is installed, connect to it
|
||||
const devToolsExtension = windowIfDefined && windowIfDefined.devToolsExtension as () => GenericStoreEnhancer;
|
||||
const createStoreWithMiddleware = compose(
|
||||
applyMiddleware(thunk, typedToPlain),
|
||||
devToolsExtension ? devToolsExtension() : f => f
|
||||
)(createStore)
|
||||
)(createStore);
|
||||
|
||||
// Combine all reducers
|
||||
// Combine all reducers and instantiate the app-wide store instance
|
||||
const allReducers = buildRootReducer(Store.reducers);
|
||||
|
||||
const store = finalCreateStore(allReducers, initialState) as Redux.Store;
|
||||
|
||||
// Required for replaying actions from devtools to work
|
||||
reduxRouterMiddleware.listenForReplays(store);
|
||||
const store = createStoreWithMiddleware(allReducers, initialState) as Redux.Store<Store.ApplicationState>;
|
||||
|
||||
// Enable Webpack hot module replacement for reducers
|
||||
if (module.hot) {
|
||||
@@ -36,5 +30,5 @@ export default function configureStore(history: HistoryModule.History, initialSt
|
||||
}
|
||||
|
||||
function buildRootReducer(allReducers) {
|
||||
return combineReducers(Object.assign({}, allReducers, { routing: routeReducer })) as Redux.Reducer;
|
||||
return combineReducers<Store.ApplicationState>(Object.assign({}, allReducers, { routing: routerReducer }));
|
||||
}
|
||||
|
||||
@@ -1,45 +1,52 @@
|
||||
{
|
||||
"name": "MusicStore",
|
||||
"name": "music-store",
|
||||
"version": "0.0.0",
|
||||
"devDependencies": {
|
||||
"babel-loader": "^6.2.1",
|
||||
"babel-plugin-react-transform": "^2.0.0",
|
||||
"babel-preset-es2015": "^6.3.13",
|
||||
"babel-preset-react": "^6.3.13",
|
||||
"dependencies": {
|
||||
"@types/react": "^0.14.29",
|
||||
"@types/react-bootstrap": "^0.0.35",
|
||||
"@types/react-dom": "^0.14.14",
|
||||
"@types/react-redux": "^4.4.29",
|
||||
"@types/react-router": "^2.0.30",
|
||||
"@types/react-router-bootstrap": "^0.0.27",
|
||||
"@types/react-router-redux": "^4.0.30",
|
||||
"@types/redux": "3.5.27",
|
||||
"@types/redux-thunk": "^2.1.28",
|
||||
"@types/source-map": "^0.1.28",
|
||||
"@types/uglify-js": "^2.0.27",
|
||||
"@types/webpack": "^1.12.35",
|
||||
"@types/webpack-env": "^1.12.1",
|
||||
"@types/whatwg-fetch": "0.0.28",
|
||||
"aspnet-prerendering": "^1.0.7",
|
||||
"aspnet-webpack": "^1.0.17",
|
||||
"aspnet-webpack-react": "^1.0.2",
|
||||
"babel-core": "^6.5.2",
|
||||
"babel-loader": "^6.2.3",
|
||||
"babel-preset-es2015": "^6.5.0",
|
||||
"babel-preset-react": "^6.5.0",
|
||||
"bootstrap": "^3.3.6",
|
||||
"css-loader": "^0.23.1",
|
||||
"express": "^4.13.4",
|
||||
"domain-task": "^2.0.1",
|
||||
"event-source-polyfill": "^0.0.7",
|
||||
"extract-text-webpack-plugin": "^1.0.1",
|
||||
"file-loader": "^0.8.5",
|
||||
"react-transform-hmr": "^1.0.2",
|
||||
"jquery": "^2.2.1",
|
||||
"react": "^15.3.2",
|
||||
"react-bootstrap": "^0.30.6",
|
||||
"react-dom": "^15.3.2",
|
||||
"react-redux": "^4.4.5",
|
||||
"react-router": "^2.8.1",
|
||||
"react-router-bootstrap": "^0.23.1",
|
||||
"react-router-redux": "^4.0.6",
|
||||
"redux": "^3.6.0",
|
||||
"redux-thunk": "^2.1.0",
|
||||
"redux-typed": "^2.0.0",
|
||||
"style-loader": "^0.13.0",
|
||||
"ts-loader": "^0.8.0",
|
||||
"typescript": "^1.7.5",
|
||||
"ts-loader": "^0.8.1",
|
||||
"typescript": "2.0.3",
|
||||
"url-loader": "^0.5.7",
|
||||
"webpack": "^1.12.12",
|
||||
"webpack-dev-middleware": "^1.5.1",
|
||||
"webpack-hot-middleware": "^2.6.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"aspnet-prerendering": "^1.0.0",
|
||||
"aspnet-webpack": "^1.0.3",
|
||||
"aspnet-webpack-react": "^1.0.1",
|
||||
"bootstrap": "^3.3.6",
|
||||
"domain-context": "^0.5.1",
|
||||
"domain-task": "^2.0.0",
|
||||
"history": "^2.0.0",
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
"memory-fs": "^0.3.0",
|
||||
"react": "^0.14.7",
|
||||
"react-bootstrap": "^0.28.2",
|
||||
"react-dom": "^0.14.7",
|
||||
"react-redux": "^4.2.1",
|
||||
"react-router": "^2.0.0-rc5",
|
||||
"react-router-bootstrap": "^0.20.1",
|
||||
"react-router-redux": "^2.1.0",
|
||||
"redux": "^3.2.1",
|
||||
"redux-thunk": "^1.0.3",
|
||||
"redux-typed": "^1.0.0",
|
||||
"require-from-string": "^1.1.0",
|
||||
"webpack-externals-plugin": "^1.0.0"
|
||||
"webpack": "^1.13.2",
|
||||
"webpack-hot-middleware": "^2.12.2",
|
||||
"webpack-merge": "^0.14.1",
|
||||
"webpack-node-externals": "^1.4.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +1,83 @@
|
||||
{
|
||||
"version": "1.0.0-*",
|
||||
"buildOptions": {
|
||||
"emitEntryPoint": true,
|
||||
"preserveCompilationContext": true
|
||||
},
|
||||
"runtimeOptions": {
|
||||
"gcServer": true
|
||||
},
|
||||
"tooling": {
|
||||
"defaultNamespace": "MusicStore"
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.ReactServices": "1.0.0-*",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.1",
|
||||
"Microsoft.AspNetCore.Razor.Tools": {
|
||||
"version": "1.0.0-preview2-final",
|
||||
"type": "build"
|
||||
},
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.NETCore.Platforms": "1.0.1",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Microsoft.EntityFrameworkCore.SQLite": "1.0.0",
|
||||
"Microsoft.AspNetCore.ReactServices": "1.0.0-*",
|
||||
"AutoMapper": "5.0.2"
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.0.0",
|
||||
"Microsoft.Extensions.Logging": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.0.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
|
||||
"AutoMapper": "5.0.2"
|
||||
},
|
||||
|
||||
"tools": {
|
||||
"Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final",
|
||||
"Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"buildOptions": {
|
||||
"emitEntryPoint": true,
|
||||
"preserveCompilationContext": true,
|
||||
"compile": {
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
},
|
||||
|
||||
"runtimeOptions": {
|
||||
"configProperties": {
|
||||
"System.GC.Server": true
|
||||
}
|
||||
},
|
||||
|
||||
"publishOptions": {
|
||||
"exclude": [
|
||||
"include": [
|
||||
"appsettings.json",
|
||||
"ClientApp/dist",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"**.xproj",
|
||||
"**.user",
|
||||
"**.vspscc"
|
||||
"Views",
|
||||
"web.config",
|
||||
"wwwroot"
|
||||
],
|
||||
"exclude": [
|
||||
"wwwroot/dist/*.map"
|
||||
]
|
||||
},
|
||||
|
||||
"scripts": {
|
||||
"prepublish": [ "npm install" ],
|
||||
"prepublish": [
|
||||
"npm install",
|
||||
"node node_modules/webpack/bin/webpack.js"
|
||||
],
|
||||
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
|
||||
},
|
||||
|
||||
"tooling": {
|
||||
"defaultNamespace": "MusicStore"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"target": "es6",
|
||||
"jsx": "preserve",
|
||||
"sourceMap": true,
|
||||
"experimentalDecorators": true
|
||||
"experimentalDecorators": true,
|
||||
"types": [ "webpack-env", "whatwg-fetch" ]
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"version": "v4",
|
||||
"repo": "borisyankov/DefinitelyTyped",
|
||||
"ref": "master",
|
||||
"path": "typings",
|
||||
"bundle": "typings/tsd.d.ts",
|
||||
"installed": {
|
||||
"react/react.d.ts": {
|
||||
"commit": "e69fe60f2d6377ea4fae539493997b098f52cad1"
|
||||
},
|
||||
"react/react-dom.d.ts": {
|
||||
"commit": "86dbea8fc37d9473fee465da4f0a21bea4f8cbd9"
|
||||
},
|
||||
"redux/redux.d.ts": {
|
||||
"commit": "e69fe60f2d6377ea4fae539493997b098f52cad1"
|
||||
},
|
||||
"webpack/webpack-env.d.ts": {
|
||||
"commit": "717a5fdb079f8dd7c19f1b22f7f656dd990f0ccf"
|
||||
},
|
||||
"react-redux/react-redux.d.ts": {
|
||||
"commit": "717a5fdb079f8dd7c19f1b22f7f656dd990f0ccf"
|
||||
},
|
||||
"react-bootstrap/react-bootstrap.d.ts": {
|
||||
"commit": "e69fe60f2d6377ea4fae539493997b098f52cad1"
|
||||
},
|
||||
"react-router/react-router.d.ts": {
|
||||
"commit": "e69fe60f2d6377ea4fae539493997b098f52cad1"
|
||||
},
|
||||
"react-router/history.d.ts": {
|
||||
"commit": "e69fe60f2d6377ea4fae539493997b098f52cad1"
|
||||
},
|
||||
"react-router-bootstrap/react-router-bootstrap.d.ts": {
|
||||
"commit": "e69fe60f2d6377ea4fae539493997b098f52cad1"
|
||||
},
|
||||
"react-router-redux/react-router-redux.d.ts": {
|
||||
"commit": "e69fe60f2d6377ea4fae539493997b098f52cad1"
|
||||
},
|
||||
"redux-thunk/redux-thunk.d.ts": {
|
||||
"commit": "e69fe60f2d6377ea4fae539493997b098f52cad1"
|
||||
},
|
||||
"whatwg-fetch/whatwg-fetch.d.ts": {
|
||||
"commit": "f4b1797c1201b6c575668f5d7ea12d9b1ab21846"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,976 +0,0 @@
|
||||
// Type definitions for react-bootstrap
|
||||
// Project: https://github.com/react-bootstrap/react-bootstrap
|
||||
// Definitions by: Walker Burgin <https://github.com/walkerburgin>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
///<reference path="../react/react.d.ts"/>
|
||||
|
||||
declare module "react-bootstrap" {
|
||||
// Import React
|
||||
import React = require("react");
|
||||
|
||||
|
||||
// <Button />
|
||||
// ----------------------------------------
|
||||
interface ButtonProps extends React.Props<ButtonClass>{
|
||||
|
||||
// Optional
|
||||
active?: boolean;
|
||||
disabled?: boolean;
|
||||
block?: boolean;
|
||||
bsStyle?: string;
|
||||
bsSize?: string;
|
||||
className?: string;
|
||||
navItem?: boolean;
|
||||
navDropdown?: boolean;
|
||||
componentClass?: string;
|
||||
href?: string;
|
||||
onClick?: Function; // Add more specific type
|
||||
target?: string;
|
||||
type?: string;
|
||||
}
|
||||
interface Button extends React.ReactElement<ButtonProps> { }
|
||||
interface ButtonClass extends React.ComponentClass<ButtonProps> { }
|
||||
var Button: ButtonClass;
|
||||
|
||||
|
||||
// <ButtonToolbar />
|
||||
// ----------------------------------------
|
||||
interface ButtonToolbarProps extends React.Props<ButtonToolbarClass> {
|
||||
|
||||
// Optional
|
||||
block?: boolean;
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
className?: string;
|
||||
justified?: boolean;
|
||||
vertical?: boolean;
|
||||
}
|
||||
interface ButtonToolbar extends React.ReactElement<ButtonToolbarProps> { }
|
||||
interface ButtonToolbarClass extends React.ComponentClass<ButtonToolbarProps> { }
|
||||
var ButtonToolbar: ButtonToolbarClass;
|
||||
|
||||
// <ButtonGroup />
|
||||
// ----------------------------------------
|
||||
interface ButtonGroupProps extends React.Props<ButtonGroupClass> {
|
||||
// Optional
|
||||
block?: boolean;
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
className?: string;
|
||||
justified?: boolean;
|
||||
vertical?: boolean;
|
||||
}
|
||||
interface ButtonGroup extends React.ReactElement<ButtonGroupProps> { }
|
||||
interface ButtonGroupClass extends React.ComponentClass<ButtonGroupProps> { }
|
||||
var ButtonGroup: ButtonGroupClass;
|
||||
|
||||
|
||||
// <DropdownButton />
|
||||
// ----------------------------------------
|
||||
interface DropdownButtonProps extends React.Props<DropdownButtonClass> {
|
||||
bsStyle?: string;
|
||||
bsSize?: string;
|
||||
buttonClassName?: string;
|
||||
className?: string;
|
||||
dropup?: boolean;
|
||||
href?: string;
|
||||
id?: string | number;
|
||||
navItem?: boolean;
|
||||
noCaret?: boolean;
|
||||
onClick?: Function; // TODO: Add more specifc type
|
||||
onSelect?: Function; // TODO: Add more specific type
|
||||
pullRight?: boolean;
|
||||
title?: any; // TODO: Add more specific type
|
||||
}
|
||||
interface DropdownButton extends React.ReactElement<DropdownButtonProps> { }
|
||||
interface DropdownButtonClass extends React.ComponentClass<DropdownButtonProps> { }
|
||||
var DropdownButton: DropdownButtonClass;
|
||||
|
||||
|
||||
// <SplitButton />
|
||||
// ----------------------------------------
|
||||
interface SplitButtonProps extends React.Props<SplitButtonClass>{
|
||||
bsStyle?: string;
|
||||
bsSize?: string;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
dropdownTitle?: any; // TODO: Add more specific type
|
||||
dropup?: boolean;
|
||||
href?: string;
|
||||
id?: string;
|
||||
onClick?: Function; // TODO: Add more specific type
|
||||
onSelect?: Function; // TODO: Add more specific type
|
||||
pullRight?: boolean;
|
||||
target?: string;
|
||||
title?: any; // TODO: Add more specific type
|
||||
}
|
||||
interface SplitButton extends React.ReactElement<SplitButtonProps> { }
|
||||
interface SplitButtonClass extends React.ComponentClass<SplitButtonProps> { }
|
||||
var SplitButton: SplitButtonClass;
|
||||
|
||||
|
||||
// <MenuItem />
|
||||
// ----------------------------------------
|
||||
interface MenuItemProps extends React.Props<MenuItemClass> {
|
||||
active?: boolean;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
divider?: boolean;
|
||||
eventKey?: any;
|
||||
header?: boolean;
|
||||
href?: string;
|
||||
onClick?: Function;
|
||||
onKeyDown?: Function;
|
||||
onSelect?: Function;
|
||||
target?: string;
|
||||
title?: string;
|
||||
}
|
||||
interface MenuItem extends React.ReactElement<MenuItemProps> { }
|
||||
interface MenuItemClass extends React.ComponentClass<MenuItemProps> { }
|
||||
var MenuItem: MenuItemClass;
|
||||
|
||||
|
||||
// <Panel />
|
||||
// ----------------------------------------
|
||||
interface PanelProps extends React.Props<PanelClass> {
|
||||
className?: string;
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
collapsible?: boolean;
|
||||
defaultExpanded?: boolean;
|
||||
eventKey?: any;
|
||||
expanded?: boolean;
|
||||
footer?: any; // TODO: Add more specific type
|
||||
header?: any; // TODO: Add more specific type
|
||||
id?: string;
|
||||
onSelect?: Function; // TODO: Add more specific type
|
||||
onClick?: Function; // TODO: Add more specific type
|
||||
}
|
||||
interface Panel extends React.ReactElement<PanelProps> { }
|
||||
interface PanelClass extends React.ComponentClass<PanelProps> { }
|
||||
var Panel: PanelClass;
|
||||
|
||||
|
||||
// <Accordion />
|
||||
// ----------------------------------------
|
||||
interface AccordionProps extends React.Props<AccordionClass> {
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
collapsible?: boolean;
|
||||
defaultExpanded?: boolean;
|
||||
eventKey?: any;
|
||||
expanded?: boolean;
|
||||
footer?: any; // TODO: Add more specific type
|
||||
header?: any; // TODO: Add more specific type
|
||||
id?: string;
|
||||
onSelect?: Function; // TODO: Add more specific type
|
||||
}
|
||||
interface Accordion extends React.ReactElement<AccordionProps> { }
|
||||
interface AccordionClass extends React.ComponentClass<AccordionProps> { }
|
||||
var Accordion: AccordionClass;
|
||||
|
||||
|
||||
// <PanelGroup />
|
||||
// ----------------------------------------
|
||||
interface PanelGroupProps extends React.Props<PanelGroupClass> {
|
||||
accordion?: boolean;
|
||||
activeKey?: any;
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
className?: string;
|
||||
defaultActiveKey?: any;
|
||||
onSelect?: Function;
|
||||
}
|
||||
interface PanelGroup extends React.ReactElement<PanelGroupProps> { }
|
||||
interface PanelGroupClass extends React.ComponentClass<PanelGroupProps> { }
|
||||
var PanelGroup: PanelGroupClass;
|
||||
|
||||
|
||||
// <Modal.Dialog />
|
||||
// ----------------------------------------
|
||||
interface ModalDialogProps extends React.Props<ModalDialogClass> {
|
||||
// TODO: Add more specific type
|
||||
}
|
||||
interface ModalDialog extends React.ReactElement<ModalDialogProps> { }
|
||||
interface ModalDialogClass extends React.ComponentClass<ModalHeaderProps> { }
|
||||
|
||||
|
||||
// <Modal.Header />
|
||||
// ----------------------------------------
|
||||
interface ModalHeaderProps extends React.Props<ModalHeaderClass> {
|
||||
className?: string;
|
||||
closeButton?: boolean;
|
||||
modalClassName?: string;
|
||||
onHide?: Function;
|
||||
// undefined?: string;
|
||||
}
|
||||
interface ModalHeader extends React.ReactElement<ModalHeaderProps> { }
|
||||
interface ModalHeaderClass extends React.ComponentClass<ModalHeaderProps> { }
|
||||
|
||||
|
||||
// <Modal.Title/>
|
||||
// ----------------------------------------
|
||||
interface ModalTitleProps extends React.Props<ModalTitleClass> {
|
||||
className?: string;
|
||||
modalClassName?: string;
|
||||
}
|
||||
interface ModalTitle extends React.ReactElement<ModalTitleProps> { }
|
||||
interface ModalTitleClass extends React.ComponentClass<ModalTitleProps> { }
|
||||
|
||||
|
||||
// <Modal.Body />
|
||||
// ----------------------------------------
|
||||
interface ModalBodyProps extends React.Props<ModalBodyClass> {
|
||||
className?: string;
|
||||
modalClassName?: string;
|
||||
}
|
||||
interface ModalBody extends React.ReactElement<ModalBodyProps> { }
|
||||
interface ModalBodyClass extends React.ComponentClass<ModalBodyProps> { }
|
||||
|
||||
|
||||
// <Modal.Footer />
|
||||
// ----------------------------------------
|
||||
interface ModalFooterProps extends React.Props<ModalFooterClass> {
|
||||
className?: string;
|
||||
modalClassName?: string;
|
||||
}
|
||||
interface ModalFooter extends React.ReactElement<ModalFooterProps> { }
|
||||
interface ModalFooterClass extends React.ComponentClass<ModalFooterProps> { }
|
||||
|
||||
|
||||
// <Modal />
|
||||
// ----------------------------------------
|
||||
interface ModalProps extends React.Props<ModalClass> {
|
||||
// Required
|
||||
onHide: Function;
|
||||
|
||||
// Optional
|
||||
animation?: boolean;
|
||||
autoFocus?: boolean;
|
||||
backdrop?: boolean|string;
|
||||
bsSize?: string;
|
||||
container?: any; // TODO: Add more specific type
|
||||
dialogClassName?: string;
|
||||
dialogComponent?: any; // TODO: Add more specific type
|
||||
enforceFocus?: boolean;
|
||||
keyboard?: boolean;
|
||||
show?: boolean;
|
||||
}
|
||||
interface Modal extends React.ReactElement<ModalProps> { }
|
||||
interface ModalClass extends React.ComponentClass<ModalProps> {
|
||||
Header: ModalHeaderClass;
|
||||
Title: ModalTitleClass;
|
||||
Body: ModalBodyClass;
|
||||
Footer: ModalFooterClass;
|
||||
Dialog: ModalDialogClass;
|
||||
}
|
||||
var Modal: ModalClass;
|
||||
|
||||
|
||||
// <OverlayTrigger />
|
||||
// ----------------------------------------
|
||||
interface OverlayTriggerProps extends React.Props<OverlayTriggerClass> {
|
||||
// Required
|
||||
overlay: any; // TODO: Add more specific type
|
||||
|
||||
// Optional
|
||||
animation?: any; // TODO: Add more specific type
|
||||
container?: any; // TODO: Add more specific type
|
||||
containerPadding?: number;
|
||||
defaultOverlayShown?: boolean;
|
||||
delay?: number;
|
||||
delayHide?: number;
|
||||
delayShow?: number;
|
||||
onEnter?: Function;
|
||||
onEntered?: Function;
|
||||
onEntering?: Function;
|
||||
onExit?: Function;
|
||||
onExited?: Function;
|
||||
onExiting?: Function;
|
||||
placement?: string;
|
||||
rootClose?: boolean;
|
||||
trigger?: string;
|
||||
}
|
||||
interface OverlayTrigger extends React.ReactElement<OverlayTriggerProps> { }
|
||||
interface OverlayTriggerClass extends React.ComponentClass<OverlayTriggerProps> { }
|
||||
var OverlayTrigger: OverlayTriggerClass;
|
||||
|
||||
|
||||
// <Tooltip />
|
||||
// ----------------------------------------
|
||||
interface TooltipProps extends React.Props<TooltipClass> {
|
||||
// Optional
|
||||
arrowOffsetLeft?: number | string;
|
||||
arrowOffsetTop?: number | string;
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
className?: string;
|
||||
id?: string;
|
||||
placement?: string;
|
||||
positionLeft?: number;
|
||||
positionTop?: number;
|
||||
title?: any; // TODO: Add more specific type
|
||||
}
|
||||
interface Tooltip extends React.ReactElement<TooltipProps> { }
|
||||
interface TooltipClass extends React.ComponentClass<TooltipProps> { }
|
||||
var Tooltip: TooltipClass;
|
||||
|
||||
|
||||
// <Popover/>
|
||||
// ----------------------------------------
|
||||
interface PopoverProps extends React.Props<PopoverClass> {
|
||||
// Optional
|
||||
arrowOffsetLeft?: number | string;
|
||||
arrowOffsetTop?: number | string;
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
className?: string;
|
||||
id?: string;
|
||||
placement?: string;
|
||||
positionLeft?: number;
|
||||
positionTop?: number;
|
||||
title?: any; // TODO: Add more specific type
|
||||
}
|
||||
interface Popover extends React.ReactElement<PopoverProps> { }
|
||||
interface PopoverClass extends React.ComponentClass<PopoverProps> { }
|
||||
var Popover: PopoverClass;
|
||||
|
||||
|
||||
// <Overlay />
|
||||
// ----------------------------------------
|
||||
interface OverlayProps extends React.Props<OverlayClass> {
|
||||
// Optional
|
||||
animation?: any; // TODO: Add more specific type
|
||||
container?: any; // TODO: Add more specific type
|
||||
containerPadding?: number; // TODO: Add more specific type
|
||||
onEnter?: Function;
|
||||
onEntered?: Function;
|
||||
onEntering?: Function;
|
||||
onExit?: Function;
|
||||
onExited?: Function;
|
||||
onExiting?: Function;
|
||||
onHide?: Function;
|
||||
placement?: string;
|
||||
rootClose?: boolean;
|
||||
show?: boolean;
|
||||
target?: Function;
|
||||
}
|
||||
interface Overlay extends React.ReactElement<OverlayProps> { }
|
||||
interface OverlayClass extends React.ComponentClass<OverlayProps> { }
|
||||
var Overlay: OverlayClass;
|
||||
|
||||
|
||||
// <ProgressBar />
|
||||
// ----------------------------------------
|
||||
interface ProgressBarProps extends React.Props<ProgressBarClass> {
|
||||
// Optional
|
||||
active?: boolean;
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
className?: string;
|
||||
interpolatedClass?: any; // TODO: Add more specific type
|
||||
label?: any; // TODO: Add more specific type
|
||||
max?: number;
|
||||
min?: number;
|
||||
now?: number;
|
||||
srOnly?: boolean;
|
||||
striped?: boolean;
|
||||
}
|
||||
interface ProgressBar extends React.ReactElement<ProgressBarProps> { }
|
||||
interface ProgressBarClass extends React.ComponentClass<ProgressBarProps> { }
|
||||
var ProgressBar: ProgressBarClass;
|
||||
|
||||
|
||||
// <Nav />
|
||||
// ----------------------------------------
|
||||
// TODO: This one turned into a union of two different types
|
||||
interface NavProps extends React.Props<NavClass> {
|
||||
// Optional
|
||||
activeHref?: string;
|
||||
activeKey?: any;
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
className?: string;
|
||||
collapsible?: boolean;
|
||||
eventKey?: any;
|
||||
expanded?: boolean;
|
||||
id?: string;
|
||||
justified?: boolean;
|
||||
navbar?: boolean;
|
||||
onSelect?: Function;
|
||||
pullRight?: boolean;
|
||||
right?: boolean;
|
||||
stacked?: boolean;
|
||||
ulClassName?: string;
|
||||
ulId?: string;
|
||||
}
|
||||
interface Nav extends React.ReactElement<NavProps> { }
|
||||
interface NavClass extends React.ComponentClass<NavProps> { }
|
||||
var Nav: NavClass;
|
||||
|
||||
|
||||
// <NavItem />
|
||||
// ----------------------------------------
|
||||
interface NavItemProps extends React.Props<NavItemClass> {
|
||||
active?: boolean;
|
||||
brand?: any; // TODO: Add more specific type
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
className?: string;
|
||||
componentClass?: any; // TODO: Add more specific type
|
||||
defaultNavExpanded?: boolean;
|
||||
disabled?: boolean;
|
||||
eventKey?: any;
|
||||
fixedBottom?: boolean;
|
||||
fixedTop?: boolean;
|
||||
fluid?: boolean;
|
||||
href?: string;
|
||||
inverse?: boolean;
|
||||
linkId?: string;
|
||||
navExpanded?: boolean;
|
||||
onClick?: Function;
|
||||
onSelect?: Function;
|
||||
onToggle?: Function;
|
||||
role?: string;
|
||||
staticTop?: boolean;
|
||||
target?: string;
|
||||
title?: string;
|
||||
toggleButton?: any; // TODO: Add more specific type
|
||||
toggleNavKey?: string | number;
|
||||
}
|
||||
interface NavItem extends React.ReactElement<NavItemProps> { }
|
||||
interface NavItemClass extends React.ComponentClass<NavItemProps> { }
|
||||
var NavItem: NavItemClass;
|
||||
|
||||
// <Navbar.Brand />
|
||||
// ----------------------------------------
|
||||
interface NavbarBrandProps extends React.Props<NavbarBrandClass> {
|
||||
}
|
||||
interface NavbarBrand extends React.ReactElement<NavbarBrandProps> { }
|
||||
interface NavbarBrandClass extends React.ComponentClass<NavbarBrandProps> { }
|
||||
|
||||
// <Navbar.Collapse />
|
||||
// ----------------------------------------
|
||||
interface NavbarCollapseProps extends React.Props<NavbarCollapseClass> {
|
||||
}
|
||||
interface NavbarCollapse extends React.ReactElement<NavbarCollapseProps> { }
|
||||
interface NavbarCollapseClass extends React.ComponentClass<NavbarCollapseProps> { }
|
||||
|
||||
// <Navbar.Header />
|
||||
// ----------------------------------------
|
||||
interface NavbarHeaderProps extends React.Props<NavbarHeaderClass> {
|
||||
}
|
||||
interface NavbarHeader extends React.ReactElement<NavbarHeaderProps> { }
|
||||
interface NavbarHeaderClass extends React.ComponentClass<NavbarHeaderProps> { }
|
||||
|
||||
// <Navbar.Toggle />
|
||||
// ----------------------------------------
|
||||
interface NavbarToggleProps extends React.Props<NavbarToggleClass> {
|
||||
}
|
||||
interface NavbarToggle extends React.ReactElement<NavbarToggleProps> { }
|
||||
interface NavbarToggleClass extends React.ComponentClass<NavbarToggleProps> { }
|
||||
|
||||
// <Navbar />
|
||||
// ----------------------------------------
|
||||
interface NavbarProps extends React.Props<NavbarClass> {
|
||||
brand?: any; // TODO: Add more specific type
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
className?: string;
|
||||
componentClass?: any; // TODO: Add more specific type
|
||||
defaultNavExpanded?: boolean;
|
||||
fixedBottom?: boolean;
|
||||
fixedTop?: boolean;
|
||||
fluid?: boolean;
|
||||
inverse?: boolean;
|
||||
navExpanded?: boolean;
|
||||
onToggle?: Function;
|
||||
role?: string;
|
||||
staticTop?: boolean;
|
||||
toggleButton?: any; // TODO: Add more specific type
|
||||
toggleNavKey?: string | number;
|
||||
}
|
||||
interface Navbar extends React.ReactElement<NavbarProps> { }
|
||||
interface NavbarClass extends React.ComponentClass<NavbarProps> {
|
||||
Brand: NavbarBrandClass;
|
||||
Collapse: NavbarCollapseClass;
|
||||
Header: NavbarHeaderClass;
|
||||
Toggle: NavbarToggleClass;
|
||||
}
|
||||
var Navbar: NavbarClass;
|
||||
|
||||
// <NavBrand />
|
||||
// ----------------------------------------
|
||||
interface NavBrandProps {
|
||||
|
||||
}
|
||||
interface NavBrand extends React.ReactElement<NavbarProps> { }
|
||||
interface NavBrandClass extends React.ComponentClass<NavbarProps> { }
|
||||
var NavBrand: NavBrandClass;
|
||||
|
||||
|
||||
// <NavDropdown />
|
||||
// ----------------------------------------
|
||||
interface NavDropdownProps extends React.Props<NavDropdownClass> {
|
||||
className?: string;
|
||||
eventKey?: any;
|
||||
title?: string;
|
||||
id?: string;
|
||||
}
|
||||
interface NavDropdown extends React.ReactElement<NavDropdownProps> { }
|
||||
interface NavDropdownClass extends React.ComponentClass<NavDropdownProps> { }
|
||||
var NavDropdown: NavDropdownClass;
|
||||
|
||||
|
||||
// <Tabs />
|
||||
// ----------------------------------------
|
||||
interface TabsProps extends React.Props<TabsClass> {
|
||||
activeKey?: any;
|
||||
animation?: boolean;
|
||||
bsStyle?: string;
|
||||
defaultActiveKey?: any;
|
||||
id?: string | number;
|
||||
onSelect?: Function;
|
||||
paneWidth?: any; // TODO: Add more specific type
|
||||
position?: string;
|
||||
tabWidth?: any; // TODO: Add more specific type
|
||||
}
|
||||
interface Tabs extends React.ReactElement<TabsProps> { }
|
||||
interface TabsClass extends React.ComponentClass<TabsProps> { }
|
||||
var Tabs: TabsClass;
|
||||
|
||||
|
||||
// <Tab />
|
||||
// ----------------------------------------
|
||||
interface TabProps extends React.Props<TabClass> {
|
||||
animation?: boolean;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
eventKey?: any; // TODO: Add more specific type
|
||||
title?: any; // TODO: Add more specific type
|
||||
}
|
||||
interface Tab extends React.ReactElement<TabProps> { }
|
||||
interface TabClass extends React.ComponentClass<TabProps> { }
|
||||
var Tab: TabClass;
|
||||
|
||||
|
||||
// <Pager />
|
||||
// ----------------------------------------
|
||||
interface PagerProps extends React.Props<PagerClass> {
|
||||
className?: string;
|
||||
onSelect?: Function;
|
||||
}
|
||||
interface Pager extends React.ReactElement<PagerProps> { }
|
||||
interface PagerClass extends React.ComponentClass<PagerProps> { }
|
||||
var Pager: PagerClass;
|
||||
|
||||
|
||||
// <PageItem />
|
||||
// ----------------------------------------
|
||||
interface PageItemProps extends React.Props<PageItemClass> {
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
eventKey?: any;
|
||||
href?: string;
|
||||
next?: boolean;
|
||||
onSelect?: Function;
|
||||
previous?: boolean;
|
||||
target?: string;
|
||||
title?: string;
|
||||
}
|
||||
interface PageItem extends React.ReactElement<PageItemProps> { }
|
||||
interface PageItemClass extends React.ComponentClass<PageItemProps> { }
|
||||
var PageItem: PageItemClass;
|
||||
|
||||
|
||||
// <Pagination />
|
||||
// ----------------------------------------
|
||||
interface PaginationProps extends React.Props<PaginationClass> {
|
||||
activePage?: number;
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
buttonComponentClass?: any; // TODO: Add more specific type
|
||||
className?: string;
|
||||
ellipsis?: boolean;
|
||||
first?: boolean;
|
||||
items?: number;
|
||||
last?: boolean;
|
||||
maxButtons?: number;
|
||||
next?: boolean;
|
||||
onSelect?: Function;
|
||||
prev?: boolean;
|
||||
}
|
||||
interface Pagination extends React.ReactElement<PaginationProps> { }
|
||||
interface PaginationClass extends React.ComponentClass<PaginationProps> { }
|
||||
var Pagination: PaginationClass;
|
||||
|
||||
|
||||
// <Alert />
|
||||
// ----------------------------------------
|
||||
interface AlertProps extends React.Props<AlertClass> {
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
className?: string;
|
||||
closeLabel?: string;
|
||||
dismissAfter?: number;
|
||||
onDismiss?: Function;
|
||||
}
|
||||
interface Alert extends React.ReactElement<AlertProps> { }
|
||||
interface AlertClass extends React.ComponentClass<AlertProps> { }
|
||||
var Alert: AlertClass;
|
||||
|
||||
|
||||
// <Carousel />
|
||||
// ----------------------------------------
|
||||
interface CarouselProps extends React.Props<CarouselClass> {
|
||||
activeIndex?: number;
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
className?: string;
|
||||
controls?: boolean;
|
||||
defaultActiveIndex?: number;
|
||||
direction?: string;
|
||||
indicators?: boolean;
|
||||
interval?: number;
|
||||
nextIcon?: any; // TODO: Add more specific type
|
||||
onSelect?: Function;
|
||||
onSlideEnd?: Function;
|
||||
pauseOnHover?: boolean;
|
||||
prevIcon?: any; // TODO: Add more specific type
|
||||
slide?: boolean;
|
||||
wrap?: boolean;
|
||||
}
|
||||
interface Carousel extends React.ReactElement<CarouselProps> { }
|
||||
interface CarouselClass extends React.ComponentClass<CarouselProps> { }
|
||||
var Carousel: CarouselClass;
|
||||
|
||||
|
||||
// <CarouselItem />
|
||||
// ----------------------------------------
|
||||
interface CarouselItemProps extends React.Props<CarouselItemClass> {
|
||||
active?: boolean;
|
||||
animtateIn?: boolean;
|
||||
animateOut?: boolean;
|
||||
caption?: any; // TODO: Add more specific type
|
||||
className?: string;
|
||||
direction?: string;
|
||||
index?: number;
|
||||
onAnimateOutEnd?: Function;
|
||||
}
|
||||
interface CarouselItem extends React.ReactElement<CarouselItemProps> { }
|
||||
interface CarouselItemClass extends React.ComponentClass<CarouselItemProps> { }
|
||||
var CarouselItem: CarouselItemClass;
|
||||
|
||||
|
||||
// <Grid />
|
||||
// ----------------------------------------
|
||||
interface GridProps extends React.Props<GridClass> {
|
||||
className?: string;
|
||||
componentClass?: any; // TODO: Add more specific type
|
||||
fluid?: boolean;
|
||||
}
|
||||
interface Grid extends React.ReactElement<GridProps> { }
|
||||
interface GridClass extends React.ComponentClass<GridProps> { }
|
||||
var Grid: GridClass;
|
||||
|
||||
|
||||
// <Row />
|
||||
// ----------------------------------------
|
||||
interface RowProps extends React.Props<RowClass> {
|
||||
className?: string;
|
||||
componentClass?: any; // TODO: Add more specific type
|
||||
}
|
||||
interface Row extends React.ReactElement<RowProps> { }
|
||||
interface RowClass extends React.ComponentClass<RowProps> { }
|
||||
var Row: RowClass;
|
||||
|
||||
|
||||
// <Col />
|
||||
// ----------------------------------------
|
||||
interface ColProps extends React.Props<ColClass> {
|
||||
className?: string;
|
||||
componentClass?: any; // TODO: Add more specific type
|
||||
lg?: number;
|
||||
lgOffset?: number;
|
||||
lgPull?: number;
|
||||
lgPush?: number;
|
||||
md?: number;
|
||||
mdOffset?: number;
|
||||
mdPull?: number;
|
||||
mdPush?: number;
|
||||
sm?: number;
|
||||
smOffset?: number;
|
||||
smPull?: number;
|
||||
smPush?: number;
|
||||
xs?: number;
|
||||
xsOffset?: number;
|
||||
xsPull?: number;
|
||||
xsPush?: number;
|
||||
}
|
||||
interface Col extends React.ReactElement<ColProps> { }
|
||||
interface ColClass extends React.ComponentClass<ColProps> { }
|
||||
var Col: ColClass;
|
||||
|
||||
|
||||
// <Thumbnail />
|
||||
// ----------------------------------------
|
||||
interface ThumbnailProps extends React.Props<ThumbnailClass> {
|
||||
alt?: string;
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
className?: string;
|
||||
href?: string;
|
||||
src?: string;
|
||||
}
|
||||
interface Thumbnail extends React.ReactElement<ThumbnailProps> { }
|
||||
interface ThumbnailClass extends React.ComponentClass<ThumbnailProps> { }
|
||||
var Thumbnail: ThumbnailClass;
|
||||
|
||||
|
||||
// <ListGroup />
|
||||
// ----------------------------------------
|
||||
interface ListGroupProps extends React.Props<ListGroupClass> {
|
||||
className?: string;
|
||||
id?: string | number;
|
||||
fill?: boolean; // TODO: Add more specific type
|
||||
}
|
||||
interface ListGroup extends React.ReactElement<ListGroupProps> { }
|
||||
interface ListGroupClass extends React.ComponentClass<ListGroupProps> { }
|
||||
var ListGroup: ListGroupClass;
|
||||
|
||||
|
||||
// <ListGroupItem />
|
||||
// ----------------------------------------
|
||||
interface ListGroupItemProps extends React.Props<ListGroupItemClass> {
|
||||
active?: any;
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
className?: string;
|
||||
disabled?: any;
|
||||
eventKey?: any;
|
||||
header?: any; // TODO: Add more specific type
|
||||
href?: string;
|
||||
key?: any; // TODO: Add more specific type
|
||||
listItem?: boolean;
|
||||
onClick?: Function; // TODO: Add more specific type
|
||||
target?: string;
|
||||
}
|
||||
interface ListGroupItem extends React.ReactElement<ListGroupItemProps> { }
|
||||
interface ListGroupItemClass extends React.ComponentClass<ListGroupItemProps> { }
|
||||
var ListGroupItem: ListGroupItemClass;
|
||||
|
||||
|
||||
// <Label />
|
||||
// ----------------------------------------
|
||||
interface LabelProps extends React.Props<LabelClass> {
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
className?: string;
|
||||
}
|
||||
interface Label extends React.ReactElement<LabelProps> { }
|
||||
interface LabelClass extends React.ComponentClass<LabelProps> { }
|
||||
var Label: LabelClass;
|
||||
|
||||
|
||||
// <Badge />
|
||||
// ----------------------------------------
|
||||
interface BadgeProps extends React.Props<BadgeClass> {
|
||||
className?: string;
|
||||
pullRight?: boolean;
|
||||
}
|
||||
interface Badge extends React.ReactElement<BadgeProps> { }
|
||||
interface BadgeClass extends React.ComponentClass<BadgeProps> { }
|
||||
var Badge: BadgeClass;
|
||||
|
||||
|
||||
// <Jumbotron />
|
||||
// ----------------------------------------
|
||||
interface JumbotronProps extends React.Props<JumbotronClass> {
|
||||
className?: string;
|
||||
componentClass?: any; // TODO: Add more specific type
|
||||
}
|
||||
interface Jumbotron extends React.ReactElement<JumbotronProps> { }
|
||||
interface JumbotronClass extends React.ComponentClass<JumbotronProps> { }
|
||||
var Jumbotron: JumbotronClass;
|
||||
|
||||
|
||||
// <PageHeader />
|
||||
// ----------------------------------------
|
||||
interface PageHeaderProps extends React.Props<PageHeaderClass> {
|
||||
className?: string;
|
||||
}
|
||||
interface PageHeader extends React.ReactElement<PageHeaderProps> { }
|
||||
interface PageHeaderClass extends React.ComponentClass<PageHeaderProps> { }
|
||||
var PageHeader: PageHeaderClass;
|
||||
|
||||
|
||||
// <Well />
|
||||
// ----------------------------------------
|
||||
interface WellProps extends React.Props<WellClass> {
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
className?: string;
|
||||
}
|
||||
interface Well extends React.ReactElement<WellProps> { }
|
||||
interface WellClass extends React.ComponentClass<WellProps> { }
|
||||
var Well: WellClass;
|
||||
|
||||
|
||||
// <Glyphicon />
|
||||
// ----------------------------------------
|
||||
interface GlyphiconProps extends React.Props<GlyphiconClass> {
|
||||
className?: string;
|
||||
// Required
|
||||
glyph: string;
|
||||
}
|
||||
interface Glyphicon extends React.ReactElement<GlyphiconProps> { }
|
||||
interface GlyphiconClass extends React.ComponentClass<GlyphiconProps> { }
|
||||
var Glyphicon: GlyphiconClass;
|
||||
|
||||
|
||||
// <Table />
|
||||
// ----------------------------------------
|
||||
interface TableProps extends React.Props<TableClass> {
|
||||
bordered?: boolean;
|
||||
className?: string;
|
||||
condensed?: boolean;
|
||||
hover?: boolean;
|
||||
responsive?: boolean;
|
||||
striped?: boolean;
|
||||
}
|
||||
interface Table extends React.ReactElement<TableProps> { }
|
||||
interface TableClass extends React.ComponentClass<TableProps> { }
|
||||
var Table: TableClass;
|
||||
|
||||
|
||||
// <Input />
|
||||
// ----------------------------------------
|
||||
interface InputProps extends React.Props<InputClass> {
|
||||
defaultValue?:string;
|
||||
addonAfter?: any; // TODO: Add more specific type
|
||||
addonBefore?: any; // TODO: Add more specific type
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
buttonAfter?: any; // TODO: Add more specific type
|
||||
buttonBefore?: any; // TODO: Add more specific type
|
||||
className?: string;
|
||||
checked?: boolean;
|
||||
disabled?: boolean;
|
||||
feedbackIcon?: any; // TODO: Add more specific type
|
||||
groupClassName?: string;
|
||||
hasFeedback?: boolean;
|
||||
help?: any; // TODO: Add more specific type
|
||||
id?: string | number;
|
||||
label?: any; // TODO: Add more specific type
|
||||
labelClassName?: string;
|
||||
multiple?: boolean;
|
||||
placeholder?: string;
|
||||
readOnly?: boolean;
|
||||
type?: string;
|
||||
onChange?: Function; // TODO: Add more specific type
|
||||
onKeyDown?: Function; // TODO: Add more specific type
|
||||
onKeyUp?: Function; // TODO: Add more specific type
|
||||
onKeyPress?: Function; // TODO: Add more specific type
|
||||
value?: any; // TODO: Add more specific type
|
||||
wrapperClassName?: string;
|
||||
}
|
||||
interface Input extends React.ReactElement<InputProps> { }
|
||||
interface InputClass extends React.ComponentClass<InputProps> { }
|
||||
var Input: InputClass;
|
||||
|
||||
|
||||
// <ButtonInput />
|
||||
// ----------------------------------------
|
||||
interface ButtonInputProps extends React.Props<ButtonInputClass> {
|
||||
addonAfter?: any; // TODO: Add more specific type
|
||||
addonBefore?: any; // TODO: Add more specific type
|
||||
bsSize?: string;
|
||||
bsStyle?: string;
|
||||
buttonAfter?: any; // TODO: Add more specific type
|
||||
buttonBefore?: any; // TODO: Add more specific type
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
feedbackIcon?: any; // TODO: Add more specific type
|
||||
groupClassName?: string;
|
||||
hasFeedback?: boolean;
|
||||
help?: any; // TODO: Add more specific type
|
||||
id?: string | number;
|
||||
label?: any; // TODO: Add more specific type
|
||||
labelClassName?: string;
|
||||
multiple?: boolean;
|
||||
onClick?: Function; // TODO: Add more specific type
|
||||
type?: string;
|
||||
value?: any; // TODO: Add more specific type
|
||||
wrapperClassName?: string;
|
||||
}
|
||||
interface ButtonInput extends React.ReactElement<ButtonInputProps> { }
|
||||
interface ButtonInputClass extends React.ComponentClass<ButtonInputProps> { }
|
||||
var ButtonInput: ButtonInputClass;
|
||||
|
||||
|
||||
// TODO: FormControls.Static
|
||||
|
||||
|
||||
// <Portal />
|
||||
// ----------------------------------------
|
||||
interface PortalProps extends React.Props<PortalClass> {
|
||||
dimension?: string | Function;
|
||||
getDimensionValue?: Function;
|
||||
in?: boolean;
|
||||
onEnter?: Function;
|
||||
onEntered?: Function;
|
||||
onEntering?: Function;
|
||||
onExit?: Function;
|
||||
onExited?: Function;
|
||||
onExiting?: Function;
|
||||
role?: string;
|
||||
timeout?: number;
|
||||
transitionAppear?: boolean;
|
||||
unmountOnExit?: boolean;
|
||||
}
|
||||
interface Portal extends React.ReactElement<PortalProps> { }
|
||||
interface PortalClass extends React.ComponentClass<PortalProps> { }
|
||||
var Portal: PortalClass;
|
||||
|
||||
|
||||
// <Position />
|
||||
// ----------------------------------------
|
||||
interface PositionProps extends React.Props<PositionClass> {
|
||||
dimension?: string | Function;
|
||||
getDimensionValue?: Function;
|
||||
in?: boolean;
|
||||
onEnter?: Function;
|
||||
onEntered?: Function;
|
||||
onEntering?: Function;
|
||||
onExit?: Function;
|
||||
onExited?: Function;
|
||||
onExiting?: Function;
|
||||
role?: string;
|
||||
timeout?: number;
|
||||
transitionAppear?: boolean;
|
||||
unmountOnExit?: boolean;
|
||||
}
|
||||
interface Position extends React.ReactElement<PositionProps> { }
|
||||
interface PositionClass extends React.ComponentClass<PositionProps> { }
|
||||
var Position: PositionClass;
|
||||
|
||||
|
||||
// <Fade />
|
||||
// ----------------------------------------
|
||||
interface FadeProps extends React.Props<FadeClass> {
|
||||
in?: boolean;
|
||||
onEnter?: Function;
|
||||
onEntered?: Function;
|
||||
onEntering?: Function;
|
||||
onExit?: Function;
|
||||
onExited?: Function;
|
||||
onExiting?: Function;
|
||||
timeout?: number;
|
||||
transitionAppear?: boolean;
|
||||
unmountOnExit?: boolean;
|
||||
}
|
||||
interface Fade extends React.ReactElement<FadeProps> { }
|
||||
interface FadeClass extends React.ComponentClass<FadeProps> { }
|
||||
var Fade: FadeClass;
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
// Type definitions for react-redux 2.1.2
|
||||
// Project: https://github.com/rackt/react-redux
|
||||
// Definitions by: Qubo <https://github.com/tkqubo>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
/// <reference path="../react/react.d.ts" />
|
||||
/// <reference path="../redux/redux.d.ts" />
|
||||
|
||||
declare module "react-redux" {
|
||||
import { Component } from 'react';
|
||||
import { Store, Dispatch, ActionCreator } from 'redux';
|
||||
|
||||
export class ElementClass extends Component<any, any> { }
|
||||
export interface ClassDecorator {
|
||||
<T extends (typeof ElementClass)>(component: T): T
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects a React component to a Redux store.
|
||||
* @param mapStateToProps
|
||||
* @param mapDispatchToProps
|
||||
* @param mergeProps
|
||||
* @param options
|
||||
*/
|
||||
export function connect(mapStateToProps?: MapStateToProps,
|
||||
mapDispatchToProps?: MapDispatchToPropsFunction|MapDispatchToPropsObject,
|
||||
mergeProps?: MergeProps,
|
||||
options?: Options): ClassDecorator;
|
||||
|
||||
interface MapStateToProps {
|
||||
(state: any, ownProps?: any): any;
|
||||
}
|
||||
|
||||
interface MapDispatchToPropsFunction {
|
||||
(dispatch: Dispatch, ownProps?: any): any;
|
||||
}
|
||||
|
||||
interface MapDispatchToPropsObject {
|
||||
[name: string]: ActionCreator;
|
||||
}
|
||||
|
||||
interface MergeProps {
|
||||
(stateProps: any, dispatchProps: any, ownProps: any): any;
|
||||
}
|
||||
|
||||
interface Options {
|
||||
/**
|
||||
* If true, implements shouldComponentUpdate and shallowly compares the result of mergeProps,
|
||||
* preventing unnecessary updates, assuming that the component is a “pure” component
|
||||
* and does not rely on any input or state other than its props and the selected Redux store’s state.
|
||||
* Defaults to true.
|
||||
* @default true
|
||||
*/
|
||||
pure: boolean;
|
||||
}
|
||||
|
||||
export interface Property {
|
||||
/**
|
||||
* The single Redux store in your application.
|
||||
*/
|
||||
store?: Store;
|
||||
children?: Function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the Redux store available to the connect() calls in the component hierarchy below.
|
||||
*/
|
||||
export class Provider extends Component<Property, {}> { }
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
// Type definitions for react-router-bootstrap
|
||||
// Project: https://github.com/react-bootstrap/react-router-bootstrap
|
||||
// Definitions by: Vincent Lesierse <https://github.com/vlesierse>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
///<reference path="../react/react.d.ts"/>
|
||||
///<reference path="../react-router/react-router.d.ts"/>
|
||||
|
||||
declare namespace ReactRouterBootstrap {
|
||||
// Import React
|
||||
import React = __React;
|
||||
|
||||
interface LinkContainerProps extends ReactRouter.LinkProps {
|
||||
disabled?: boolean
|
||||
}
|
||||
interface LinkContainer extends React.ComponentClass<LinkContainerProps> {}
|
||||
interface LinkContainerElement extends React.ReactElement<LinkContainerProps> {}
|
||||
const LinkContainer: LinkContainer
|
||||
|
||||
const IndexLinkContainer: LinkContainer
|
||||
}
|
||||
|
||||
declare module "react-router-bootstrap/lib/LinkContainer" {
|
||||
|
||||
export default ReactRouterBootstrap.LinkContainer
|
||||
|
||||
}
|
||||
|
||||
declare module "react-router-bootstrap/lib/IndexLinkContainer" {
|
||||
|
||||
export default ReactRouterBootstrap.IndexLinkContainer
|
||||
|
||||
}
|
||||
|
||||
declare module "react-router-bootstrap" {
|
||||
|
||||
import LinkContainer from "react-router-bootstrap/lib/LinkContainer"
|
||||
|
||||
import IndexLinkContainer from "react-router-bootstrap/lib/IndexLinkContainer"
|
||||
|
||||
export {
|
||||
LinkContainer,
|
||||
IndexLinkContainer
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
// Type definitions for react-router-redux v2.1.0
|
||||
// Project: https://github.com/rackt/react-router-redux
|
||||
// Definitions by: Isman Usoh <http://github.com/isman-usoh>, Noah Shipley <https://github.com/noah79>, Dimitri Rosenberg <https://github.com/rosendi>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
/// <reference path="../redux/redux.d.ts" />
|
||||
/// <reference path="../react-router/react-router.d.ts"/>
|
||||
|
||||
declare namespace ReactRouterRedux {
|
||||
import R = Redux;
|
||||
import H = HistoryModule;
|
||||
|
||||
const TRANSITION: string;
|
||||
const UPDATE_LOCATION: string;
|
||||
|
||||
const push: PushAction;
|
||||
const replace: ReplaceAction;
|
||||
const go: GoAction;
|
||||
const goBack: GoForwardAction;
|
||||
const goForward: GoBackAction;
|
||||
const routeActions: RouteActions;
|
||||
|
||||
type LocationDescriptor = H.Location | H.Path;
|
||||
type PushAction = (nextLocation: LocationDescriptor) => void;
|
||||
type ReplaceAction = (nextLocation: LocationDescriptor) => void;
|
||||
type GoAction = (n: number) => void;
|
||||
type GoForwardAction = () => void;
|
||||
type GoBackAction = () => void;
|
||||
|
||||
interface RouteActions {
|
||||
push: PushAction;
|
||||
replace: ReplaceAction;
|
||||
go: GoAction;
|
||||
goForward: GoForwardAction;
|
||||
goBack: GoBackAction;
|
||||
}
|
||||
interface HistoryMiddleware extends R.Middleware {
|
||||
listenForReplays(store: R.Store, selectLocationState?: Function): void;
|
||||
unsubscribe(): void;
|
||||
}
|
||||
|
||||
function routeReducer(state?: any, options?: any): R.Reducer;
|
||||
function syncHistory(history: H.History): HistoryMiddleware;
|
||||
}
|
||||
|
||||
declare module "react-router-redux" {
|
||||
export = ReactRouterRedux;
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
// Type definitions for history v1.13.1
|
||||
// Project: https://github.com/rackt/history
|
||||
// Definitions by: Sergey Buturlakin <http://github.com/sergey-buturlakin>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
|
||||
declare namespace HistoryModule {
|
||||
|
||||
// types based on https://github.com/rackt/history/blob/master/docs/Terms.md
|
||||
|
||||
type Action = string
|
||||
|
||||
type BeforeUnloadHook = () => string | boolean
|
||||
|
||||
type CreateHistory<T> = (options?: HistoryOptions) => T
|
||||
|
||||
type CreateHistoryEnhancer<T, E> = (createHistory: CreateHistory<T>) => CreateHistory<T & E>
|
||||
|
||||
interface History {
|
||||
listenBefore(hook: TransitionHook): Function
|
||||
listen(listener: LocationListener): Function
|
||||
transitionTo(location: Location): void
|
||||
pushState(state: LocationState, path: Path): void
|
||||
replaceState(state: LocationState, path: Path): void
|
||||
push(path: Path): void
|
||||
replace(path: Path): void
|
||||
go(n: number): void
|
||||
goBack(): void
|
||||
goForward(): void
|
||||
createKey(): LocationKey
|
||||
createPath(path: Path): Path
|
||||
createHref(path: Path): Href
|
||||
createLocation(path?: Path, state?: LocationState, action?: Action, key?: LocationKey): Location
|
||||
|
||||
/** @deprecated use location.key to save state instead */
|
||||
setState(state: LocationState): void
|
||||
/** @deprecated use listenBefore instead */
|
||||
registerTransitionHook(hook: TransitionHook): void
|
||||
/** @deprecated use the callback returned from listenBefore instead */
|
||||
unregisterTransitionHook(hook: TransitionHook): void
|
||||
}
|
||||
|
||||
type HistoryOptions = Object
|
||||
|
||||
type Href = string
|
||||
|
||||
type Location = {
|
||||
pathname: Pathname
|
||||
search: QueryString
|
||||
query: Query
|
||||
state: LocationState
|
||||
action: Action
|
||||
key: LocationKey
|
||||
}
|
||||
|
||||
type LocationKey = string
|
||||
|
||||
type LocationListener = (location: Location) => void
|
||||
|
||||
type LocationState = Object
|
||||
|
||||
type Path = string // Pathname + QueryString
|
||||
|
||||
type Pathname = string
|
||||
|
||||
type Query = Object
|
||||
|
||||
type QueryString = string
|
||||
|
||||
type TransitionHook = (location: Location, callback: Function) => any
|
||||
|
||||
|
||||
interface HistoryBeforeUnload {
|
||||
listenBeforeUnload(hook: BeforeUnloadHook): Function
|
||||
}
|
||||
|
||||
interface HistoryQueries {
|
||||
pushState(state: LocationState, pathname: Pathname | Path, query?: Query): void
|
||||
replaceState(state: LocationState, pathname: Pathname | Path, query?: Query): void
|
||||
createPath(path: Path, query?: Query): Path
|
||||
createHref(path: Path, query?: Query): Href
|
||||
}
|
||||
|
||||
|
||||
// Global usage, without modules, needs the small trick, because lib.d.ts
|
||||
// already has `history` and `History` global definitions:
|
||||
// var createHistory = ((window as any).History as HistoryModule.Module).createHistory;
|
||||
interface Module {
|
||||
createHistory: CreateHistory<History>
|
||||
createHashHistory: CreateHistory<History>
|
||||
createMemoryHistory: CreateHistory<History>
|
||||
createLocation(path?: Path, state?: LocationState, action?: Action, key?: LocationKey): Location
|
||||
useBasename<T>(createHistory: CreateHistory<T>): CreateHistory<T>
|
||||
useBeforeUnload<T>(createHistory: CreateHistory<T>): CreateHistory<T & HistoryBeforeUnload>
|
||||
useQueries<T>(createHistory: CreateHistory<T>): CreateHistory<T & HistoryQueries>
|
||||
actions: {
|
||||
PUSH: string
|
||||
REPLACE: string
|
||||
POP: string
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "history/lib/createBrowserHistory" {
|
||||
|
||||
export default function createBrowserHistory(options?: HistoryModule.HistoryOptions): HistoryModule.History
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "history/lib/createHashHistory" {
|
||||
|
||||
export default function createHashHistory(options?: HistoryModule.HistoryOptions): HistoryModule.History
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "history/lib/createMemoryHistory" {
|
||||
|
||||
export default function createMemoryHistory(options?: HistoryModule.HistoryOptions): HistoryModule.History
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "history/lib/createLocation" {
|
||||
|
||||
export default function createLocation(path?: HistoryModule.Path, state?: HistoryModule.LocationState, action?: HistoryModule.Action, key?: HistoryModule.LocationKey): HistoryModule.Location
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "history/lib/useBasename" {
|
||||
|
||||
export default function useBasename<T>(createHistory: HistoryModule.CreateHistory<T>): HistoryModule.CreateHistory<T>
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "history/lib/useBeforeUnload" {
|
||||
|
||||
export default function useBeforeUnload<T>(createHistory: HistoryModule.CreateHistory<T>): HistoryModule.CreateHistory<T & HistoryModule.HistoryBeforeUnload>
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "history/lib/useQueries" {
|
||||
|
||||
export default function useQueries<T>(createHistory: HistoryModule.CreateHistory<T>): HistoryModule.CreateHistory<T & HistoryModule.HistoryQueries>
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "history/lib/actions" {
|
||||
|
||||
export const PUSH: string
|
||||
|
||||
export const REPLACE: string
|
||||
|
||||
export const POP: string
|
||||
|
||||
export default {
|
||||
PUSH,
|
||||
REPLACE,
|
||||
POP
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "history" {
|
||||
|
||||
export { default as createHistory } from "history/lib/createBrowserHistory"
|
||||
|
||||
export { default as createHashHistory } from "history/lib/createHashHistory"
|
||||
|
||||
export { default as createMemoryHistory } from "history/lib/createMemoryHistory"
|
||||
|
||||
export { default as createLocation } from "history/lib/createLocation"
|
||||
|
||||
export { default as useBasename } from "history/lib/useBasename"
|
||||
|
||||
export { default as useBeforeUnload } from "history/lib/useBeforeUnload"
|
||||
|
||||
export { default as useQueries } from "history/lib/useQueries"
|
||||
|
||||
import * as Actions from "history/lib/actions"
|
||||
|
||||
export { Actions }
|
||||
|
||||
}
|
||||
@@ -1,474 +0,0 @@
|
||||
// Type definitions for react-router v2.0.0-rc5
|
||||
// Project: https://github.com/rackt/react-router
|
||||
// Definitions by: Sergey Buturlakin <http://github.com/sergey-buturlakin>, Yuichi Murata <https://github.com/mrk21>, Václav Ostrožlík <https://github.com/vasek17>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
|
||||
/// <reference path="../react/react.d.ts" />
|
||||
/// <reference path="./history.d.ts"/>
|
||||
|
||||
|
||||
declare namespace ReactRouter {
|
||||
|
||||
import React = __React
|
||||
|
||||
import H = HistoryModule
|
||||
|
||||
// types based on https://github.com/rackt/react-router/blob/master/docs/Glossary.md
|
||||
|
||||
type Component = React.ReactType
|
||||
|
||||
type EnterHook = (nextState: RouterState, replaceState: RedirectFunction, callback?: Function) => any
|
||||
|
||||
type LeaveHook = () => any
|
||||
|
||||
type Params = Object
|
||||
|
||||
type ParseQueryString = (queryString: H.QueryString) => H.Query
|
||||
|
||||
type RedirectFunction = (state: H.LocationState, pathname: H.Pathname | H.Path, query?: H.Query) => void
|
||||
|
||||
type RouteComponent = Component
|
||||
|
||||
// use the following interface in an app code to get access to route param values, history, location...
|
||||
// interface MyComponentProps extends ReactRouter.RouteComponentProps<{}, { id: number }> {}
|
||||
// somewhere in MyComponent
|
||||
// ...
|
||||
// let id = this.props.routeParams.id
|
||||
// ...
|
||||
// this.props.history. ...
|
||||
// ...
|
||||
interface RouteComponentProps<P, R> {
|
||||
history?: History
|
||||
location?: H.Location
|
||||
params?: P
|
||||
route?: PlainRoute
|
||||
routeParams?: R
|
||||
routes?: PlainRoute[]
|
||||
children?: React.ReactElement<any>
|
||||
}
|
||||
|
||||
type RouteComponents = { [key: string]: RouteComponent }
|
||||
|
||||
type RouteConfig = React.ReactNode | PlainRoute | PlainRoute[]
|
||||
|
||||
type RouteHook = (nextLocation?: H.Location) => any
|
||||
|
||||
type RoutePattern = string
|
||||
|
||||
type StringifyQuery = (queryObject: H.Query) => H.QueryString
|
||||
|
||||
type RouterListener = (error: Error, nextState: RouterState) => void
|
||||
|
||||
interface RouterState {
|
||||
location: H.Location
|
||||
routes: PlainRoute[]
|
||||
params: Params
|
||||
components: RouteComponent[]
|
||||
}
|
||||
|
||||
|
||||
interface HistoryBase extends H.History {
|
||||
routes: PlainRoute[]
|
||||
parseQueryString?: ParseQueryString
|
||||
stringifyQuery?: StringifyQuery
|
||||
}
|
||||
|
||||
type History = HistoryBase & H.HistoryQueries & HistoryRoutes
|
||||
const browserHistory: History;
|
||||
const hashHistory: History;
|
||||
|
||||
/* components */
|
||||
|
||||
interface RouterProps extends React.Props<Router> {
|
||||
history?: H.History
|
||||
routes?: RouteConfig // alias for children
|
||||
createElement?: (component: RouteComponent, props: Object) => any
|
||||
onError?: (error: any) => any
|
||||
onUpdate?: () => any
|
||||
parseQueryString?: ParseQueryString
|
||||
stringifyQuery?: StringifyQuery
|
||||
}
|
||||
interface Router extends React.ComponentClass<RouterProps> {}
|
||||
interface RouterElement extends React.ReactElement<RouterProps> {}
|
||||
const Router: Router
|
||||
|
||||
|
||||
interface LinkProps extends React.HTMLAttributes, React.Props<Link> {
|
||||
activeStyle?: React.CSSProperties
|
||||
activeClassName?: string
|
||||
onlyActiveOnIndex?: boolean
|
||||
to: RoutePattern
|
||||
query?: H.Query
|
||||
state?: H.LocationState
|
||||
}
|
||||
interface Link extends React.ComponentClass<LinkProps> {}
|
||||
interface LinkElement extends React.ReactElement<LinkProps> {}
|
||||
const Link: Link
|
||||
|
||||
|
||||
const IndexLink: Link
|
||||
|
||||
|
||||
interface RouterContextProps extends React.Props<RouterContext> {
|
||||
history?: H.History
|
||||
router: Router
|
||||
createElement: (component: RouteComponent, props: Object) => any
|
||||
location: H.Location
|
||||
routes: RouteConfig
|
||||
params: Params
|
||||
components?: RouteComponent[]
|
||||
}
|
||||
interface RouterContext extends React.ComponentClass<RouterContextProps> {}
|
||||
interface RouterContextElement extends React.ReactElement<RouterContextProps> {
|
||||
history?: H.History
|
||||
location: H.Location
|
||||
router?: Router
|
||||
}
|
||||
const RouterContext: RouterContext
|
||||
|
||||
|
||||
/* components (configuration) */
|
||||
|
||||
interface RouteProps extends React.Props<Route> {
|
||||
path?: RoutePattern
|
||||
component?: RouteComponent
|
||||
components?: RouteComponents
|
||||
getComponent?: (location: H.Location, cb: (error: any, component?: RouteComponent) => void) => void
|
||||
getComponents?: (location: H.Location, cb: (error: any, components?: RouteComponents) => void) => void
|
||||
onEnter?: EnterHook
|
||||
onLeave?: LeaveHook
|
||||
getIndexRoute?: (location: H.Location, cb: (error: any, indexRoute: RouteConfig) => void) => void
|
||||
getChildRoutes?: (location: H.Location, cb: (error: any, childRoutes: RouteConfig) => void) => void
|
||||
}
|
||||
interface Route extends React.ComponentClass<RouteProps> {}
|
||||
interface RouteElement extends React.ReactElement<RouteProps> {}
|
||||
const Route: Route
|
||||
|
||||
|
||||
interface PlainRoute {
|
||||
path?: RoutePattern
|
||||
component?: RouteComponent
|
||||
components?: RouteComponents
|
||||
getComponent?: (location: H.Location, cb: (error: any, component?: RouteComponent) => void) => void
|
||||
getComponents?: (location: H.Location, cb: (error: any, components?: RouteComponents) => void) => void
|
||||
onEnter?: EnterHook
|
||||
onLeave?: LeaveHook
|
||||
indexRoute?: PlainRoute
|
||||
getIndexRoute?: (location: H.Location, cb: (error: any, indexRoute: RouteConfig) => void) => void
|
||||
childRoutes?: PlainRoute[]
|
||||
getChildRoutes?: (location: H.Location, cb: (error: any, childRoutes: RouteConfig) => void) => void
|
||||
}
|
||||
|
||||
|
||||
interface RedirectProps extends React.Props<Redirect> {
|
||||
path?: RoutePattern
|
||||
from?: RoutePattern // alias for path
|
||||
to: RoutePattern
|
||||
query?: H.Query
|
||||
state?: H.LocationState
|
||||
}
|
||||
interface Redirect extends React.ComponentClass<RedirectProps> {}
|
||||
interface RedirectElement extends React.ReactElement<RedirectProps> {}
|
||||
const Redirect: Redirect
|
||||
|
||||
|
||||
interface IndexRouteProps extends React.Props<IndexRoute> {
|
||||
component?: RouteComponent
|
||||
components?: RouteComponents
|
||||
getComponent?: (location: H.Location, cb: (error: any, component?: RouteComponent) => void) => void
|
||||
getComponents?: (location: H.Location, cb: (error: any, components?: RouteComponents) => void) => void
|
||||
onEnter?: EnterHook
|
||||
onLeave?: LeaveHook
|
||||
}
|
||||
interface IndexRoute extends React.ComponentClass<IndexRouteProps> {}
|
||||
interface IndexRouteElement extends React.ReactElement<IndexRouteProps> {}
|
||||
const IndexRoute: IndexRoute
|
||||
|
||||
|
||||
interface IndexRedirectProps extends React.Props<IndexRedirect> {
|
||||
to: RoutePattern
|
||||
query?: H.Query
|
||||
state?: H.LocationState
|
||||
}
|
||||
interface IndexRedirect extends React.ComponentClass<IndexRedirectProps> {}
|
||||
interface IndexRedirectElement extends React.ReactElement<IndexRedirectProps> {}
|
||||
const IndexRedirect: IndexRedirect
|
||||
|
||||
|
||||
/* mixins */
|
||||
|
||||
interface HistoryMixin {
|
||||
history: History
|
||||
}
|
||||
const History: React.Mixin<any, any>
|
||||
|
||||
|
||||
interface LifecycleMixin {
|
||||
routerWillLeave(nextLocation: H.Location): string | boolean
|
||||
}
|
||||
const Lifecycle: React.Mixin<any, any>
|
||||
|
||||
|
||||
const RouteContext: React.Mixin<any, any>
|
||||
|
||||
|
||||
/* utils */
|
||||
|
||||
interface HistoryRoutes {
|
||||
listen(listener: RouterListener): Function
|
||||
listenBeforeLeavingRoute(route: PlainRoute, hook: RouteHook): void
|
||||
match(location: H.Location, callback: (error: any, nextState: RouterState, nextLocation: H.Location) => void): void
|
||||
isActive(pathname: H.Pathname, query?: H.Query, indexOnly?: boolean): boolean
|
||||
}
|
||||
|
||||
function useRoutes<T>(createHistory: HistoryModule.CreateHistory<T>): HistoryModule.CreateHistory<T & HistoryRoutes>
|
||||
|
||||
|
||||
function createRoutes(routes: RouteConfig): PlainRoute[]
|
||||
|
||||
|
||||
interface MatchArgs {
|
||||
routes?: RouteConfig
|
||||
history?: H.History
|
||||
location?: H.Location
|
||||
parseQueryString?: ParseQueryString
|
||||
stringifyQuery?: StringifyQuery
|
||||
}
|
||||
interface MatchState extends RouterState {
|
||||
history: History
|
||||
}
|
||||
function match(args: MatchArgs, cb: (error: any, nextLocation: H.Location, nextState: MatchState) => void): void
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "react-router/lib/Router" {
|
||||
|
||||
export default ReactRouter.Router
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "react-router/lib/Link" {
|
||||
|
||||
export default ReactRouter.Link
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "react-router/lib/IndexLink" {
|
||||
|
||||
export default ReactRouter.IndexLink
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "react-router/lib/IndexRedirect" {
|
||||
|
||||
export default ReactRouter.IndexRedirect
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "react-router/lib/IndexRoute" {
|
||||
|
||||
export default ReactRouter.IndexRoute
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "react-router/lib/Redirect" {
|
||||
|
||||
export default ReactRouter.Redirect
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "react-router/lib/Route" {
|
||||
|
||||
export default ReactRouter.Route
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "react-router/lib/History" {
|
||||
|
||||
export default ReactRouter.History
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "react-router/lib/Lifecycle" {
|
||||
|
||||
export default ReactRouter.Lifecycle
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "react-router/lib/RouteContext" {
|
||||
|
||||
export default ReactRouter.RouteContext
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "react-router/lib/useRoutes" {
|
||||
|
||||
export default ReactRouter.useRoutes
|
||||
|
||||
}
|
||||
|
||||
declare module "react-router/lib/PatternUtils" {
|
||||
|
||||
export function formatPattern(pattern: string, params: {}): string;
|
||||
|
||||
}
|
||||
|
||||
declare module "react-router/lib/RouteUtils" {
|
||||
|
||||
type E = __React.ReactElement<any>
|
||||
|
||||
export function isReactChildren(object: E | E[]): boolean
|
||||
|
||||
export function createRouteFromReactElement(element: E): ReactRouter.PlainRoute
|
||||
|
||||
export function createRoutesFromReactChildren(children: E | E[], parentRoute: ReactRouter.PlainRoute): ReactRouter.PlainRoute[]
|
||||
|
||||
export import createRoutes = ReactRouter.createRoutes
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "react-router/lib/RouterContext" {
|
||||
|
||||
export default ReactRouter.RouterContext
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "react-router/lib/PropTypes" {
|
||||
|
||||
import React = __React
|
||||
|
||||
export function falsy(props: any, propName: string, componentName: string): Error;
|
||||
|
||||
export const history: React.Requireable<any>
|
||||
|
||||
export const location: React.Requireable<any>
|
||||
|
||||
export const component: React.Requireable<any>
|
||||
|
||||
export const components: React.Requireable<any>
|
||||
|
||||
export const route: React.Requireable<any>
|
||||
|
||||
export const routes: React.Requireable<any>
|
||||
|
||||
export default {
|
||||
falsy,
|
||||
history,
|
||||
location,
|
||||
component,
|
||||
components,
|
||||
route
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
declare module "react-router/lib/browserHistory" {
|
||||
export default ReactRouter.browserHistory;
|
||||
}
|
||||
|
||||
declare module "react-router/lib/hashHistory" {
|
||||
export default ReactRouter.hashHistory;
|
||||
}
|
||||
|
||||
declare module "react-router/lib/match" {
|
||||
|
||||
export default ReactRouter.match
|
||||
|
||||
}
|
||||
|
||||
|
||||
declare module "react-router" {
|
||||
|
||||
import Router from "react-router/lib/Router"
|
||||
|
||||
import Link from "react-router/lib/Link"
|
||||
|
||||
import IndexLink from "react-router/lib/IndexLink"
|
||||
|
||||
import IndexRedirect from "react-router/lib/IndexRedirect"
|
||||
|
||||
import IndexRoute from "react-router/lib/IndexRoute"
|
||||
|
||||
import Redirect from "react-router/lib/Redirect"
|
||||
|
||||
import Route from "react-router/lib/Route"
|
||||
|
||||
import History from "react-router/lib/History"
|
||||
|
||||
import Lifecycle from "react-router/lib/Lifecycle"
|
||||
|
||||
import RouteContext from "react-router/lib/RouteContext"
|
||||
|
||||
import browserHistory from "react-router/lib/browserHistory"
|
||||
|
||||
import hashHistory from "react-router/lib/hashHistory"
|
||||
|
||||
import useRoutes from "react-router/lib/useRoutes"
|
||||
|
||||
import { createRoutes } from "react-router/lib/RouteUtils"
|
||||
|
||||
import { formatPattern } from "react-router/lib/PatternUtils"
|
||||
|
||||
import RouterContext from "react-router/lib/RouterContext"
|
||||
|
||||
import PropTypes from "react-router/lib/PropTypes"
|
||||
|
||||
import match from "react-router/lib/match"
|
||||
|
||||
// PlainRoute is defined in the API documented at:
|
||||
// https://github.com/rackt/react-router/blob/master/docs/API.md
|
||||
// but not included in any of the .../lib modules above.
|
||||
export type PlainRoute = ReactRouter.PlainRoute
|
||||
|
||||
// The following definitions are also very useful to export
|
||||
// because by using these types lots of potential type errors
|
||||
// can be exposed:
|
||||
export type EnterHook = ReactRouter.EnterHook
|
||||
export type LeaveHook = ReactRouter.LeaveHook
|
||||
export type ParseQueryString = ReactRouter.ParseQueryString
|
||||
export type RedirectFunction = ReactRouter.RedirectFunction
|
||||
export type RouteComponentProps<P,R> = ReactRouter.RouteComponentProps<P,R>;
|
||||
export type RouteHook = ReactRouter.RouteHook
|
||||
export type StringifyQuery = ReactRouter.StringifyQuery
|
||||
export type RouterListener = ReactRouter.RouterListener
|
||||
export type RouterState = ReactRouter.RouterState
|
||||
export type HistoryBase = ReactRouter.HistoryBase
|
||||
|
||||
export {
|
||||
Router,
|
||||
Link,
|
||||
IndexLink,
|
||||
IndexRedirect,
|
||||
IndexRoute,
|
||||
Redirect,
|
||||
Route,
|
||||
History,
|
||||
browserHistory,
|
||||
hashHistory,
|
||||
Lifecycle,
|
||||
RouteContext,
|
||||
useRoutes,
|
||||
createRoutes,
|
||||
formatPattern,
|
||||
RouterContext,
|
||||
PropTypes,
|
||||
match
|
||||
}
|
||||
|
||||
export default Router
|
||||
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
// Type definitions for React v0.14 (react-dom)
|
||||
// Project: http://facebook.github.io/react/
|
||||
// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
/// <reference path="react.d.ts" />
|
||||
|
||||
declare namespace __React {
|
||||
namespace __DOM {
|
||||
function findDOMNode<E extends Element>(instance: ReactInstance): E;
|
||||
function findDOMNode(instance: ReactInstance): Element;
|
||||
|
||||
function render<P>(
|
||||
element: DOMElement<P>,
|
||||
container: Element,
|
||||
callback?: (element: Element) => any): Element;
|
||||
function render<P, S>(
|
||||
element: ClassicElement<P>,
|
||||
container: Element,
|
||||
callback?: (component: ClassicComponent<P, S>) => any): ClassicComponent<P, S>;
|
||||
function render<P, S>(
|
||||
element: ReactElement<P>,
|
||||
container: Element,
|
||||
callback?: (component: Component<P, S>) => any): Component<P, S>;
|
||||
|
||||
function unmountComponentAtNode(container: Element): boolean;
|
||||
|
||||
var version: string;
|
||||
|
||||
function unstable_batchedUpdates<A, B>(callback: (a: A, b: B) => any, a: A, b: B): void;
|
||||
function unstable_batchedUpdates<A>(callback: (a: A) => any, a: A): void;
|
||||
function unstable_batchedUpdates(callback: () => any): void;
|
||||
|
||||
function unstable_renderSubtreeIntoContainer<P>(
|
||||
parentComponent: Component<any, any>,
|
||||
nextElement: DOMElement<P>,
|
||||
container: Element,
|
||||
callback?: (element: Element) => any): Element;
|
||||
function unstable_renderSubtreeIntoContainer<P, S>(
|
||||
parentComponent: Component<any, any>,
|
||||
nextElement: ClassicElement<P>,
|
||||
container: Element,
|
||||
callback?: (component: ClassicComponent<P, S>) => any): ClassicComponent<P, S>;
|
||||
function unstable_renderSubtreeIntoContainer<P, S>(
|
||||
parentComponent: Component<any, any>,
|
||||
nextElement: ReactElement<P>,
|
||||
container: Element,
|
||||
callback?: (component: Component<P, S>) => any): Component<P, S>;
|
||||
}
|
||||
|
||||
namespace __DOMServer {
|
||||
function renderToString(element: ReactElement<any>): string;
|
||||
function renderToStaticMarkup(element: ReactElement<any>): string;
|
||||
var version: string;
|
||||
}
|
||||
}
|
||||
|
||||
declare module "react-dom" {
|
||||
import DOM = __React.__DOM;
|
||||
export = DOM;
|
||||
}
|
||||
|
||||
declare module "react-dom/server" {
|
||||
import DOMServer = __React.__DOMServer;
|
||||
export = DOMServer;
|
||||
}
|
||||
2274
samples/react/MusicStore/typings/react/react.d.ts
vendored
2274
samples/react/MusicStore/typings/react/react.d.ts
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,18 +0,0 @@
|
||||
// Type definitions for redux-thunk
|
||||
// Project: https://github.com/gaearon/redux-thunk
|
||||
// Definitions by: Qubo <https://github.com/tkqubo>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
/// <reference path="../redux/redux.d.ts" />
|
||||
|
||||
declare module ReduxThunk {
|
||||
export interface Thunk extends Redux.Middleware {}
|
||||
export interface ThunkInterface {
|
||||
<T>(dispatch: Redux.Dispatch, getState?: () => T): any;
|
||||
}
|
||||
}
|
||||
|
||||
declare module "redux-thunk" {
|
||||
var thunk: ReduxThunk.Thunk;
|
||||
export = thunk;
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
// Type definitions for Redux v1.0.0
|
||||
// Project: https://github.com/rackt/redux
|
||||
// Definitions by: William Buchwalter <https://github.com/wbuchwalter/>, Vincent Prouillet <https://github.com/Keats/>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
declare module Redux {
|
||||
|
||||
interface ActionCreator extends Function {
|
||||
(...args: any[]): any;
|
||||
}
|
||||
|
||||
interface Reducer extends Function {
|
||||
(state: any, action: any): any;
|
||||
}
|
||||
|
||||
interface Dispatch extends Function {
|
||||
(action: any): any;
|
||||
}
|
||||
|
||||
interface StoreMethods {
|
||||
dispatch: Dispatch;
|
||||
getState(): any;
|
||||
}
|
||||
|
||||
|
||||
interface MiddlewareArg {
|
||||
dispatch: Dispatch;
|
||||
getState: Function;
|
||||
}
|
||||
|
||||
interface Middleware extends Function {
|
||||
(obj: MiddlewareArg): Function;
|
||||
}
|
||||
|
||||
class Store {
|
||||
getReducer(): Reducer;
|
||||
replaceReducer(nextReducer: Reducer): void;
|
||||
dispatch(action: any): any;
|
||||
getState(): any;
|
||||
subscribe(listener: Function): Function;
|
||||
}
|
||||
|
||||
function createStore(reducer: Reducer, initialState?: any): Store;
|
||||
function bindActionCreators<T>(actionCreators: T, dispatch: Dispatch): T;
|
||||
function combineReducers(reducers: any): Reducer;
|
||||
function applyMiddleware(...middlewares: Middleware[]): Function;
|
||||
function compose<T extends Function>(...functions: Function[]): T;
|
||||
}
|
||||
|
||||
declare module "redux" {
|
||||
export = Redux;
|
||||
}
|
||||
12
samples/react/MusicStore/typings/tsd.d.ts
vendored
12
samples/react/MusicStore/typings/tsd.d.ts
vendored
@@ -1,12 +0,0 @@
|
||||
/// <reference path="react-redux/react-redux.d.ts" />
|
||||
/// <reference path="react/react-dom.d.ts" />
|
||||
/// <reference path="react/react.d.ts" />
|
||||
/// <reference path="redux/redux.d.ts" />
|
||||
/// <reference path="webpack/webpack-env.d.ts" />
|
||||
/// <reference path="react-bootstrap/react-bootstrap.d.ts" />
|
||||
/// <reference path="react-router/history.d.ts" />
|
||||
/// <reference path="react-router/react-router.d.ts" />
|
||||
/// <reference path="react-router-bootstrap/react-router-bootstrap.d.ts" />
|
||||
/// <reference path="react-router-redux/react-router-redux.d.ts" />
|
||||
/// <reference path="redux-thunk/redux-thunk.d.ts" />
|
||||
/// <reference path="whatwg-fetch/whatwg-fetch.d.ts" />
|
||||
@@ -1,232 +0,0 @@
|
||||
// Type definitions for webpack 1.12.2 (module API)
|
||||
// Project: https://github.com/webpack/webpack
|
||||
// Definitions by: use-strict <https://github.com/use-strict>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
/**
|
||||
* Webpack module API - variables and global functions available inside modules
|
||||
*/
|
||||
|
||||
declare namespace __WebpackModuleApi {
|
||||
interface RequireContext {
|
||||
keys(): string[];
|
||||
<T>(id: string): T;
|
||||
resolve(id: string): string;
|
||||
}
|
||||
|
||||
interface RequireFunction {
|
||||
/**
|
||||
* Returns the exports from a dependency. The call is sync. No request to the server is fired. The compiler ensures that the dependency is available.
|
||||
*/
|
||||
<T>(path: string): T;
|
||||
/**
|
||||
* Behaves similar to require.ensure, but the callback is called with the exports of each dependency in the paths array. There is no option to provide a chunk name.
|
||||
*/
|
||||
(paths: string[], callback: (...modules: any[]) => void): void;
|
||||
/**
|
||||
* Download additional dependencies on demand. The paths array lists modules that should be available. When they are, callback is called. If the callback is a function expression, dependencies in that source part are extracted and also loaded on demand. A single request is fired to the server, except if all modules are already available.
|
||||
*
|
||||
* This creates a chunk. The chunk can be named. If a chunk with this name already exists, the dependencies are merged into that chunk and that chunk is used.
|
||||
*/
|
||||
ensure: (paths: string[], callback: (require: <T>(path: string) => T) => void, chunkName?: string) => void;
|
||||
context: (path: string, deep?: boolean, filter?: RegExp) => RequireContext;
|
||||
/**
|
||||
* Returns the module id of a dependency. The call is sync. No request to the server is fired. The compiler ensures that the dependency is available.
|
||||
*
|
||||
* The module id is a number in webpack (in contrast to node.js where it is a string, the filename).
|
||||
*/
|
||||
resolve(path: string): number;
|
||||
/**
|
||||
* Like require.resolve, but doesn’t include the module into the bundle. It’s a weak dependency.
|
||||
*/
|
||||
resolveWeak(path: string): number;
|
||||
/**
|
||||
* Ensures that the dependency is available, but don’t execute it. This can be use for optimizing the position of a module in the chunks.
|
||||
*/
|
||||
include(path: string): void;
|
||||
/**
|
||||
* Multiple requires to the same module result in only one module execution and only one export. Therefore a cache in the runtime exists. Removing values from this cache cause new module execution and a new export. This is only needed in rare cases (for compatibility!).
|
||||
*/
|
||||
cache: {
|
||||
[id: string]: any;
|
||||
}
|
||||
}
|
||||
|
||||
interface Module {
|
||||
exports: any;
|
||||
require(id: string): any;
|
||||
id: string;
|
||||
filename: string;
|
||||
loaded: boolean;
|
||||
parent: any;
|
||||
children: any[];
|
||||
hot: Hot;
|
||||
}
|
||||
type ModuleId = string|number;
|
||||
|
||||
interface Hot {
|
||||
/**
|
||||
* Accept code updates for the specified dependencies. The callback is called when dependencies were replaced.
|
||||
* @param dependencies
|
||||
* @param callback
|
||||
*/
|
||||
accept(dependencies: string[], callback: (updatedDependencies: ModuleId[]) => void): void;
|
||||
/**
|
||||
* Accept code updates for the specified dependencies. The callback is called when dependencies were replaced.
|
||||
* @param dependency
|
||||
* @param callback
|
||||
*/
|
||||
accept(dependency: string, callback: () => void): void;
|
||||
/**
|
||||
* Accept code updates for this module without notification of parents.
|
||||
* This should only be used if the module doesn’t export anything.
|
||||
* The errHandler can be used to handle errors that occur while loading the updated module.
|
||||
* @param errHandler
|
||||
*/
|
||||
accept(errHandler?: (err: Error) => void): void;
|
||||
/**
|
||||
* Do not accept updates for the specified dependencies. If any dependencies is updated, the code update fails with code "decline".
|
||||
*/
|
||||
decline(dependencies: string[]): void;
|
||||
/**
|
||||
* Do not accept updates for the specified dependencies. If any dependencies is updated, the code update fails with code "decline".
|
||||
*/
|
||||
decline(dependency: string): void;
|
||||
/**
|
||||
* Flag the current module as not update-able. If updated the update code would fail with code "decline".
|
||||
*/
|
||||
decline(): void;
|
||||
/**
|
||||
* Add a one time handler, which is executed when the current module code is replaced.
|
||||
* Here you should destroy/remove any persistent resource you have claimed/created.
|
||||
* If you want to transfer state to the new module, add it to data object.
|
||||
* The data will be available at module.hot.data on the new module.
|
||||
* @param callback
|
||||
*/
|
||||
dispose<T>(callback: (data: T) => void): void;
|
||||
/**
|
||||
* Add a one time handler, which is executed when the current module code is replaced.
|
||||
* Here you should destroy/remove any persistent resource you have claimed/created.
|
||||
* If you want to transfer state to the new module, add it to data object.
|
||||
* The data will be available at module.hot.data on the new module.
|
||||
* @param callback
|
||||
*/
|
||||
addDisposeHandler<T>(callback: (data: T) => void): void;
|
||||
/**
|
||||
* Remove a handler.
|
||||
* This can useful to add a temporary dispose handler. You could i. e. replace code while in the middle of a multi-step async function.
|
||||
* @param callback
|
||||
*/
|
||||
removeDisposeHandler<T>(callback: (data: T) => void): void;
|
||||
/**
|
||||
* Throws an exceptions if status() is not idle.
|
||||
* Check all currently loaded modules for updates and apply updates if found.
|
||||
* If no update was found, the callback is called with null.
|
||||
* If autoApply is truthy the callback will be called with all modules that were disposed.
|
||||
* apply() is automatically called with autoApply as options parameter.
|
||||
* If autoApply is not set the callback will be called with all modules that will be disposed on apply().
|
||||
* @param autoApply
|
||||
* @param callback
|
||||
*/
|
||||
check(autoApply: boolean, callback: (err: Error, outdatedModules: ModuleId[]) => void): void;
|
||||
/**
|
||||
* Throws an exceptions if status() is not idle.
|
||||
* Check all currently loaded modules for updates and apply updates if found.
|
||||
* If no update was found, the callback is called with null.
|
||||
* The callback will be called with all modules that will be disposed on apply().
|
||||
* @param callback
|
||||
*/
|
||||
check(callback: (err: Error, outdatedModules: ModuleId[]) => void): void;
|
||||
/**
|
||||
* If status() != "ready" it throws an error.
|
||||
* Continue the update process.
|
||||
* @param options
|
||||
* @param callback
|
||||
*/
|
||||
apply(options: AcceptOptions, callback: (err: Error, outdatedModules: ModuleId[]) => void): void;
|
||||
/**
|
||||
* If status() != "ready" it throws an error.
|
||||
* Continue the update process.
|
||||
* @param callback
|
||||
*/
|
||||
apply(callback: (err: Error, outdatedModules: ModuleId[]) => void): void;
|
||||
/**
|
||||
* Return one of idle, check, watch, watch-delay, prepare, ready, dispose, apply, abort or fail.
|
||||
*/
|
||||
status(): string;
|
||||
/** Register a callback on status change. */
|
||||
status(callback: (status: string) => void): void;
|
||||
/** Register a callback on status change. */
|
||||
addStatusHandler(callback: (status: string) => void): void;
|
||||
/**
|
||||
* Remove a registered status change handler.
|
||||
* @param callback
|
||||
*/
|
||||
removeStatusHandler(callback: (status: string) => void): void;
|
||||
|
||||
active: boolean;
|
||||
data: {};
|
||||
}
|
||||
|
||||
interface AcceptOptions {
|
||||
/**
|
||||
* If true the update process continues even if some modules are not accepted (and would bubble to the entry point).
|
||||
*/
|
||||
ignoreUnaccepted?: boolean;
|
||||
/**
|
||||
* Indicates that apply() is automatically called by check function
|
||||
*/
|
||||
autoApply?: boolean;
|
||||
}
|
||||
}
|
||||
|
||||
declare var require: __WebpackModuleApi.RequireFunction;
|
||||
|
||||
/**
|
||||
* The resource query of the current module.
|
||||
*
|
||||
* e.g. __resourceQuery === "?test" // Inside "file.js?test"
|
||||
*/
|
||||
declare var __resourceQuery: string;
|
||||
|
||||
/**
|
||||
* Equals the config options output.publicPath.
|
||||
*/
|
||||
declare var __webpack_public_path__: string;
|
||||
|
||||
/**
|
||||
* The raw require function. This expression isn’t parsed by the Parser for dependencies.
|
||||
*/
|
||||
declare var __webpack_require__: any;
|
||||
|
||||
/**
|
||||
* The internal chunk loading function
|
||||
*
|
||||
* @param chunkId The id for the chunk to load.
|
||||
* @param callback A callback function called once the chunk is loaded.
|
||||
*/
|
||||
declare var __webpack_chunk_load__: (chunkId: any, callback: (require: (id: string) => any) => void) => void;
|
||||
|
||||
/**
|
||||
* Access to the internal object of all modules.
|
||||
*/
|
||||
declare var __webpack_modules__: any[];
|
||||
|
||||
/**
|
||||
* Access to the hash of the compilation.
|
||||
*
|
||||
* Only available with the HotModuleReplacementPlugin or the ExtendedAPIPlugin
|
||||
*/
|
||||
declare var __webpack_hash__: any;
|
||||
|
||||
/**
|
||||
* Generates a require function that is not parsed by webpack. Can be used to do cool stuff with a global require function if available.
|
||||
*/
|
||||
declare var __non_webpack_require__: any;
|
||||
|
||||
/**
|
||||
* Equals the config option debug
|
||||
*/
|
||||
declare var DEBUG: boolean;
|
||||
|
||||
declare var module: __WebpackModuleApi.Module;
|
||||
@@ -1,85 +0,0 @@
|
||||
// Type definitions for fetch API
|
||||
// Project: https://github.com/github/fetch
|
||||
// Definitions by: Ryan Graham <https://github.com/ryan-codingintrigue>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
declare class Request extends Body {
|
||||
constructor(input: string|Request, init?:RequestInit);
|
||||
method: string;
|
||||
url: string;
|
||||
headers: Headers;
|
||||
context: string|RequestContext;
|
||||
referrer: string;
|
||||
mode: string|RequestMode;
|
||||
credentials: string|RequestCredentials;
|
||||
cache: string|RequestCache;
|
||||
}
|
||||
|
||||
interface RequestInit {
|
||||
method?: string;
|
||||
headers?: HeaderInit|{ [index: string]: string };
|
||||
body?: BodyInit;
|
||||
mode?: string|RequestMode;
|
||||
credentials?: string|RequestCredentials;
|
||||
cache?: string|RequestCache;
|
||||
}
|
||||
|
||||
declare enum RequestContext {
|
||||
"audio", "beacon", "cspreport", "download", "embed", "eventsource", "favicon", "fetch",
|
||||
"font", "form", "frame", "hyperlink", "iframe", "image", "imageset", "import",
|
||||
"internal", "location", "manifest", "object", "ping", "plugin", "prefetch", "script",
|
||||
"serviceworker", "sharedworker", "subresource", "style", "track", "video", "worker",
|
||||
"xmlhttprequest", "xslt"
|
||||
}
|
||||
declare enum RequestMode { "same-origin", "no-cors", "cors" }
|
||||
declare enum RequestCredentials { "omit", "same-origin", "include" }
|
||||
declare enum RequestCache { "default", "no-store", "reload", "no-cache", "force-cache", "only-if-cached" }
|
||||
|
||||
declare class Headers {
|
||||
append(name: string, value: string): void;
|
||||
delete(name: string):void;
|
||||
get(name: string): string;
|
||||
getAll(name: string): Array<string>;
|
||||
has(name: string): boolean;
|
||||
set(name: string, value: string): void;
|
||||
}
|
||||
|
||||
declare class Body {
|
||||
bodyUsed: boolean;
|
||||
arrayBuffer(): Promise<ArrayBuffer>;
|
||||
blob(): Promise<Blob>;
|
||||
formData(): Promise<FormData>;
|
||||
json(): Promise<any>;
|
||||
json<T>(): Promise<T>;
|
||||
text(): Promise<string>;
|
||||
}
|
||||
declare class Response extends Body {
|
||||
constructor(body?: BodyInit, init?: ResponseInit);
|
||||
error(): Response;
|
||||
redirect(url: string, status: number): Response;
|
||||
type: string|ResponseType;
|
||||
url: string;
|
||||
status: number;
|
||||
ok: boolean;
|
||||
statusText: string;
|
||||
headers: Headers;
|
||||
clone(): Response;
|
||||
}
|
||||
|
||||
declare enum ResponseType { "basic", "cors", "default", "error", "opaque" }
|
||||
|
||||
interface ResponseInit {
|
||||
status: number;
|
||||
statusText?: string;
|
||||
headers?: HeaderInit;
|
||||
}
|
||||
|
||||
declare type HeaderInit = Headers|Array<string>;
|
||||
declare type BodyInit = Blob|FormData|string;
|
||||
declare type RequestInfo = Request|string;
|
||||
|
||||
interface Window {
|
||||
fetch(url: string|Request, init?: RequestInit): Promise<Response>;
|
||||
}
|
||||
|
||||
declare var fetch: typeof window.fetch;
|
||||
@@ -9,14 +9,31 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.AngularServices
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for prepopulating Angular 2's 'http' service with data.
|
||||
/// </summary>
|
||||
public static class PrimeCacheHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs an HTTP GET request to the specified URL and adds the resulting JSON data
|
||||
/// to the Angular 'http' service cache.
|
||||
/// </summary>
|
||||
/// <param name="html">The <see cref="IHtmlHelper"/>.</param>
|
||||
/// <param name="url">The URL to be requested.</param>
|
||||
/// <returns>A task representing the HTML content to be rendered into the document.</returns>
|
||||
[Obsolete("Use PrimeCacheAsync instead")]
|
||||
public static Task<IHtmlContent> PrimeCache(this IHtmlHelper html, string url)
|
||||
{
|
||||
return PrimeCacheAsync(html, url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an HTTP GET request to the specified URL and adds the resulting JSON data
|
||||
/// to the Angular 'http' service cache.
|
||||
/// </summary>
|
||||
/// <param name="html">The <see cref="IHtmlHelper"/>.</param>
|
||||
/// <param name="url">The URL to be requested.</param>
|
||||
/// <returns>A task representing the HTML content to be rendered into the document.</returns>
|
||||
public static async Task<IHtmlContent> PrimeCacheAsync(this IHtmlHelper html, string url)
|
||||
{
|
||||
// TODO: Consider deduplicating the PrimeCacheAsync calls (that is, if there are multiple requests to precache
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: AssemblyMetadata("Serviceable", "True")]
|
||||
[assembly: NeutralResourcesLanguage("en-us")]
|
||||
[assembly: AssemblyCompany("Microsoft Corporation.")]
|
||||
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
|
||||
[assembly: AssemblyProduct("Microsoft ASP.NET Core")]
|
||||
@@ -5,21 +5,28 @@
|
||||
"main": "./dist/Exports",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"prepublish": "rimraf *.d.ts dist/*.d.ts && tsd install && tsc && node build.js"
|
||||
"prepublish": "rimraf *.d.ts dist/*.d.ts && tsc && node build.js"
|
||||
},
|
||||
"typings": "dist/Exports",
|
||||
"author": "Microsoft",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/aspnet/JavaScriptServices/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aspnet/JavaScriptServices.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"angular2": "^2.0.0-beta.13",
|
||||
"angular2": "2.0.0-beta.13",
|
||||
"reflect-metadata": "0.1.2",
|
||||
"rxjs": "5.0.0-beta.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"es6-shim": "^0.35.0",
|
||||
"reflect-metadata": "^0.1.2",
|
||||
"rimraf": "^2.5.4",
|
||||
"systemjs-builder": "^0.14.11",
|
||||
"typescript": "^1.8.10",
|
||||
"typescript": "^2.0.0",
|
||||
"zone.js": "^0.6.10"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
"declaration": true,
|
||||
"experimentalDecorators": true,
|
||||
"noLib": false,
|
||||
"outDir": "./dist"
|
||||
"outDir": "./dist",
|
||||
"lib": ["es2015", "dom"]
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"version": "v4",
|
||||
"repo": "borisyankov/DefinitelyTyped",
|
||||
"ref": "master",
|
||||
"path": "typings",
|
||||
"bundle": "typings/tsd.d.ts",
|
||||
"installed": {
|
||||
"es6-shim/es6-shim.d.ts": {
|
||||
"commit": "ec9eb4b28c74665a602c22db3457f0a76fa0fa23"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,668 +0,0 @@
|
||||
// Type definitions for es6-shim v0.31.2
|
||||
// Project: https://github.com/paulmillr/es6-shim
|
||||
// Definitions by: Ron Buckton <http://github.com/rbuckton>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
|
||||
declare type PropertyKey = string | number | symbol;
|
||||
|
||||
interface IteratorResult<T> {
|
||||
done: boolean;
|
||||
value?: T;
|
||||
}
|
||||
|
||||
interface IterableShim<T> {
|
||||
/**
|
||||
* Shim for an ES6 iterable. Not intended for direct use by user code.
|
||||
*/
|
||||
"_es6-shim iterator_"(): Iterator<T>;
|
||||
}
|
||||
|
||||
interface Iterator<T> {
|
||||
next(value?: any): IteratorResult<T>;
|
||||
return?(value?: any): IteratorResult<T>;
|
||||
throw?(e?: any): IteratorResult<T>;
|
||||
}
|
||||
|
||||
interface IterableIteratorShim<T> extends IterableShim<T>, Iterator<T> {
|
||||
/**
|
||||
* Shim for an ES6 iterable iterator. Not intended for direct use by user code.
|
||||
*/
|
||||
"_es6-shim iterator_"(): IterableIteratorShim<T>;
|
||||
}
|
||||
|
||||
interface StringConstructor {
|
||||
/**
|
||||
* Return the String value whose elements are, in order, the elements in the List elements.
|
||||
* If length is 0, the empty string is returned.
|
||||
*/
|
||||
fromCodePoint(...codePoints: number[]): string;
|
||||
|
||||
/**
|
||||
* String.raw is intended for use as a tag function of a Tagged Template String. When called
|
||||
* as such the first argument will be a well formed template call site object and the rest
|
||||
* parameter will contain the substitution values.
|
||||
* @param template A well-formed template string call site representation.
|
||||
* @param substitutions A set of substitution values.
|
||||
*/
|
||||
raw(template: TemplateStringsArray, ...substitutions: any[]): string;
|
||||
}
|
||||
|
||||
interface String {
|
||||
/**
|
||||
* Returns a nonnegative integer Number less than 1114112 (0x110000) that is the code point
|
||||
* value of the UTF-16 encoded code point starting at the string element at position pos in
|
||||
* the String resulting from converting this object to a String.
|
||||
* If there is no element at that position, the result is undefined.
|
||||
* If a valid UTF-16 surrogate pair does not begin at pos, the result is the code unit at pos.
|
||||
*/
|
||||
codePointAt(pos: number): number;
|
||||
|
||||
/**
|
||||
* Returns true if searchString appears as a substring of the result of converting this
|
||||
* object to a String, at one or more positions that are
|
||||
* greater than or equal to position; otherwise, returns false.
|
||||
* @param searchString search string
|
||||
* @param position If position is undefined, 0 is assumed, so as to search all of the String.
|
||||
*/
|
||||
includes(searchString: string, position?: number): boolean;
|
||||
|
||||
/**
|
||||
* Returns true if the sequence of elements of searchString converted to a String is the
|
||||
* same as the corresponding elements of this object (converted to a String) starting at
|
||||
* endPosition – length(this). Otherwise returns false.
|
||||
*/
|
||||
endsWith(searchString: string, endPosition?: number): boolean;
|
||||
|
||||
/**
|
||||
* Returns a String value that is made from count copies appended together. If count is 0,
|
||||
* T is the empty String is returned.
|
||||
* @param count number of copies to append
|
||||
*/
|
||||
repeat(count: number): string;
|
||||
|
||||
/**
|
||||
* Returns true if the sequence of elements of searchString converted to a String is the
|
||||
* same as the corresponding elements of this object (converted to a String) starting at
|
||||
* position. Otherwise returns false.
|
||||
*/
|
||||
startsWith(searchString: string, position?: number): boolean;
|
||||
|
||||
/**
|
||||
* Returns an <a> HTML anchor element and sets the name attribute to the text value
|
||||
* @param name
|
||||
*/
|
||||
anchor(name: string): string;
|
||||
|
||||
/** Returns a <big> HTML element */
|
||||
big(): string;
|
||||
|
||||
/** Returns a <blink> HTML element */
|
||||
blink(): string;
|
||||
|
||||
/** Returns a <b> HTML element */
|
||||
bold(): string;
|
||||
|
||||
/** Returns a <tt> HTML element */
|
||||
fixed(): string
|
||||
|
||||
/** Returns a <font> HTML element and sets the color attribute value */
|
||||
fontcolor(color: string): string
|
||||
|
||||
/** Returns a <font> HTML element and sets the size attribute value */
|
||||
fontsize(size: number): string;
|
||||
|
||||
/** Returns a <font> HTML element and sets the size attribute value */
|
||||
fontsize(size: string): string;
|
||||
|
||||
/** Returns an <i> HTML element */
|
||||
italics(): string;
|
||||
|
||||
/** Returns an <a> HTML element and sets the href attribute value */
|
||||
link(url: string): string;
|
||||
|
||||
/** Returns a <small> HTML element */
|
||||
small(): string;
|
||||
|
||||
/** Returns a <strike> HTML element */
|
||||
strike(): string;
|
||||
|
||||
/** Returns a <sub> HTML element */
|
||||
sub(): string;
|
||||
|
||||
/** Returns a <sup> HTML element */
|
||||
sup(): string;
|
||||
|
||||
/**
|
||||
* Shim for an ES6 iterable. Not intended for direct use by user code.
|
||||
*/
|
||||
"_es6-shim iterator_"(): IterableIteratorShim<string>;
|
||||
}
|
||||
|
||||
interface ArrayConstructor {
|
||||
/**
|
||||
* Creates an array from an array-like object.
|
||||
* @param arrayLike An array-like object to convert to an array.
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): Array<U>;
|
||||
|
||||
/**
|
||||
* Creates an array from an iterable object.
|
||||
* @param iterable An iterable object to convert to an array.
|
||||
* @param mapfn A mapping function to call on every element of the array.
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from<T, U>(iterable: IterableShim<T>, mapfn: (v: T, k: number) => U, thisArg?: any): Array<U>;
|
||||
|
||||
/**
|
||||
* Creates an array from an array-like object.
|
||||
* @param arrayLike An array-like object to convert to an array.
|
||||
*/
|
||||
from<T>(arrayLike: ArrayLike<T>): Array<T>;
|
||||
|
||||
/**
|
||||
* Creates an array from an iterable object.
|
||||
* @param iterable An iterable object to convert to an array.
|
||||
*/
|
||||
from<T>(iterable: IterableShim<T>): Array<T>;
|
||||
|
||||
/**
|
||||
* Returns a new array from a set of elements.
|
||||
* @param items A set of elements to include in the new array object.
|
||||
*/
|
||||
of<T>(...items: T[]): Array<T>;
|
||||
}
|
||||
|
||||
interface Array<T> {
|
||||
/**
|
||||
* Returns the value of the first element in the array where predicate is true, and undefined
|
||||
* otherwise.
|
||||
* @param predicate find calls predicate once for each element of the array, in ascending
|
||||
* order, until it finds one where predicate returns true. If such an element is found, find
|
||||
* immediately returns that element value. Otherwise, find returns undefined.
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
find(predicate: (value: T, index: number, obj: Array<T>) => boolean, thisArg?: any): T;
|
||||
|
||||
/**
|
||||
* Returns the index of the first element in the array where predicate is true, and undefined
|
||||
* otherwise.
|
||||
* @param predicate find calls predicate once for each element of the array, in ascending
|
||||
* order, until it finds one where predicate returns true. If such an element is found, find
|
||||
* immediately returns that element value. Otherwise, find returns undefined.
|
||||
* @param thisArg If provided, it will be used as the this value for each invocation of
|
||||
* predicate. If it is not provided, undefined is used instead.
|
||||
*/
|
||||
findIndex(predicate: (value: T) => boolean, thisArg?: any): number;
|
||||
|
||||
/**
|
||||
* Returns the this object after filling the section identified by start and end with value
|
||||
* @param value value to fill array section with
|
||||
* @param start index to start filling the array at. If start is negative, it is treated as
|
||||
* length+start where length is the length of the array.
|
||||
* @param end index to stop filling the array at. If end is negative, it is treated as
|
||||
* length+end.
|
||||
*/
|
||||
fill(value: T, start?: number, end?: number): T[];
|
||||
|
||||
/**
|
||||
* Returns the this object after copying a section of the array identified by start and end
|
||||
* to the same array starting at position target
|
||||
* @param target If target is negative, it is treated as length+target where length is the
|
||||
* length of the array.
|
||||
* @param start If start is negative, it is treated as length+start. If end is negative, it
|
||||
* is treated as length+end.
|
||||
* @param end If not specified, length of the this object is used as its default value.
|
||||
*/
|
||||
copyWithin(target: number, start: number, end?: number): T[];
|
||||
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the array
|
||||
*/
|
||||
entries(): IterableIteratorShim<[number, T]>;
|
||||
|
||||
/**
|
||||
* Returns an list of keys in the array
|
||||
*/
|
||||
keys(): IterableIteratorShim<number>;
|
||||
|
||||
/**
|
||||
* Returns an list of values in the array
|
||||
*/
|
||||
values(): IterableIteratorShim<T>;
|
||||
|
||||
/**
|
||||
* Shim for an ES6 iterable. Not intended for direct use by user code.
|
||||
*/
|
||||
"_es6-shim iterator_"(): IterableIteratorShim<T>;
|
||||
}
|
||||
|
||||
interface NumberConstructor {
|
||||
/**
|
||||
* The value of Number.EPSILON is the difference between 1 and the smallest value greater than 1
|
||||
* that is representable as a Number value, which is approximately:
|
||||
* 2.2204460492503130808472633361816 x 10−16.
|
||||
*/
|
||||
EPSILON: number;
|
||||
|
||||
/**
|
||||
* Returns true if passed value is finite.
|
||||
* Unlike the global isFininte, Number.isFinite doesn't forcibly convert the parameter to a
|
||||
* number. Only finite values of the type number, result in true.
|
||||
* @param number A numeric value.
|
||||
*/
|
||||
isFinite(number: number): boolean;
|
||||
|
||||
/**
|
||||
* Returns true if the value passed is an integer, false otherwise.
|
||||
* @param number A numeric value.
|
||||
*/
|
||||
isInteger(number: number): boolean;
|
||||
|
||||
/**
|
||||
* Returns a Boolean value that indicates whether a value is the reserved value NaN (not a
|
||||
* number). Unlike the global isNaN(), Number.isNaN() doesn't forcefully convert the parameter
|
||||
* to a number. Only values of the type number, that are also NaN, result in true.
|
||||
* @param number A numeric value.
|
||||
*/
|
||||
isNaN(number: number): boolean;
|
||||
|
||||
/**
|
||||
* Returns true if the value passed is a safe integer.
|
||||
* @param number A numeric value.
|
||||
*/
|
||||
isSafeInteger(number: number): boolean;
|
||||
|
||||
/**
|
||||
* The value of the largest integer n such that n and n + 1 are both exactly representable as
|
||||
* a Number value.
|
||||
* The value of Number.MIN_SAFE_INTEGER is 9007199254740991 2^53 − 1.
|
||||
*/
|
||||
MAX_SAFE_INTEGER: number;
|
||||
|
||||
/**
|
||||
* The value of the smallest integer n such that n and n − 1 are both exactly representable as
|
||||
* a Number value.
|
||||
* The value of Number.MIN_SAFE_INTEGER is −9007199254740991 (−(2^53 − 1)).
|
||||
*/
|
||||
MIN_SAFE_INTEGER: number;
|
||||
|
||||
/**
|
||||
* Converts a string to a floating-point number.
|
||||
* @param string A string that contains a floating-point number.
|
||||
*/
|
||||
parseFloat(string: string): number;
|
||||
|
||||
/**
|
||||
* Converts A string to an integer.
|
||||
* @param s A string to convert into a number.
|
||||
* @param radix A value between 2 and 36 that specifies the base of the number in numString.
|
||||
* If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal.
|
||||
* All other strings are considered decimal.
|
||||
*/
|
||||
parseInt(string: string, radix?: number): number;
|
||||
}
|
||||
|
||||
interface ObjectConstructor {
|
||||
/**
|
||||
* Copy the values of all of the enumerable own properties from one or more source objects to a
|
||||
* target object. Returns the target object.
|
||||
* @param target The target object to copy to.
|
||||
* @param sources One or more source objects to copy properties from.
|
||||
*/
|
||||
assign(target: any, ...sources: any[]): any;
|
||||
|
||||
/**
|
||||
* Returns true if the values are the same value, false otherwise.
|
||||
* @param value1 The first value.
|
||||
* @param value2 The second value.
|
||||
*/
|
||||
is(value1: any, value2: any): boolean;
|
||||
|
||||
/**
|
||||
* Sets the prototype of a specified object o to object proto or null. Returns the object o.
|
||||
* @param o The object to change its prototype.
|
||||
* @param proto The value of the new prototype or null.
|
||||
* @remarks Requires `__proto__` support.
|
||||
*/
|
||||
setPrototypeOf(o: any, proto: any): any;
|
||||
}
|
||||
|
||||
interface RegExp {
|
||||
/**
|
||||
* Returns a string indicating the flags of the regular expression in question. This field is read-only.
|
||||
* The characters in this string are sequenced and concatenated in the following order:
|
||||
*
|
||||
* - "g" for global
|
||||
* - "i" for ignoreCase
|
||||
* - "m" for multiline
|
||||
* - "u" for unicode
|
||||
* - "y" for sticky
|
||||
*
|
||||
* If no flags are set, the value is the empty string.
|
||||
*/
|
||||
flags: string;
|
||||
}
|
||||
|
||||
interface Math {
|
||||
/**
|
||||
* Returns the number of leading zero bits in the 32-bit binary representation of a number.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
clz32(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the result of 32-bit multiplication of two numbers.
|
||||
* @param x First number
|
||||
* @param y Second number
|
||||
*/
|
||||
imul(x: number, y: number): number;
|
||||
|
||||
/**
|
||||
* Returns the sign of the x, indicating whether x is positive, negative or zero.
|
||||
* @param x The numeric expression to test
|
||||
*/
|
||||
sign(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the base 10 logarithm of a number.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
log10(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the base 2 logarithm of a number.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
log2(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the natural logarithm of 1 + x.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
log1p(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the result of (e^x - 1) of x (e raised to the power of x, where e is the base of
|
||||
* the natural logarithms).
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
expm1(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic cosine of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
cosh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic sine of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
sinh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the hyperbolic tangent of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
tanh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic cosine of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
acosh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic sine of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
asinh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the inverse hyperbolic tangent of a number.
|
||||
* @param x A numeric expression that contains an angle measured in radians.
|
||||
*/
|
||||
atanh(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the square root of the sum of squares of its arguments.
|
||||
* @param values Values to compute the square root for.
|
||||
* If no arguments are passed, the result is +0.
|
||||
* If there is only one argument, the result is the absolute value.
|
||||
* If any argument is +Infinity or -Infinity, the result is +Infinity.
|
||||
* If any argument is NaN, the result is NaN.
|
||||
* If all arguments are either +0 or −0, the result is +0.
|
||||
*/
|
||||
hypot(...values: number[]): number;
|
||||
|
||||
/**
|
||||
* Returns the integral part of the a numeric expression, x, removing any fractional digits.
|
||||
* If x is already an integer, the result is x.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
trunc(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns the nearest single precision float representation of a number.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
fround(x: number): number;
|
||||
|
||||
/**
|
||||
* Returns an implementation-dependent approximation to the cube root of number.
|
||||
* @param x A numeric expression.
|
||||
*/
|
||||
cbrt(x: number): number;
|
||||
}
|
||||
|
||||
interface PromiseLike<T> {
|
||||
/**
|
||||
* Attaches callbacks for the resolution and/or rejection of the Promise.
|
||||
* @param onfulfilled The callback to execute when the Promise is resolved.
|
||||
* @param onrejected The callback to execute when the Promise is rejected.
|
||||
* @returns A Promise for the completion of which ever callback is executed.
|
||||
*/
|
||||
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>;
|
||||
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): PromiseLike<TResult>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the completion of an asynchronous operation
|
||||
*/
|
||||
interface Promise<T> {
|
||||
/**
|
||||
* Attaches callbacks for the resolution and/or rejection of the Promise.
|
||||
* @param onfulfilled The callback to execute when the Promise is resolved.
|
||||
* @param onrejected The callback to execute when the Promise is rejected.
|
||||
* @returns A Promise for the completion of which ever callback is executed.
|
||||
*/
|
||||
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): Promise<TResult>;
|
||||
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): Promise<TResult>;
|
||||
|
||||
/**
|
||||
* Attaches a callback for only the rejection of the Promise.
|
||||
* @param onrejected The callback to execute when the Promise is rejected.
|
||||
* @returns A Promise for the completion of the callback.
|
||||
*/
|
||||
catch(onrejected?: (reason: any) => T | PromiseLike<T>): Promise<T>;
|
||||
catch(onrejected?: (reason: any) => void): Promise<T>;
|
||||
}
|
||||
|
||||
interface PromiseConstructor {
|
||||
/**
|
||||
* A reference to the prototype.
|
||||
*/
|
||||
prototype: Promise<any>;
|
||||
|
||||
/**
|
||||
* Creates a new Promise.
|
||||
* @param executor A callback used to initialize the promise. This callback is passed two arguments:
|
||||
* a resolve callback used resolve the promise with a value or the result of another promise,
|
||||
* and a reject callback used to reject the promise with a provided reason or error.
|
||||
*/
|
||||
new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): Promise<T>;
|
||||
|
||||
/**
|
||||
* Creates a Promise that is resolved with an array of results when all of the provided Promises
|
||||
* resolve, or rejected when any Promise is rejected.
|
||||
* @param values An array of Promises.
|
||||
* @returns A new Promise.
|
||||
*/
|
||||
all<T>(values: IterableShim<T | PromiseLike<T>>): Promise<T[]>;
|
||||
|
||||
/**
|
||||
* Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
|
||||
* or rejected.
|
||||
* @param values An array of Promises.
|
||||
* @returns A new Promise.
|
||||
*/
|
||||
race<T>(values: IterableShim<T | PromiseLike<T>>): Promise<T>;
|
||||
|
||||
/**
|
||||
* Creates a new rejected promise for the provided reason.
|
||||
* @param reason The reason the promise was rejected.
|
||||
* @returns A new rejected Promise.
|
||||
*/
|
||||
reject(reason: any): Promise<void>;
|
||||
|
||||
/**
|
||||
* Creates a new rejected promise for the provided reason.
|
||||
* @param reason The reason the promise was rejected.
|
||||
* @returns A new rejected Promise.
|
||||
*/
|
||||
reject<T>(reason: any): Promise<T>;
|
||||
|
||||
/**
|
||||
* Creates a new resolved promise for the provided value.
|
||||
* @param value A promise.
|
||||
* @returns A promise whose internal state matches the provided promise.
|
||||
*/
|
||||
resolve<T>(value: T | PromiseLike<T>): Promise<T>;
|
||||
|
||||
/**
|
||||
* Creates a new resolved promise .
|
||||
* @returns A resolved promise.
|
||||
*/
|
||||
resolve(): Promise<void>;
|
||||
}
|
||||
|
||||
declare var Promise: PromiseConstructor;
|
||||
|
||||
interface Map<K, V> {
|
||||
clear(): void;
|
||||
delete(key: K): boolean;
|
||||
forEach(callbackfn: (value: V, index: K, map: Map<K, V>) => void, thisArg?: any): void;
|
||||
get(key: K): V;
|
||||
has(key: K): boolean;
|
||||
set(key: K, value?: V): Map<K, V>;
|
||||
size: number;
|
||||
entries(): IterableIteratorShim<[K, V]>;
|
||||
keys(): IterableIteratorShim<K>;
|
||||
values(): IterableIteratorShim<V>;
|
||||
}
|
||||
|
||||
interface MapConstructor {
|
||||
new <K, V>(): Map<K, V>;
|
||||
new <K, V>(iterable: IterableShim<[K, V]>): Map<K, V>;
|
||||
prototype: Map<any, any>;
|
||||
}
|
||||
|
||||
declare var Map: MapConstructor;
|
||||
|
||||
interface Set<T> {
|
||||
add(value: T): Set<T>;
|
||||
clear(): void;
|
||||
delete(value: T): boolean;
|
||||
forEach(callbackfn: (value: T, index: T, set: Set<T>) => void, thisArg?: any): void;
|
||||
has(value: T): boolean;
|
||||
size: number;
|
||||
entries(): IterableIteratorShim<[T, T]>;
|
||||
keys(): IterableIteratorShim<T>;
|
||||
values(): IterableIteratorShim<T>;
|
||||
}
|
||||
|
||||
interface SetConstructor {
|
||||
new <T>(): Set<T>;
|
||||
new <T>(iterable: IterableShim<T>): Set<T>;
|
||||
prototype: Set<any>;
|
||||
}
|
||||
|
||||
declare var Set: SetConstructor;
|
||||
|
||||
interface WeakMap<K, V> {
|
||||
delete(key: K): boolean;
|
||||
get(key: K): V;
|
||||
has(key: K): boolean;
|
||||
set(key: K, value?: V): WeakMap<K, V>;
|
||||
}
|
||||
|
||||
interface WeakMapConstructor {
|
||||
new <K, V>(): WeakMap<K, V>;
|
||||
new <K, V>(iterable: IterableShim<[K, V]>): WeakMap<K, V>;
|
||||
prototype: WeakMap<any, any>;
|
||||
}
|
||||
|
||||
declare var WeakMap: WeakMapConstructor;
|
||||
|
||||
interface WeakSet<T> {
|
||||
add(value: T): WeakSet<T>;
|
||||
delete(value: T): boolean;
|
||||
has(value: T): boolean;
|
||||
}
|
||||
|
||||
interface WeakSetConstructor {
|
||||
new <T>(): WeakSet<T>;
|
||||
new <T>(iterable: IterableShim<T>): WeakSet<T>;
|
||||
prototype: WeakSet<any>;
|
||||
}
|
||||
|
||||
declare var WeakSet: WeakSetConstructor;
|
||||
|
||||
declare namespace Reflect {
|
||||
function apply(target: Function, thisArgument: any, argumentsList: ArrayLike<any>): any;
|
||||
function construct(target: Function, argumentsList: ArrayLike<any>): any;
|
||||
function defineProperty(target: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean;
|
||||
function deleteProperty(target: any, propertyKey: PropertyKey): boolean;
|
||||
function enumerate(target: any): IterableIteratorShim<any>;
|
||||
function get(target: any, propertyKey: PropertyKey, receiver?: any): any;
|
||||
function getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor;
|
||||
function getPrototypeOf(target: any): any;
|
||||
function has(target: any, propertyKey: PropertyKey): boolean;
|
||||
function isExtensible(target: any): boolean;
|
||||
function ownKeys(target: any): Array<PropertyKey>;
|
||||
function preventExtensions(target: any): boolean;
|
||||
function set(target: any, propertyKey: PropertyKey, value: any, receiver?: any): boolean;
|
||||
function setPrototypeOf(target: any, proto: any): boolean;
|
||||
}
|
||||
|
||||
declare module "es6-shim" {
|
||||
var String: StringConstructor;
|
||||
var Array: ArrayConstructor;
|
||||
var Number: NumberConstructor;
|
||||
var Math: Math;
|
||||
var Object: ObjectConstructor;
|
||||
var Map: MapConstructor;
|
||||
var Set: SetConstructor;
|
||||
var WeakMap: WeakMapConstructor;
|
||||
var WeakSet: WeakSetConstructor;
|
||||
var Promise: PromiseConstructor;
|
||||
namespace Reflect {
|
||||
function apply(target: Function, thisArgument: any, argumentsList: ArrayLike<any>): any;
|
||||
function construct(target: Function, argumentsList: ArrayLike<any>): any;
|
||||
function defineProperty(target: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean;
|
||||
function deleteProperty(target: any, propertyKey: PropertyKey): boolean;
|
||||
function enumerate(target: any): Iterator<any>;
|
||||
function get(target: any, propertyKey: PropertyKey, receiver?: any): any;
|
||||
function getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor;
|
||||
function getPrototypeOf(target: any): any;
|
||||
function has(target: any, propertyKey: PropertyKey): boolean;
|
||||
function isExtensible(target: any): boolean;
|
||||
function ownKeys(target: any): Array<PropertyKey>;
|
||||
function preventExtensions(target: any): boolean;
|
||||
function set(target: any, propertyKey: PropertyKey, value: any, receiver?: any): boolean;
|
||||
function setPrototypeOf(target: any, proto: any): boolean;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
|
||||
/// <reference path="es6-shim/es6-shim.d.ts" />
|
||||
@@ -1,26 +1,28 @@
|
||||
{
|
||||
"version": "1.0.0-*",
|
||||
"description": "Helpers for building Angular 2 applications on ASP.NET Core.",
|
||||
"compilationOptions": {
|
||||
"keyFile": "../../tools/Key.snk"
|
||||
"version": "1.0.0-*",
|
||||
"packOptions": {
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/aspnet/javascriptservices"
|
||||
},
|
||||
"tags": [
|
||||
"aspnetcore",
|
||||
"aspnetcoremvc",
|
||||
"nodeservices"
|
||||
]
|
||||
},
|
||||
"authors": [ "Microsoft" ],
|
||||
"tooling": {
|
||||
"defaultNamespace": "Microsoft.AspNetCore.AngularServices"
|
||||
"buildOptions": {
|
||||
"warningsAsErrors": true,
|
||||
"keyFile": "../../tools/Key.snk",
|
||||
"xmlDoc": true
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.1",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {
|
||||
},
|
||||
"netstandard1.6": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
"net451": {},
|
||||
"netstandard1.6": {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
namespace Microsoft.AspNetCore.NodeServices
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a way of creating and invoking code in a Node.js environment.
|
||||
/// </summary>
|
||||
public enum NodeHostingModel
|
||||
{
|
||||
/// <summary>
|
||||
/// An out-of-process Node.js instance where RPC calls are made via HTTP.
|
||||
/// </summary>
|
||||
Http,
|
||||
|
||||
/// <summary>
|
||||
/// An out-of-process Node.js instance where RPC calls are made over binary sockets.
|
||||
/// </summary>
|
||||
Socket,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,16 @@ using Microsoft.AspNetCore.NodeServices.HostingModels;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices
|
||||
{
|
||||
/// <summary>
|
||||
/// Supplies INodeServices instances.
|
||||
/// </summary>
|
||||
public static class NodeServicesFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Create an <see cref="INodeServices"/> instance according to the supplied options.
|
||||
/// </summary>
|
||||
/// <param name="options">Options for creating the <see cref="INodeServices"/> instance.</param>
|
||||
/// <returns>An <see cref="INodeServices"/> instance.</returns>
|
||||
public static INodeServices CreateNodeServices(NodeServicesOptions options)
|
||||
{
|
||||
if (options == null)
|
||||
|
||||
@@ -8,14 +8,25 @@ using Microsoft.Extensions.Logging.Console;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes options used to configure an <see cref="INodeServices"/> instance.
|
||||
/// </summary>
|
||||
public class NodeServicesOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the default <see cref="NodeHostingModel"/>.
|
||||
/// </summary>
|
||||
public const NodeHostingModel DefaultNodeHostingModel = NodeHostingModel.Http;
|
||||
|
||||
internal const string TimeoutConfigPropertyName = nameof(InvocationTimeoutMilliseconds);
|
||||
private const int DefaultInvocationTimeoutMilliseconds = 60 * 1000;
|
||||
private const string LogCategoryName = "Microsoft.AspNetCore.NodeServices";
|
||||
private static readonly string[] DefaultWatchFileExtensions = { ".js", ".jsx", ".ts", ".tsx", ".json", ".html" };
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="NodeServicesOptions"/>.
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider">The <see cref="IServiceProvider"/>.</param>
|
||||
public NodeServicesOptions(IServiceProvider serviceProvider)
|
||||
{
|
||||
if (serviceProvider == null)
|
||||
@@ -44,14 +55,49 @@ namespace Microsoft.AspNetCore.NodeServices
|
||||
: new ConsoleLogger(LogCategoryName, null, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies which <see cref="NodeHostingModel"/> should be used.
|
||||
/// </summary>
|
||||
public NodeHostingModel HostingModel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set, this callback function will be invoked to supply the <see cref="INodeServices"/> instance.
|
||||
/// </summary>
|
||||
public Func<INodeInstance> NodeInstanceFactory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set, overrides the path to the root of your application. This path is used when locating Node.js modules relative to your project.
|
||||
/// </summary>
|
||||
public string ProjectPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set, the Node.js instance should restart when any matching file on disk within your project changes.
|
||||
/// </summary>
|
||||
public string[] WatchFileExtensions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Node.js instance's stdout/stderr will be redirected to this <see cref="ILogger"/>.
|
||||
/// </summary>
|
||||
public ILogger NodeInstanceOutputLogger { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the Node.js instance will accept incoming V8 debugger connections (e.g., from node-inspector).
|
||||
/// </summary>
|
||||
public bool LaunchWithDebugging { get; set; }
|
||||
public IDictionary<string, string> EnvironmentVariables { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If <see cref="LaunchWithDebugging"/> is true, the Node.js instance will listen for V8 debugger connections on this port.
|
||||
/// </summary>
|
||||
public int DebuggingPort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set, starts the Node.js instance with the specified environment variables.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> EnvironmentVariables { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the maximum duration, in milliseconds, that your .NET code should wait for Node.js RPC calls to return.
|
||||
/// </summary>
|
||||
public int InvocationTimeoutMilliseconds { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,18 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
/// </summary>
|
||||
public static class NodeServicesServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds NodeServices support to the <paramref name="serviceCollection"/>.
|
||||
/// </summary>
|
||||
/// <param name="serviceCollection">The <see cref="IServiceCollection"/>.</param>
|
||||
public static void AddNodeServices(this IServiceCollection serviceCollection)
|
||||
=> AddNodeServices(serviceCollection, _ => {});
|
||||
|
||||
/// <summary>
|
||||
/// Adds NodeServices support to the <paramref name="serviceCollection"/>.
|
||||
/// </summary>
|
||||
/// <param name="serviceCollection">The <see cref="IServiceCollection"/>.</param>
|
||||
/// <param name="options">Options for configuring the <see cref="INodeServices"/> instances.</param>
|
||||
[Obsolete("Use the AddNodeServices(Action<NodeServicesOptions> setupAction) overload instead.")]
|
||||
public static void AddNodeServices(this IServiceCollection serviceCollection, NodeServicesOptions options)
|
||||
{
|
||||
@@ -20,6 +29,11 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds NodeServices support to the <paramref name="serviceCollection"/>.
|
||||
/// </summary>
|
||||
/// <param name="serviceCollection">The <see cref="IServiceCollection"/>.</param>
|
||||
/// <param name="setupAction">A callback that will be invoked to populate the <see cref="NodeServicesOptions"/>.</param>
|
||||
public static void AddNodeServices(this IServiceCollection serviceCollection, Action<NodeServicesOptions> setupAction)
|
||||
{
|
||||
if (setupAction == null)
|
||||
|
||||
@@ -128,9 +128,8 @@
|
||||
ExitWhenParentExits_1.exitWhenParentExits(parseInt(parsedArgs.parentPid));
|
||||
function readRequestBodyAsJson(request, callback) {
|
||||
var requestBodyAsString = '';
|
||||
request
|
||||
.on('data', function (chunk) { requestBodyAsString += chunk; })
|
||||
.on('end', function () { callback(JSON.parse(requestBodyAsString)); });
|
||||
request.on('data', function (chunk) { requestBodyAsString += chunk; });
|
||||
request.on('end', function () { callback(JSON.parse(requestBodyAsString)); });
|
||||
}
|
||||
function respondWithError(res, errorValue) {
|
||||
res.statusCode = 500;
|
||||
|
||||
@@ -376,11 +376,12 @@
|
||||
_this._sendFrame(header.connectionIdBinary, data, writeCompletedCallback);
|
||||
}
|
||||
};
|
||||
var newVirtualConnection = new VirtualConnection_1.VirtualConnection(beginWriteCallback)
|
||||
.on('end', function () {
|
||||
var newVirtualConnection = new VirtualConnection_1.VirtualConnection(beginWriteCallback);
|
||||
newVirtualConnection.on('end', function () {
|
||||
// The virtual connection was closed remotely. Clean up locally.
|
||||
_this._onVirtualConnectionWasClosed(header.connectionIdString);
|
||||
}).on('finish', function () {
|
||||
});
|
||||
newVirtualConnection.on('finish', function () {
|
||||
// The virtual connection was closed locally. Clean up locally, and notify the remote that we're done.
|
||||
_this._onVirtualConnectionWasClosed(header.connectionIdString);
|
||||
_this._sendFrame(header.connectionIdBinary, new Buffer(0));
|
||||
|
||||
@@ -4,8 +4,20 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an instance of Node.js to which Remote Procedure Calls (RPC) may be sent.
|
||||
/// </summary>
|
||||
public interface INodeInstance : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Asynchronously invokes code in the Node.js instance.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The JSON-serializable data type that the Node.js code will asynchronously return.</typeparam>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the invocation.</param>
|
||||
/// <param name="moduleName">The path to the Node.js module (i.e., JavaScript file) relative to your project root that contains the code to be invoked.</param>
|
||||
/// <param name="exportNameOrNull">If set, specifies the CommonJS export to be invoked. If not set, the module's default CommonJS export itself must be a function to be invoked.</param>
|
||||
/// <param name="args">Any sequence of JSON-serializable arguments to be passed to the Node.js function.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> representing the completion of the RPC call.</returns>
|
||||
Task<T> InvokeExportAsync<T>(CancellationToken cancellationToken, string moduleName, string exportNameOrNull, params object[] args);
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,33 @@ using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an exception caused by invoking Node.js code.
|
||||
/// </summary>
|
||||
public class NodeInvocationException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// If true, indicates that the invocation failed because the Node.js instance could not be reached. For example,
|
||||
/// it might have already shut down or previously crashed.
|
||||
/// </summary>
|
||||
public bool NodeInstanceUnavailable { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="NodeInvocationException"/>.
|
||||
/// </summary>
|
||||
/// <param name="message">A description of the exception.</param>
|
||||
/// <param name="details">Additional information, such as a Node.js stack trace, representing the exception.</param>
|
||||
public NodeInvocationException(string message, string details)
|
||||
: base(message + Environment.NewLine + details)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="NodeInvocationException"/>.
|
||||
/// </summary>
|
||||
/// <param name="message">A description of the exception.</param>
|
||||
/// <param name="details">Additional information, such as a Node.js stack trace, representing the exception.</param>
|
||||
/// <param name="nodeInstanceUnavailable">Specifies a value for the <see cref="NodeInstanceUnavailable"/> flag.</param>
|
||||
public NodeInvocationException(string message, string details, bool nodeInstanceUnavailable)
|
||||
: this(message, details)
|
||||
{
|
||||
|
||||
@@ -1,9 +1,24 @@
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes an RPC call sent from .NET code to Node.js code.
|
||||
/// </summary>
|
||||
public class NodeInvocationInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the path to the Node.js module (i.e., .js file) relative to the project root.
|
||||
/// </summary>
|
||||
public string ModuleName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set, specifies the name of CommonJS function export to be invoked.
|
||||
/// If not set, the Node.js module's default export must itself be a function to be invoked.
|
||||
/// </summary>
|
||||
public string ExportedFunctionName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A sequence of JSON-serializable arguments to be passed to the Node.js function being invoked.
|
||||
/// </summary>
|
||||
public object[] Args { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,11 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
/// <seealso cref="Microsoft.AspNetCore.NodeServices.HostingModels.INodeInstance" />
|
||||
public abstract class OutOfProcessNodeInstance : INodeInstance
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> to which the Node.js instance's stdout/stderr is being redirected.
|
||||
/// </summary>
|
||||
protected readonly ILogger OutputLogger;
|
||||
|
||||
private const string ConnectionEstablishedMessage = "[Microsoft.AspNetCore.NodeServices:Listening]";
|
||||
private const string DebuggingStartedMessageFormat = @"-----
|
||||
*** Node.js debugging is enabled ***
|
||||
@@ -43,6 +47,18 @@ If you haven't yet installed node-inspector, you can do so as follows:
|
||||
private bool _nodeProcessNeedsRestart;
|
||||
private readonly string[] _watchFileExtensions;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="OutOfProcessNodeInstance"/>.
|
||||
/// </summary>
|
||||
/// <param name="entryPointScript">The path to the entry point script that the Node instance should load and execute.</param>
|
||||
/// <param name="projectPath">The root path of the current project. This is used when resolving Node.js module paths relative to the project root.</param>
|
||||
/// <param name="watchFileExtensions">The filename extensions that should be watched within the project root. The Node instance will automatically shut itself down if any matching file changes.</param>
|
||||
/// <param name="commandLineArguments">Additional command-line arguments to be passed to the Node.js instance.</param>
|
||||
/// <param name="nodeOutputLogger">The <see cref="ILogger"/> to which the Node.js instance's stdout/stderr (and other log information) should be written.</param>
|
||||
/// <param name="environmentVars">Environment variables to be set on the Node.js process.</param>
|
||||
/// <param name="invocationTimeoutMilliseconds">The maximum duration, in milliseconds, to wait for RPC calls to complete.</param>
|
||||
/// <param name="launchWithDebugging">If true, passes a flag to the Node.js process telling it to accept V8 debugger connections.</param>
|
||||
/// <param name="debuggingPort">If debugging is enabled, the Node.js process should listen for V8 debugger connections on this port.</param>
|
||||
public OutOfProcessNodeInstance(
|
||||
string entryPointScript,
|
||||
string projectPath,
|
||||
@@ -71,6 +87,15 @@ If you haven't yet installed node-inspector, you can do so as follows:
|
||||
ConnectToInputOutputStreams();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously invokes code in the Node.js instance.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The JSON-serializable data type that the Node.js code will asynchronously return.</typeparam>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the invocation.</param>
|
||||
/// <param name="moduleName">The path to the Node.js module (i.e., JavaScript file) relative to your project root that contains the code to be invoked.</param>
|
||||
/// <param name="exportNameOrNull">If set, specifies the CommonJS export to be invoked. If not set, the module's default CommonJS export itself must be a function to be invoked.</param>
|
||||
/// <param name="args">Any sequence of JSON-serializable arguments to be passed to the Node.js function.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> representing the completion of the RPC call.</returns>
|
||||
public async Task<T> InvokeExportAsync<T>(
|
||||
CancellationToken cancellationToken, string moduleName, string exportNameOrNull, params object[] args)
|
||||
{
|
||||
@@ -154,21 +179,41 @@ If you haven't yet installed node-inspector, you can do so as follows:
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes this instance.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously invokes code in the Node.js instance.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The JSON-serializable data type that the Node.js code will asynchronously return.</typeparam>
|
||||
/// <param name="invocationInfo">Specifies the Node.js function to be invoked and arguments to be passed to it.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the invocation.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> representing the completion of the RPC call.</returns>
|
||||
protected abstract Task<T> InvokeExportAsync<T>(
|
||||
NodeInvocationInfo invocationInfo,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
// This method is virtual, as it provides a way to override the NODE_PATH or the path to node.exe
|
||||
/// <summary>
|
||||
/// Configures a <see cref="ProcessStartInfo"/> instance describing how to launch the Node.js process.
|
||||
/// </summary>
|
||||
/// <param name="entryPointFilename">The entrypoint JavaScript file that the Node.js process should execute.</param>
|
||||
/// <param name="projectPath">The root path of the project. This is used when locating Node.js modules relative to the project root.</param>
|
||||
/// <param name="commandLineArguments">Command-line arguments to be passed to the Node.js process.</param>
|
||||
/// <param name="environmentVars">Environment variables to be set on the Node.js process.</param>
|
||||
/// <param name="launchWithDebugging">If true, passes a flag to the Node.js process telling it to accept V8 debugger connections.</param>
|
||||
/// <param name="debuggingPort">If debugging is enabled, the Node.js process should listen for V8 debugger connections on this port.</param>
|
||||
/// <returns></returns>
|
||||
protected virtual ProcessStartInfo PrepareNodeProcessStartInfo(
|
||||
string entryPointFilename, string projectPath, string commandLineArguments,
|
||||
IDictionary<string, string> environmentVars, bool launchWithDebugging, int debuggingPort)
|
||||
{
|
||||
// This method is virtual, as it provides a way to override the NODE_PATH or the path to node.exe
|
||||
string debuggingArgs;
|
||||
if (launchWithDebugging)
|
||||
{
|
||||
@@ -217,16 +262,28 @@ If you haven't yet installed node-inspector, you can do so as follows:
|
||||
return startInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Virtual method invoked whenever the Node.js process emits a line to its stdout.
|
||||
/// </summary>
|
||||
/// <param name="outputData">The line emitted to the Node.js process's stdout.</param>
|
||||
protected virtual void OnOutputDataReceived(string outputData)
|
||||
{
|
||||
OutputLogger.LogInformation(outputData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Virtual method invoked whenever the Node.js process emits a line to its stderr.
|
||||
/// </summary>
|
||||
/// <param name="errorData">The line emitted to the Node.js process's stderr.</param>
|
||||
protected virtual void OnErrorDataReceived(string errorData)
|
||||
{
|
||||
OutputLogger.LogError(errorData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes the instance.
|
||||
/// </summary>
|
||||
/// <param name="disposing">True if the object is disposing or false if it is finalizing.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
@@ -403,6 +460,9 @@ If you haven't yet installed node-inspector, you can do so as follows:
|
||||
EnsureFileSystemWatcherIsDisposed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements the finalization part of the IDisposable pattern by calling Dispose(false).
|
||||
/// </summary>
|
||||
~OutOfProcessNodeInstance()
|
||||
{
|
||||
Dispose(false);
|
||||
|
||||
@@ -33,6 +33,9 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
TypeNameHandling = TypeNameHandling.None
|
||||
};
|
||||
|
||||
private readonly static int streamBufferSize = 16 * 1024;
|
||||
private readonly static UTF8Encoding utf8EncodingWithoutBom = new UTF8Encoding(false);
|
||||
|
||||
private readonly SemaphoreSlim _connectionCreationSemaphore = new SemaphoreSlim(1);
|
||||
private bool _connectionHasFailed;
|
||||
private StreamConnection _physicalConnection;
|
||||
@@ -89,7 +92,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
virtualConnection = _virtualConnectionClient.OpenVirtualConnection();
|
||||
|
||||
// Send request
|
||||
await WriteJsonLineAsync(virtualConnection, invocationInfo, cancellationToken);
|
||||
WriteJsonLine(virtualConnection, invocationInfo);
|
||||
|
||||
// Determine what kind of response format is expected
|
||||
if (typeof(T) == typeof(Stream))
|
||||
@@ -169,11 +172,20 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
private static async Task WriteJsonLineAsync(Stream stream, object serializableObject, CancellationToken cancellationToken)
|
||||
private static void WriteJsonLine(Stream stream, object serializableObject)
|
||||
{
|
||||
var json = JsonConvert.SerializeObject(serializableObject, jsonSerializerSettings);
|
||||
var bytes = Encoding.UTF8.GetBytes(json + '\n');
|
||||
await stream.WriteAsync(bytes, 0, bytes.Length, cancellationToken);
|
||||
using (var streamWriter = new StreamWriter(stream, utf8EncodingWithoutBom, streamBufferSize, true))
|
||||
using (var jsonWriter = new JsonTextWriter(streamWriter))
|
||||
{
|
||||
jsonWriter.CloseOutput = false;
|
||||
|
||||
var serializer = JsonSerializer.Create(jsonSerializerSettings);
|
||||
serializer.Serialize(jsonWriter, serializableObject);
|
||||
jsonWriter.Flush();
|
||||
|
||||
streamWriter.WriteLine();
|
||||
streamWriter.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<T> ReadJsonAsync<T>(Stream stream, CancellationToken cancellationToken)
|
||||
@@ -184,7 +196,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
|
||||
private static async Task<byte[]> ReadAllBytesAsync(Stream input, CancellationToken cancellationToken)
|
||||
{
|
||||
byte[] buffer = new byte[16 * 1024];
|
||||
byte[] buffer = new byte[streamBufferSize];
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
|
||||
@@ -7,6 +7,10 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels.VirtualConnections
|
||||
{
|
||||
/// <summary>
|
||||
/// A callback that will be invoked if the <see cref="VirtualConnectionClient"/> encounters a read error.
|
||||
/// </summary>
|
||||
/// <param name="ex"></param>
|
||||
public delegate void VirtualConnectionReadErrorHandler(Exception ex);
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -4,18 +4,71 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the ability to invoke code in a Node.js environment. Although the underlying Node.js instance
|
||||
/// might change over time (e.g., the process might be restarted), the <see cref="INodeServices"/> instance
|
||||
/// will remain constant.
|
||||
/// </summary>
|
||||
public interface INodeServices : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Asynchronously invokes code in the Node.js instance.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The JSON-serializable data type that the Node.js code will asynchronously return.</typeparam>
|
||||
/// <param name="moduleName">The path to the Node.js module (i.e., JavaScript file) relative to your project root whose default CommonJS export is the function to be invoked.</param>
|
||||
/// <param name="args">Any sequence of JSON-serializable arguments to be passed to the Node.js function.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> representing the completion of the RPC call.</returns>
|
||||
Task<T> InvokeAsync<T>(string moduleName, params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously invokes code in the Node.js instance.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The JSON-serializable data type that the Node.js code will asynchronously return.</typeparam>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the invocation.</param>
|
||||
/// <param name="moduleName">The path to the Node.js module (i.e., JavaScript file) relative to your project root whose default CommonJS export is the function to be invoked.</param>
|
||||
/// <param name="args">Any sequence of JSON-serializable arguments to be passed to the Node.js function.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> representing the completion of the RPC call.</returns>
|
||||
Task<T> InvokeAsync<T>(CancellationToken cancellationToken, string moduleName, params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously invokes code in the Node.js instance.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The JSON-serializable data type that the Node.js code will asynchronously return.</typeparam>
|
||||
/// <param name="moduleName">The path to the Node.js module (i.e., JavaScript file) relative to your project root that contains the code to be invoked.</param>
|
||||
/// <param name="exportedFunctionName">Specifies the CommonJS export to be invoked.</param>
|
||||
/// <param name="args">Any sequence of JSON-serializable arguments to be passed to the Node.js function.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> representing the completion of the RPC call.</returns>
|
||||
Task<T> InvokeExportAsync<T>(string moduleName, string exportedFunctionName, params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously invokes code in the Node.js instance.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The JSON-serializable data type that the Node.js code will asynchronously return.</typeparam>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the invocation.</param>
|
||||
/// <param name="moduleName">The path to the Node.js module (i.e., JavaScript file) relative to your project root that contains the code to be invoked.</param>
|
||||
/// <param name="exportedFunctionName">Specifies the CommonJS export to be invoked.</param>
|
||||
/// <param name="args">Any sequence of JSON-serializable arguments to be passed to the Node.js function.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> representing the completion of the RPC call.</returns>
|
||||
Task<T> InvokeExportAsync<T>(CancellationToken cancellationToken, string moduleName, string exportedFunctionName, params object[] args);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously invokes code in the Node.js instance.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The JSON-serializable data type that the Node.js code will asynchronously return.</typeparam>
|
||||
/// <param name="moduleName">The path to the Node.js module (i.e., JavaScript file) relative to your project root whose default CommonJS export is the function to be invoked.</param>
|
||||
/// <param name="args">Any sequence of JSON-serializable arguments to be passed to the Node.js function.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> representing the completion of the RPC call.</returns>
|
||||
[Obsolete("Use InvokeAsync instead")]
|
||||
Task<T> Invoke<T>(string moduleName, params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously invokes code in the Node.js instance.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The JSON-serializable data type that the Node.js code will asynchronously return.</typeparam>
|
||||
/// <param name="moduleName">The path to the Node.js module (i.e., JavaScript file) relative to your project root that contains the code to be invoked.</param>
|
||||
/// <param name="exportedFunctionName">Specifies the CommonJS export to be invoked.</param>
|
||||
/// <param name="args">Any sequence of JSON-serializable arguments to be passed to the Node.js function.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> representing the completion of the RPC call.</returns>
|
||||
[Obsolete("Use InvokeExportAsync instead")]
|
||||
Task<T> InvokeExport<T>(string moduleName, string exportedFunctionName, params object[] args);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: AssemblyMetadata("Serviceable", "True")]
|
||||
[assembly: NeutralResourcesLanguage("en-us")]
|
||||
[assembly: AssemblyCompany("Microsoft Corporation.")]
|
||||
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
|
||||
[assembly: AssemblyProduct("Microsoft ASP.NET Core")]
|
||||
@@ -80,9 +80,8 @@ exitWhenParentExits(parseInt(parsedArgs.parentPid));
|
||||
|
||||
function readRequestBodyAsJson(request, callback) {
|
||||
let requestBodyAsString = '';
|
||||
request
|
||||
.on('data', chunk => { requestBodyAsString += chunk; })
|
||||
.on('end', () => { callback(JSON.parse(requestBodyAsString)); });
|
||||
request.on('data', chunk => { requestBodyAsString += chunk; });
|
||||
request.on('end', () => { callback(JSON.parse(requestBodyAsString)); });
|
||||
}
|
||||
|
||||
function respondWithError(res: http.ServerResponse, errorValue: any) {
|
||||
|
||||
@@ -105,15 +105,16 @@ class VirtualConnectionsCollection {
|
||||
}
|
||||
};
|
||||
|
||||
const newVirtualConnection = new VirtualConnection(beginWriteCallback)
|
||||
.on('end', () => {
|
||||
// The virtual connection was closed remotely. Clean up locally.
|
||||
this._onVirtualConnectionWasClosed(header.connectionIdString);
|
||||
}).on('finish', () => {
|
||||
// The virtual connection was closed locally. Clean up locally, and notify the remote that we're done.
|
||||
this._onVirtualConnectionWasClosed(header.connectionIdString);
|
||||
this._sendFrame(header.connectionIdBinary, new Buffer(0));
|
||||
});
|
||||
const newVirtualConnection = new VirtualConnection(beginWriteCallback);
|
||||
newVirtualConnection.on('end', () => {
|
||||
// The virtual connection was closed remotely. Clean up locally.
|
||||
this._onVirtualConnectionWasClosed(header.connectionIdString);
|
||||
});
|
||||
newVirtualConnection.on('finish', () => {
|
||||
// The virtual connection was closed locally. Clean up locally, and notify the remote that we're done.
|
||||
this._onVirtualConnectionWasClosed(header.connectionIdString);
|
||||
this._sendFrame(header.connectionIdBinary, new Buffer(0));
|
||||
});
|
||||
|
||||
this._virtualConnections[header.connectionIdString] = newVirtualConnection;
|
||||
this._onVirtualConnectionCallback(newVirtualConnection);
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"target": "es3",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node"
|
||||
"moduleResolution": "node",
|
||||
"types": ["node"]
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
/// <reference path="node/node.d.ts" />
|
||||
@@ -4,8 +4,17 @@ using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains methods for reading embedded resources.
|
||||
/// </summary>
|
||||
public static class EmbeddedResourceReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads the specified embedded resource from a given assembly.
|
||||
/// </summary>
|
||||
/// <param name="assemblyContainingType">Any <see cref="Type"/> in the assembly whose resource is to be read.</param>
|
||||
/// <param name="path">The path of the resource to be read.</param>
|
||||
/// <returns>The contents of the resource.</returns>
|
||||
public static string Read(Type assemblyContainingType, string path)
|
||||
{
|
||||
var asm = assemblyContainingType.GetTypeInfo().Assembly;
|
||||
|
||||
@@ -3,19 +3,31 @@ using System.IO;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices
|
||||
{
|
||||
// Makes it easier to pass script files to Node in a way that's sure to clean up after the process exits
|
||||
/// <summary>
|
||||
/// Makes it easier to pass script files to Node in a way that's sure to clean up after the process exits.
|
||||
/// </summary>
|
||||
public sealed class StringAsTempFile : IDisposable
|
||||
{
|
||||
private bool _disposedValue;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance of <see cref="StringAsTempFile"/>.
|
||||
/// </summary>
|
||||
/// <param name="content">The contents of the temporary file to be created.</param>
|
||||
public StringAsTempFile(string content)
|
||||
{
|
||||
FileName = Path.GetTempFileName();
|
||||
File.WriteAllText(FileName, content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the filename of the temporary file.
|
||||
/// </summary>
|
||||
public string FileName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Disposes the instance and deletes the associated temporary file.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeImpl(true);
|
||||
@@ -37,6 +49,9 @@ namespace Microsoft.AspNetCore.NodeServices
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements the finalization part of the IDisposable pattern by calling Dispose(false).
|
||||
/// </summary>
|
||||
~StringAsTempFile()
|
||||
{
|
||||
DisposeImpl(false);
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
"author": "Microsoft",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@types/node": "^6.0.42",
|
||||
"ts-loader": "^0.8.2",
|
||||
"typescript": "^1.8.10",
|
||||
"typescript": "^2.0.0",
|
||||
"webpack": "^1.13.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,31 @@
|
||||
{
|
||||
"version": "1.0.0-*",
|
||||
"description": "Invoke Node.js modules at runtime in ASP.NET Core applications.",
|
||||
"compilationOptions": {
|
||||
"keyFile": "../../tools/Key.snk"
|
||||
"version": "1.0.0-*",
|
||||
"packOptions": {
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/aspnet/javascriptservices"
|
||||
},
|
||||
"tags": [
|
||||
"aspnetcore",
|
||||
"aspnetcoremvc",
|
||||
"nodeservices"
|
||||
]
|
||||
},
|
||||
"buildOptions": {
|
||||
"warningsAsErrors": true,
|
||||
"keyFile": "../../tools/Key.snk",
|
||||
"embed": [
|
||||
"Content/**/*"
|
||||
],
|
||||
"xmlDoc": true
|
||||
},
|
||||
"authors": [ "Microsoft" ],
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Hosting.Abstractions": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "1.0.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.0.0",
|
||||
"Microsoft.Extensions.PlatformAbstractions": "1.0.0",
|
||||
"Newtonsoft.Json": "9.0.1"
|
||||
"Newtonsoft.Json": "9.0.1",
|
||||
"NETStandard.Library": "1.6.0"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {
|
||||
@@ -22,27 +36,18 @@
|
||||
"Microsoft.Tpl.Dataflow": "4.5.24"
|
||||
}
|
||||
},
|
||||
"netstandard1.3": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
],
|
||||
"netstandard1.6": {
|
||||
"dependencies": {
|
||||
"System.Console": "4.0.0",
|
||||
"System.Diagnostics.Process": "4.1.0",
|
||||
"System.IO.Pipes": "4.0.0",
|
||||
"System.Net.Http": "4.1.0",
|
||||
"System.Net.Sockets": "4.1.0",
|
||||
"System.Runtime.InteropServices.RuntimeInformation": "4.0.0",
|
||||
"System.Text.RegularExpressions": "4.1.0",
|
||||
"System.Threading.Tasks.Dataflow": "4.5.25"
|
||||
"System.Threading.Tasks.Dataflow": "4.6.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"buildOptions": {
|
||||
"embed": [
|
||||
"Content/**/*"
|
||||
"scripts": {
|
||||
"prepublish": [
|
||||
"npm install",
|
||||
"node node_modules/webpack/bin/webpack.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"version": "v4",
|
||||
"repo": "borisyankov/DefinitelyTyped",
|
||||
"ref": "master",
|
||||
"path": "TypeScript/typings",
|
||||
"bundle": "TypeScript/typings/tsd.d.ts",
|
||||
"installed": {
|
||||
"node/node.d.ts": {
|
||||
"commit": "edb64e4a35896510ce02b93c0bca5ec3878db738"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: AssemblyMetadata("Serviceable", "True")]
|
||||
[assembly: NeutralResourcesLanguage("en-us")]
|
||||
[assembly: AssemblyCompany("Microsoft Corporation.")]
|
||||
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
|
||||
[assembly: AssemblyProduct("Microsoft ASP.NET Core")]
|
||||
@@ -1,4 +1,3 @@
|
||||
/typings/
|
||||
/node_modules/
|
||||
/*.js
|
||||
/*.d.ts
|
||||
|
||||
@@ -1,17 +1,27 @@
|
||||
{
|
||||
"name": "redux-typed",
|
||||
"version": "1.0.0",
|
||||
"version": "2.0.0",
|
||||
"description": "Helpers for building React+Redux apps with strong TypeScript type checking everywhere",
|
||||
"main": "main.js",
|
||||
"typings": "main.d.ts",
|
||||
"scripts": {
|
||||
"prepublish": "rimraf *.d.ts && tsd update && tsc && echo 'Finished building NPM package \"redux-typed\"'",
|
||||
"prepublish": "rimraf *.d.ts && tsc && echo 'Finished building NPM package \"redux-typed\"'",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Microsoft",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/aspnet/JavaScriptServices/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aspnet/JavaScriptServices.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^0.14.38",
|
||||
"@types/react-redux": "^4.4.32",
|
||||
"@types/redux": "^3.5.30",
|
||||
"rimraf": "^2.5.4",
|
||||
"typescript": "^1.8.10"
|
||||
"typescript": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,12 @@
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"declaration": true,
|
||||
"outDir": "."
|
||||
"outDir": ".",
|
||||
"lib": ["es2015", "dom"]
|
||||
},
|
||||
"files": [
|
||||
"src/main.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"version": "v4",
|
||||
"repo": "borisyankov/DefinitelyTyped",
|
||||
"ref": "master",
|
||||
"path": "typings",
|
||||
"bundle": "typings/tsd.d.ts",
|
||||
"installed": {
|
||||
"react/react.d.ts": {
|
||||
"commit": "f4b1797c1201b6c575668f5d7ea12d9b1ab21846"
|
||||
},
|
||||
"react-redux/react-redux.d.ts": {
|
||||
"commit": "f4b1797c1201b6c575668f5d7ea12d9b1ab21846"
|
||||
},
|
||||
"redux/redux.d.ts": {
|
||||
"commit": "f4b1797c1201b6c575668f5d7ea12d9b1ab21846"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,28 @@
|
||||
{
|
||||
"version": "1.0.0-*",
|
||||
"description": "Helpers for building React applications on ASP.NET Core.",
|
||||
"compilationOptions": {
|
||||
"keyFile": "../../tools/Key.snk"
|
||||
"version": "1.0.0-*",
|
||||
"packOptions": {
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/aspnet/javascriptservices"
|
||||
},
|
||||
"tags": [
|
||||
"aspnetcore",
|
||||
"aspnetcoremvc",
|
||||
"nodeservices"
|
||||
]
|
||||
},
|
||||
"authors": [ "Microsoft" ],
|
||||
"tooling": {
|
||||
"defaultNamespace": "Microsoft.AspNetCore.ReactServices"
|
||||
"buildOptions": {
|
||||
"warningsAsErrors": true,
|
||||
"keyFile": "../../tools/Key.snk",
|
||||
"xmlDoc": true
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.1",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {
|
||||
},
|
||||
"netstandard1.6": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
"net451": {},
|
||||
"netstandard1.6": {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
/bin/
|
||||
/node_modules/
|
||||
|
||||
@@ -1,12 +1,178 @@
|
||||
// Pass through the invocation to the 'aspnet-prerendering' package, verifying that it can be loaded
|
||||
module.exports.renderToString = function (callback) {
|
||||
var aspNetPrerendering;
|
||||
try {
|
||||
aspNetPrerendering = require('aspnet-prerendering');
|
||||
} catch (ex) {
|
||||
callback('To use prerendering, you must install the \'aspnet-prerendering\' NPM package.');
|
||||
return;
|
||||
}
|
||||
(function(e, a) { for(var i in a) e[i] = a[i]; }(exports, /******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
||||
return aspNetPrerendering.renderToString.apply(this, arguments);
|
||||
};
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId])
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ exports: {},
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false
|
||||
/******/ };
|
||||
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
|
||||
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
module.exports = __webpack_require__(1);
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 1 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
var path = __webpack_require__(2);
|
||||
// Separate declaration and export just to add type checking on function signature
|
||||
exports.renderToString = renderToStringImpl;
|
||||
// This function is invoked by .NET code (via NodeServices). Its job is to hand off execution to the application's
|
||||
// prerendering boot function. It can operate in two modes:
|
||||
// [1] Legacy mode
|
||||
// This is for backward compatibility with projects created with templates older than the generator version 0.6.0.
|
||||
// In this mode, we don't really do anything here - we just load the 'aspnet-prerendering' NPM module (which must
|
||||
// exist in node_modules, and must be v1.x (not v2+)), and pass through all the parameters to it. Code in
|
||||
// 'aspnet-prerendering' v1.x will locate the boot function and invoke it.
|
||||
// The drawback to this mode is that, for it to work, you have to deploy node_modules to production.
|
||||
// [2] Current mode
|
||||
// This is for projects created with the Yeoman generator 0.6.0+ (or projects manually updated). In this mode,
|
||||
// we don't invoke 'require' at runtime at all. All our dependencies are bundled into the NuGet package, so you
|
||||
// don't have to deploy node_modules to production.
|
||||
// To determine whether we're in mode [1] or [2], the code locates your prerendering boot function, and checks whether
|
||||
// a certain flag is attached to the function instance.
|
||||
function renderToStringImpl(callback, applicationBasePath, bootModule, absoluteRequestUrl, requestPathAndQuery, customDataParameter, overrideTimeoutMilliseconds) {
|
||||
try {
|
||||
var forceLegacy = isLegacyAspNetPrerendering();
|
||||
var renderToStringFunc = !forceLegacy && findRenderToStringFunc(applicationBasePath, bootModule);
|
||||
var isNotLegacyMode = renderToStringFunc && renderToStringFunc['isServerRenderer'];
|
||||
if (isNotLegacyMode) {
|
||||
// Current (non-legacy) mode - we invoke the exported function directly (instead of going through aspnet-prerendering)
|
||||
// It's type-safe to just apply the incoming args to this function, because we already type-checked that it's a RenderToStringFunc,
|
||||
// just like renderToStringImpl itself is.
|
||||
renderToStringFunc.apply(null, arguments);
|
||||
}
|
||||
else {
|
||||
// Legacy mode - just hand off execution to 'aspnet-prerendering' v1.x, which must exist in node_modules at runtime
|
||||
var aspNetPrerenderingV1RenderToString = __webpack_require__(3).renderToString;
|
||||
if (aspNetPrerenderingV1RenderToString) {
|
||||
aspNetPrerenderingV1RenderToString(callback, applicationBasePath, bootModule, absoluteRequestUrl, requestPathAndQuery, customDataParameter, overrideTimeoutMilliseconds);
|
||||
}
|
||||
else {
|
||||
callback('If you use aspnet-prerendering >= 2.0.0, you must update your server-side boot module to call createServerRenderer. '
|
||||
+ 'Either update your boot module code, or revert to aspnet-prerendering version 1.x');
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ex) {
|
||||
// Make sure loading errors are reported back to the .NET part of the app
|
||||
callback('Prerendering failed because of error: '
|
||||
+ ex.stack
|
||||
+ '\nCurrent directory is: '
|
||||
+ process.cwd());
|
||||
}
|
||||
}
|
||||
;
|
||||
function findBootModule(applicationBasePath, bootModule) {
|
||||
var bootModuleNameFullPath = path.resolve(applicationBasePath, bootModule.moduleName);
|
||||
if (bootModule.webpackConfig) {
|
||||
// If you're using asp-prerender-webpack-config, you're definitely in legacy mode
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return require(bootModuleNameFullPath);
|
||||
}
|
||||
}
|
||||
function findRenderToStringFunc(applicationBasePath, bootModule) {
|
||||
// First try to load the module
|
||||
var foundBootModule = findBootModule(applicationBasePath, bootModule);
|
||||
if (foundBootModule === null) {
|
||||
return null; // Must be legacy mode
|
||||
}
|
||||
// Now try to pick out the function they want us to invoke
|
||||
var renderToStringFunc;
|
||||
if (bootModule.exportName) {
|
||||
// Explicitly-named export
|
||||
renderToStringFunc = foundBootModule[bootModule.exportName];
|
||||
}
|
||||
else if (typeof foundBootModule !== 'function') {
|
||||
// TypeScript-style default export
|
||||
renderToStringFunc = foundBootModule.default;
|
||||
}
|
||||
else {
|
||||
// Native default export
|
||||
renderToStringFunc = foundBootModule;
|
||||
}
|
||||
// Validate the result
|
||||
if (typeof renderToStringFunc !== 'function') {
|
||||
if (bootModule.exportName) {
|
||||
throw new Error("The module at " + bootModule.moduleName + " has no function export named " + bootModule.exportName + ".");
|
||||
}
|
||||
else {
|
||||
throw new Error("The module at " + bootModule.moduleName + " does not export a default function, and you have not specified which export to invoke.");
|
||||
}
|
||||
}
|
||||
return renderToStringFunc;
|
||||
}
|
||||
function isLegacyAspNetPrerendering() {
|
||||
var version = getAspNetPrerenderingPackageVersion();
|
||||
return version && /^1\./.test(version);
|
||||
}
|
||||
function getAspNetPrerenderingPackageVersion() {
|
||||
try {
|
||||
var packageEntryPoint = require.resolve('aspnet-prerendering');
|
||||
var packageDir = path.dirname(packageEntryPoint);
|
||||
var packageJsonPath = path.join(packageDir, 'package.json');
|
||||
var packageJson = require(packageJsonPath);
|
||||
return packageJson.version.toString();
|
||||
}
|
||||
catch (ex) {
|
||||
// Implies aspnet-prerendering isn't in node_modules at all (or node_modules itself doesn't exist,
|
||||
// which will be the case in production based on latest templates).
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 2 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
module.exports = require("path");
|
||||
|
||||
/***/ },
|
||||
/* 3 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
module.exports = require("aspnet-prerendering");
|
||||
|
||||
/***/ }
|
||||
/******/ ])));
|
||||
@@ -1,12 +1,86 @@
|
||||
// Pass through the invocation to the 'aspnet-webpack' package, verifying that it can be loaded
|
||||
module.exports.createWebpackDevServer = function (callback) {
|
||||
var aspNetWebpack;
|
||||
try {
|
||||
aspNetWebpack = require('aspnet-webpack');
|
||||
} catch (ex) {
|
||||
callback('To use webpack dev middleware, you must install the \'aspnet-webpack\' NPM package.');
|
||||
return;
|
||||
}
|
||||
(function(e, a) { for(var i in a) e[i] = a[i]; }(exports, /******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
||||
return aspNetWebpack.createWebpackDevServer.apply(this, arguments);
|
||||
};
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId])
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ exports: {},
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false
|
||||
/******/ };
|
||||
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
|
||||
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
module.exports = __webpack_require__(4);
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 1 */,
|
||||
/* 2 */,
|
||||
/* 3 */,
|
||||
/* 4 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
// Pass through the invocation to the 'aspnet-webpack' package, verifying that it can be loaded
|
||||
function createWebpackDevServer(callback) {
|
||||
var aspNetWebpack;
|
||||
try {
|
||||
aspNetWebpack = __webpack_require__(5);
|
||||
}
|
||||
catch (ex) {
|
||||
// Developers sometimes have trouble with badly-configured Node installations, where it's unable
|
||||
// to find node_modules. Or they accidentally fail to deploy node_modules, or even to run 'npm install'.
|
||||
// Make sure such errors are reported back to the .NET part of the app.
|
||||
callback('Webpack dev middleware failed because of an error while loading \'aspnet-webpack\'. Error was: '
|
||||
+ ex.stack
|
||||
+ '\nCurrent directory is: '
|
||||
+ process.cwd());
|
||||
return;
|
||||
}
|
||||
return aspNetWebpack.createWebpackDevServer.apply(this, arguments);
|
||||
}
|
||||
exports.createWebpackDevServer = createWebpackDevServer;
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 5 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
module.exports = require("aspnet-webpack");
|
||||
|
||||
/***/ }
|
||||
/******/ ])));
|
||||
@@ -1,14 +1,36 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes how to find the JavaScript code that performs prerendering.
|
||||
/// </summary>
|
||||
public class JavaScriptModuleExport
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="JavaScriptModuleExport"/>.
|
||||
/// </summary>
|
||||
/// <param name="moduleName">The path to the JavaScript module containing prerendering code.</param>
|
||||
public JavaScriptModuleExport(string moduleName)
|
||||
{
|
||||
ModuleName = moduleName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the path to the JavaScript module containing prerendering code.
|
||||
/// </summary>
|
||||
public string ModuleName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set, specifies the name of the CommonJS export that is the prerendering function to execute.
|
||||
/// If not set, the JavaScript module's default CommonJS export must itself be the prerendering function.
|
||||
/// </summary>
|
||||
public string ExportName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Obsolete. Do not use. Instead, configure Webpack to build a Node.js-compatible bundle and reference that directly.
|
||||
/// </summary>
|
||||
[Obsolete("Do not use. This feature will be removed. Instead, configure Webpack to build a Node.js-compatible bundle and reference that directly.")]
|
||||
public string WebpackConfig { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,9 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
{
|
||||
/// <summary>
|
||||
/// A tag helper for prerendering JavaScript applications on the server.
|
||||
/// </summary>
|
||||
[HtmlTargetElement(Attributes = PrerenderModuleAttributeName)]
|
||||
public class PrerenderTagHelper : TagHelper
|
||||
{
|
||||
@@ -24,6 +27,10 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
private readonly string _applicationBasePath;
|
||||
private readonly INodeServices _nodeServices;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="PrerenderTagHelper"/>.
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider">The <see cref="IServiceProvider"/>.</param>
|
||||
public PrerenderTagHelper(IServiceProvider serviceProvider)
|
||||
{
|
||||
var hostEnv = (IHostingEnvironment) serviceProvider.GetService(typeof(IHostingEnvironment));
|
||||
@@ -39,25 +46,51 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the path to the JavaScript module containing prerendering code.
|
||||
/// </summary>
|
||||
[HtmlAttributeName(PrerenderModuleAttributeName)]
|
||||
public string ModuleName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set, specifies the name of the CommonJS export that is the prerendering function to execute.
|
||||
/// If not set, the JavaScript module's default CommonJS export must itself be the prerendering function.
|
||||
/// </summary>
|
||||
[HtmlAttributeName(PrerenderExportAttributeName)]
|
||||
public string ExportName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Obsolete. Do not use. Instead, configure Webpack to build a Node.js-compatible bundle and reference that directly.
|
||||
/// </summary>
|
||||
[Obsolete("Do not use. This feature will be removed. Instead, configure Webpack to build a Node.js-compatible bundle and reference that directly.")]
|
||||
[HtmlAttributeName(PrerenderWebpackConfigAttributeName)]
|
||||
public string WebpackConfigPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An optional JSON-serializable parameter to be supplied to the prerendering code.
|
||||
/// </summary>
|
||||
[HtmlAttributeName(PrerenderDataAttributeName)]
|
||||
public object CustomDataParameter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The maximum duration to wait for prerendering to complete.
|
||||
/// </summary>
|
||||
[HtmlAttributeName(PrerenderTimeoutAttributeName)]
|
||||
public int TimeoutMillisecondsParameter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ViewContext"/>.
|
||||
/// </summary>
|
||||
[HtmlAttributeNotBound]
|
||||
[ViewContext]
|
||||
public ViewContext ViewContext { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Executes the tag helper to perform server-side prerendering.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="TagHelperContext"/>.</param>
|
||||
/// <param name="output">The <see cref="TagHelperOutput"/>.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the operation.</returns>
|
||||
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
// We want to pass the original, unencoded incoming URL data through to Node, so that
|
||||
@@ -79,12 +112,23 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
new JavaScriptModuleExport(ModuleName)
|
||||
{
|
||||
ExportName = ExportName,
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
WebpackConfig = WebpackConfigPath
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
},
|
||||
unencodedAbsoluteUrl,
|
||||
unencodedPathAndQuery,
|
||||
CustomDataParameter,
|
||||
TimeoutMillisecondsParameter);
|
||||
|
||||
if (!string.IsNullOrEmpty(result.RedirectUrl))
|
||||
{
|
||||
// It's a redirection
|
||||
ViewContext.HttpContext.Response.Redirect(result.RedirectUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
// It's some HTML to inject
|
||||
output.Content.SetHtmlContent(result.Html);
|
||||
|
||||
// Also attach any specified globals to the 'window' object. This is useful for transferring
|
||||
|
||||
@@ -4,6 +4,9 @@ using Microsoft.AspNetCore.NodeServices;
|
||||
|
||||
namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs server-side prerendering by invoking code in Node.js.
|
||||
/// </summary>
|
||||
public static class Prerenderer
|
||||
{
|
||||
private static readonly Lazy<StringAsTempFile> NodeScript;
|
||||
@@ -17,6 +20,17 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs server-side prerendering by invoking code in Node.js.
|
||||
/// </summary>
|
||||
/// <param name="applicationBasePath">The root path to your application. This is used when resolving project-relative paths.</param>
|
||||
/// <param name="nodeServices">The instance of <see cref="INodeServices"/> that will be used to invoke JavaScript code.</param>
|
||||
/// <param name="bootModule">The path to the JavaScript file containing the prerendering logic.</param>
|
||||
/// <param name="requestAbsoluteUrl">The URL of the currently-executing HTTP request. This is supplied to the prerendering code.</param>
|
||||
/// <param name="requestPathAndQuery">The path and query part of the URL of the currently-executing HTTP request. This is supplied to the prerendering code.</param>
|
||||
/// <param name="customDataParameter">An optional JSON-serializable parameter to be supplied to the prerendering code.</param>
|
||||
/// <param name="timeoutMilliseconds">The maximum duration to wait for prerendering to complete.</param>
|
||||
/// <returns></returns>
|
||||
public static Task<RenderToStringResult> RenderToString(
|
||||
string applicationBasePath,
|
||||
INodeServices nodeServices,
|
||||
|
||||
@@ -2,9 +2,28 @@ using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes the prerendering result returned by JavaScript code.
|
||||
/// </summary>
|
||||
public class RenderToStringResult
|
||||
{
|
||||
/// <summary>
|
||||
/// If set, specifies JSON-serializable data that should be added as a set of global JavaScript variables in the document.
|
||||
/// This can be used to transfer arbitrary data from server-side prerendering code to client-side code (for example, to
|
||||
/// transfer the state of a Redux store).
|
||||
/// </summary>
|
||||
public JObject Globals { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The HTML generated by the prerendering logic.
|
||||
/// </summary>
|
||||
public string Html { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set, specifies that instead of rendering HTML, the response should be an HTTP redirection to this URL.
|
||||
/// This can be used if the prerendering code determines that the requested URL would lead to a redirection according
|
||||
/// to the SPA's routing configuration.
|
||||
/// </summary>
|
||||
public string RedirectUrl { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: AssemblyMetadata("Serviceable", "True")]
|
||||
[assembly: NeutralResourcesLanguage("en-us")]
|
||||
[assembly: AssemblyCompany("Microsoft Corporation.")]
|
||||
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
|
||||
[assembly: AssemblyProduct("Microsoft ASP.NET Core")]
|
||||
@@ -38,6 +38,8 @@ If you're starting from scratch, you might prefer to use the `aspnetcore-spa` Ye
|
||||
|
||||
See: [Getting started with the aspnetcore-spa generator](http://blog.stevensanderson.com/2016/05/02/angular2-react-knockout-apps-on-aspnet-core/)
|
||||
|
||||
Also, if you want to debug projects created with the aspnetcore-spa generator, see [Debugging your projects](#debugging-your-projects)
|
||||
|
||||
## Server-side prerendering
|
||||
|
||||
The `SpaServices` package isn't tied to any particular client-side framework, and it doesn't force you to set up your client-side application in any one particular style. So, `SpaServices` doesn't contain hard-coded logic for rendering Angular 2 / React / etc. components.
|
||||
@@ -50,7 +52,7 @@ Make sure you've installed the `Microsoft.AspNetCore.SpaServices` NuGet package
|
||||
|
||||
Now go to your `Views/_ViewImports.cshtml` file, and add the following line:
|
||||
|
||||
@addTagHelper "*, Microsoft.AspNetCore.SpaServices"
|
||||
@addTagHelper *, Microsoft.AspNetCore.SpaServices
|
||||
|
||||
### 2. Use asp-prerender-* in a view
|
||||
|
||||
@@ -129,45 +131,54 @@ This can be useful if, for example, you want to avoid loading the same data twic
|
||||
|
||||
### 4. Enabling webpack build tooling
|
||||
|
||||
Of course, rather than writing your `boot-server` module and your entire SPA in plain ES5 JavaScript, it's quite likely that you'll want to write your client-side code in TypeScript or at least ES2015 code. To enable this, you can either:
|
||||
Of course, rather than writing your `boot-server` module and your entire SPA in plain ES5 JavaScript, it's quite likely that you'll want to write your client-side code in TypeScript or at least ES2015 code. To enable this, you need to set up a build system.
|
||||
|
||||
* Set up some build tool such as Babel to transpile to ES5, and always remember to run this to generate plain ES5 `.js` files before you run your application
|
||||
* Or, more conveniently, use [webpack](https://webpack.github.io/) along with the `asp-prerender-webpack-config` attribute so that `Microsoft.AspNetCore.SpaServices` can automatically build your boot module and the SPA code that it references. Then there's no need for `.js` files even to be written to disk - the build process is all dynamic and in memory.
|
||||
#### Example: Configuring Webpack to build TypeScript
|
||||
|
||||
To enable webpack builds for your server-side prerendering, amend your MVC view to specify the location of your webpack configuration file using an `asp-prerender-webpack-config` attribute, e.g.:
|
||||
Let's say you want to write your boot module and SPA code in TypeScript, and build it using Webpack. First ensure that `webpack` is installed, along with the libraries needed for TypeScript compilation:
|
||||
|
||||
<div id="my-spa" asp-prerender-module="ClientApp/boot-server"
|
||||
asp-prerender-webpack-config="webpack.config.js"></div>
|
||||
|
||||
You'll also need to install the NPM module `aspnet-webpack` if you don't have it already, e.g.:
|
||||
|
||||
npm install --save aspnet-webpack
|
||||
|
||||
This includes webpack as well as the server-side code needed to invoke it from ASP.NET Core at runtime.
|
||||
|
||||
Now, assuming you have a working webpack configuration at `webpack.config.js`, your boot module and SPA code will dynamically be built using webpack.
|
||||
|
||||
#### Example: Configuring webpack to build TypeScript
|
||||
|
||||
Let's say you want to write your boot module and SPA code in TypeScript. First ensure that `aspnet-webpack` is installed, along with the libraries needed for TypeScript compilation:
|
||||
|
||||
npm install --save aspnet-webpack ts-loader typescript
|
||||
npm install -g webpack
|
||||
npm install --save ts-loader typescript
|
||||
|
||||
Next, create a file `webpack.config.js` at the root of your project, containing:
|
||||
|
||||
```javascript
|
||||
var path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: { 'main-server': './ClientApp/boot-server.ts' },
|
||||
resolve: { extensions: [ '', '.js', '.ts' ] },
|
||||
output: {
|
||||
path: path.join(__dirname, './ClientApp/dist'),
|
||||
filename: '[name].js',
|
||||
libraryTarget: 'commonjs'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.ts$/, loader: 'ts-loader' }
|
||||
]
|
||||
}
|
||||
},
|
||||
target: 'node',
|
||||
devtool: 'inline-source-map'
|
||||
};
|
||||
```
|
||||
|
||||
This tells webpack that it should compile `.ts` files using TypeScript, and that when looking for modules by name (e.g., `boot-server`), it should also find files with `.js` and `.ts` extensions.
|
||||
|
||||
If you don't already have a `tsconfig.json` file at the root of your project, add one now. Make sure your `tsconfig.json` includes `"es6"` in its `"lib"` array so that TypeScript knows about intrinsics such as `Promise`. Here's an example `tsconfig.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"target": "es5",
|
||||
"sourceMap": true,
|
||||
"lib": [ "es6", "dom" ]
|
||||
},
|
||||
"exclude": [ "bin", "node_modules" ]
|
||||
}
|
||||
```
|
||||
|
||||
Now you can delete `ClientApp/boot-server.js`, and in its place, create `ClientApp/boot-server.ts`, containing the TypeScript equivalent of what you had before:
|
||||
|
||||
```javascript
|
||||
@@ -184,12 +195,9 @@ export default function (params: any): Promise<{ html: string}> {
|
||||
}
|
||||
```
|
||||
|
||||
Finally, you can tell `SpaServices` to use the Webpack environment you've just set up. In your MVC view where you use `aspnet-prerender-module`, also specify `aspnet-prerender-webpack-config`:
|
||||
Finally, run `webpack` on the command line to build `ClientApp/dist/main-server.js`. Then you can tell `SpaServices` to use that file for server-side prerendering. In your MVC view where you use `aspnet-prerender-module`, update the attribute value:
|
||||
|
||||
<div id="my-spa" asp-prerender-module="ClientApp/boot-server"
|
||||
asp-prerender-webpack-config="webpack.config.js"></div>
|
||||
|
||||
Now your `boot-server.ts` code should get executed when your ASP.NET Core page is rendered, and since it's TypeScript, it can of course reference any other TypeScript modules, which means your entire SPA can be written in TypeScript and executed on the server.
|
||||
<div id="my-spa" asp-prerender-module="ClientApp/dist/main-server"></div>
|
||||
|
||||
Webpack is a broad and powerful tool and can do far more than just invoke the TypeScript compiler. To learn more, see the [webpack website](https://webpack.github.io/).
|
||||
|
||||
@@ -276,30 +284,7 @@ You can now run your React code on the client by adding the following to one of
|
||||
<div id="my-spa"></div>
|
||||
<script src="/dist/main.js"></script>
|
||||
|
||||
#### Running React code on the server
|
||||
|
||||
Now you have React code being built using Webpack, you can enable server-side prerendering using the `aspnet-prerender-*` tag helpers as follows:
|
||||
|
||||
<div id="my-spa" asp-prerender-module="ClientApp/boot-server"
|
||||
asp-prerender-webpack-config="webpack.config.js"></div>
|
||||
|
||||
... along with the following boot module at `ClientApp/boot-server.jsx`:
|
||||
|
||||
```javascript
|
||||
import * as React from 'react';
|
||||
import { renderToString } from 'react-dom/server';
|
||||
import { HelloMessage } from './react-app';
|
||||
|
||||
export default function (params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve({
|
||||
html: renderToString(<HelloMessage message="from the server" />)
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
Now you should find that your React app is rendered in the page even before any JavaScript is loaded in the browser (or even if JavaScript is disabled in the browser).
|
||||
If you want to enable server-side prerendering too, follow the same process as described under [server-side prerendering](#server-side-prerendering).
|
||||
|
||||
#### Realistic React apps and Redux
|
||||
|
||||
@@ -378,17 +363,64 @@ So that's enough to build TypeScript. Here's where webpack dev middleware comes
|
||||
|
||||
### Example: A simple Webpack setup that builds LESS
|
||||
|
||||
Following on from the preceding example that builds TypeScript, you could extend your Webpack configuration further to support building LESS. There are two major approaches to doing this:
|
||||
Following on from the preceding example that builds TypeScript, you could extend your Webpack configuration further to support building LESS. There are three major approaches to doing this:
|
||||
|
||||
1. **Have each build embed the style information into your JavaScript code**. At runtime, Webpack can dynamically attach the styles to your document via JavaScript. This has certain benefits during development.
|
||||
1. **If using Angular 2, use its native style loader to attach the styles to components**. This is extremely simple and is usually the right choice if you are using Angular 2. However it only applies to Angular 2 components, not to any other part of the host page, so sometimes you might want to combine this technique with options 2 or 3 below.
|
||||
|
||||
2. **Or, have each build write a standalone `.css` file to disk**. At runtime, load it using a regular `<link rel='stylesheet'>` tag. This is likely to be the approach you'll want for production use as it's the most robust and best-performing option.
|
||||
2. **Or, use Webpack's style loader to attach the styles at runtime**. The CSS markup will be included in your JavaScript bundles and will be attached to the document dynamically. This has certain benefits during development but isn't recommended in production.
|
||||
|
||||
3. **Or, have each build write a standalone `.css` file to disk**. At runtime, load it using a regular `<link rel='stylesheet'>` tag. This is likely to be the approach you'll want for production use (at least for non-Angular 2 applications, such as React applications) as it's the most robust and best-performing option.
|
||||
|
||||
If instead of LESS you prefer SASS or another CSS preprocessor, the exact same techniques should work, but of course you'll need to replace the `less-loader` with an equivalent Webpack loader for SASS or your chosen preprocessor.
|
||||
|
||||
#### Approach 1: Loading the styles using JavaScript
|
||||
#### Approach 1: Scoping styles to Angular 2 components
|
||||
|
||||
This technique is a little simpler to set up than technique 2, plus it works flawlessly with Hot Module Replacement (HMR). The downside is that it's really only good for development time, because in production you probably don't want users to wait until JavaScript is loaded before styles are applied to the page (this would mean they'd see a 'flash of unstyled content' while the page is being loaded).
|
||||
If you are using Angular 2, this is the easiest way to perform styling. It works with both server and client rendering, supports Hot Module Replacement, and robustly scopes styles to particular components (and optionally, their descendant elements).
|
||||
|
||||
This repository's Angular 2 template uses this technique to scope styles to components out of the box. It defines those styles as `.css` files. For example, its components reference `.css` files like this:
|
||||
|
||||
```javascript
|
||||
@Component({
|
||||
...
|
||||
styles: [require('./somecomponent.css')]
|
||||
})
|
||||
export class SomeComponent { ... }
|
||||
```
|
||||
|
||||
To make this work, the template has Webpack configured to inject the contents of the `.css` file as a string literal in the built file. Here's the configuration that enables this:
|
||||
|
||||
```javascript
|
||||
// This goes into webpack.config.js, in the module loaders array:
|
||||
{ test: /\.css/, include: /ClientApp/, loader: 'raw-loader' }
|
||||
```
|
||||
|
||||
Now if you want to use LESS instead of plain CSS, you just need to include a LESS loader. Run the following in a command prompt at your project root:
|
||||
|
||||
```
|
||||
npm install --save less-loader less
|
||||
```
|
||||
|
||||
Next, add the following loader configuration to the `loaders` array in `webpack.config.js`:
|
||||
|
||||
```javascript
|
||||
{ test: /\.less/, include: /ClientApp/, loader: 'raw-loader!less-loader' }
|
||||
```
|
||||
|
||||
Notice how this chains together with `less-loader` (which transforms `.less` syntax to plain CSS syntax), then the `raw` loader (which turn the result into a string literal). With this in place, you can reference `.less` files from your Angular 2 components in the obvious way:
|
||||
|
||||
```javascript
|
||||
@Component({
|
||||
...
|
||||
styles: [require('./somecomponent.less')]
|
||||
})
|
||||
export class SomeComponent { ... }
|
||||
```
|
||||
|
||||
... and your styles will be applied in both server-side and client-side rendering.
|
||||
|
||||
#### Approach 2: Loading the styles using Webpack and JavaScript
|
||||
|
||||
This technique works with any client-side framework (not just Angular 2), and can also apply styles to the entire document rather than just individual components. It's a little simpler to set up than technique 3, plus it works flawlessly with Hot Module Replacement (HMR). The downside is that it's really only good for development time, because in production you probably don't want users to wait until JavaScript is loaded before styles are applied to the page (this would mean they'd see a 'flash of unstyled content' while the page is being loaded).
|
||||
|
||||
First create a `.less` file in your project. For example, create a file at `ClientApp/styles/mystyles.less` containing:
|
||||
|
||||
@@ -404,7 +436,7 @@ Reference this file from an `import` or `require` statement in one of your JavaS
|
||||
|
||||
```javascript
|
||||
import './styles/mystyles.less';
|
||||
```
|
||||
```
|
||||
|
||||
If you try to run the Webpack compiler now (e.g., via `webpack` on the command line), you'll get an error saying it doesn't know how to build `.less` files. So, it's time to install a Webpack loader for LESS (plus related NPM modules). In a command prompt at your project's root directory, run:
|
||||
|
||||
@@ -415,47 +447,16 @@ npm install --save less-loader less
|
||||
Finally, tell Webpack to use this whenever it encounters a `.less` file. In `webpack.config.js`, add to the `loaders` array:
|
||||
|
||||
```
|
||||
{ test: /\.less/, loader: 'style!css!less' }
|
||||
{ test: /\.less/, loader: 'style-loader!css-loader!less-loader' }
|
||||
```
|
||||
|
||||
This means that when you `import` or `require` a `.less` file, it should pass it first to the LESS compiler to produce CSS, then the output goes to the CSS and Style loaders that know how to attach it dynamically to the page at runtime.
|
||||
|
||||
That's all you need to do! Restart your site and you should see the LESS styles being applied. This technique is compatible with both source maps and Hot Module Replacement (HMR), so you can edit your `.less` files at will and see the changes appearing live in the browser.
|
||||
|
||||
**Scoping styles in Angular 2 components**
|
||||
#### Approach 3: Building LESS to CSS files on disk
|
||||
|
||||
If you're using Angular 2, you can define styles on a per-component basis rather than just globally for your whole app. Angular then takes care of ensuring that only the intended styles are applied to each component, even if the selector names would otherwise clash. To extend the above technique to per-component styling, first install the `to-string-loader` NPM module:
|
||||
|
||||
```
|
||||
npm install --save to-string-loader
|
||||
```
|
||||
|
||||
Then in your `webpack.config.js`, simplify the `loader` entry for LESS files so that it just outputs `css` (without preparing it for use in a `style` tag):
|
||||
|
||||
```javascript
|
||||
{ test: /\.less/, loader: 'css!less' }
|
||||
```
|
||||
|
||||
Now **you must remove any direct global references to the `.less` file**, since you'll no longer be loading it globally. So if you previously loaded `mystyles.less` using an `import` or `require` statement in `boot-client.ts` or similar, remove that line.
|
||||
|
||||
Finally, load the LESS file scoped to a particular Angular 2 component by declaring a `styles` value for that component. For example,
|
||||
|
||||
```javascript
|
||||
@ng.Component({
|
||||
selector: ... leave value unchanged ...,
|
||||
template: ... leave value unchanged ...,
|
||||
styles: [require('to-string!../../styles/mystyles.less')]
|
||||
})
|
||||
export class YourComponent {
|
||||
... code remains here ...
|
||||
}
|
||||
```
|
||||
|
||||
Now when you reload your page, you should file that the styles in `mystyles.less` are applied, but only to the component where you attached it. It's reasonable to use this technique in production because, even though the styles now depend on JavaScript to be applied, they are only used on elements that are injected via JavaScript anyway.
|
||||
|
||||
#### Approach 2: Building LESS to CSS files on disk
|
||||
|
||||
This technique takes a little more work to set up than technique 1, and lacks compatibility with HMR. But it's much better for production use if your styles are applied to the whole page (not just elements constructed via JavaScript), because it loads the CSS independently of JavaScript.
|
||||
This technique takes a little more work to set up than technique 2, and lacks compatibility with HMR. But it's much better for production use if your styles are applied to the whole page (not just elements constructed via JavaScript), because it loads the CSS independently of JavaScript.
|
||||
|
||||
First add a `.less` file into your project. For example, create a file at `ClientApp/styles/mystyles.less` containing:
|
||||
|
||||
@@ -471,7 +472,7 @@ Reference this file from an `import` or `require` statement in one of your JavaS
|
||||
|
||||
```javascript
|
||||
import './styles/mystyles.less';
|
||||
```
|
||||
```
|
||||
|
||||
If you try to run the Webpack compiler now (e.g., via `webpack` on the command line), you'll get an error saying it doesn't know how to build `.less` files. So, it's time to install a Webpack loader for LESS (plus related NPM modules). In a command prompt at your project's root directory, run:
|
||||
|
||||
@@ -488,7 +489,7 @@ var extractStyles = new (require('extract-text-webpack-plugin'))('mystyles.css')
|
||||
This creates a plugin instance that will output text to a file called `mystyles.css`. You can now compile `.less` files and emit the resulting CSS text into that file. To do so, add the following to the `loaders` array in your Webpack configuration:
|
||||
|
||||
```javascript
|
||||
{ test: /\.less$/, loader: extractStyles.extract('css!less') }
|
||||
{ test: /\.less$/, loader: extractStyles.extract('css-loader!less-loader') }
|
||||
```
|
||||
|
||||
This tells Webpack that, whenever it finds a `.less` file, it should use the LESS loader to produce CSS, and then feed that CSS into the `extractStyles` object which you've already configured to write a file on disk called `mystyles.css`. Finally, for this to actually work, you need to include `extractStyles` in the list of active plugins. Just add that object to the `plugins` array in your Webpack config, e.g.:
|
||||
@@ -517,7 +518,7 @@ if (env.IsDevelopment()) {
|
||||
app.UseWebpackDevMiddleware();
|
||||
}
|
||||
|
||||
// You call to app.UseStaticFiles(); should be here
|
||||
// Your call to app.UseStaticFiles(); should be here
|
||||
```
|
||||
|
||||
Also check your webpack configuration at `webpack.config.js`. Since `UseWebpackDevMiddleware` needs to know which incoming requests to intercept, make sure you've specified a `publicPath` value on your `output`, for example:
|
||||
@@ -588,6 +589,14 @@ Now when you load your application in a browser, you should see a message like t
|
||||
|
||||
If you edit any of your source files that get built by webpack, the result will automatically be pushed into the browser. As for what the browser does with these updates - that's a matter of how you configure it - see below.
|
||||
|
||||
**Note for TypeScript + Visual Studio users**
|
||||
|
||||
If you want HMR to work correctly with TypeScript, and you use Visual Studio on Windows as an IDE (but not VS Code), then you will need to make a further configuration change. In your `.csproj` file, in one of the `<PropertyGroup>` elements, add this:
|
||||
|
||||
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
|
||||
|
||||
This is necessary because otherwise, Visual Studio will try to auto-compile TypeScript files as you save changes to them. That default auto-compilation behavior is unhelpful in projects where you have a proper build system (e.g., Webpack), because VS doesn't know about your build system and would emit `.js` files in the wrong locations, which would in turn cause problems with your real build or deployment mechanisms.
|
||||
|
||||
#### Enabling hot replacement for React components
|
||||
|
||||
Webpack has built-in support for updating React components in place. To enable this, amend your `UseWebpackDevMiddleware` call further as follows:
|
||||
@@ -648,3 +657,141 @@ Then, since `MapSpaFallbackRoute` is last, any other requests **that don't appea
|
||||
Any requests that do appear to be for static files (i.e., those that end with filename extensions), will *not* be handled by `MapSpaFallbackRoute`, and so will end up as 404s.
|
||||
|
||||
This is not a perfect solution to the problem of identifying 404s, because for example `MapSpaFallbackRoute` will not match requests for `/users/albert.einstein`, because it appears to contain a filename extension (`.einstein`). If you need your SPA to handle routes like that, then don't use `MapSpaFallbackRoute` - just use a regular MVC catch-all route. But then beware that requests for unknown static files will result in your client-side app being rendered.
|
||||
|
||||
## Debugging your projects
|
||||
|
||||
How to attach and use a debugger depends on what code you want to debug. For details, see:
|
||||
|
||||
* [How to debug your C# code that runs on the server](#debugging-your-c-code-that-runs-on-the-server)
|
||||
* How to debug your JavaScript/TypeScript code:
|
||||
* ... [when it's running in a browser](#debugging-your-javascripttypescript-code-when-its-running-in-a-browser)
|
||||
* ... [when it's running on the server](#debugging-your-javascripttypescript-code-when-it-runs-on-the-server) (i.e., via `asp-prerender` or NodeSevices)
|
||||
|
||||
### Debugging your C# code that runs on the server
|
||||
|
||||
You can use any .NET debugger, for example Visual Studio's C# debugger or [Visual Studio Code's C# debugger](https://code.visualstudio.com/Docs/editor/debugging).
|
||||
|
||||
### Debugging your JavaScript/TypeScript code when it's running in a browser
|
||||
|
||||
**The absolute most reliable way of debugging your client-side code is to use your browser's built-in debugger.** This is much easier to make work than debugging via an IDE, plus it offers much richer insight into what's going on than your IDE will do (for example, you'll be able to inspect the DOM and capture performance profiles as well as just set breakpoints and step through code).
|
||||
|
||||
If you're unfamiliar with your browser's debugging tools, then take the time to get familiar with them. You will become more productive.
|
||||
|
||||
#### Using your browser's built-in debugging tools
|
||||
|
||||
##### Using Chrome's developer tools for debugging
|
||||
|
||||
In Chrome, with your application running in the browser, [open the developer tools](https://developer.chrome.com/devtools#access). You can now find your code:
|
||||
|
||||
* In the developer tools *Sources* tab, expand folders in the hierarchy pane on the left to find the file you want
|
||||
* Or, press `ctrl`+`o` (on Windows) or `cmd`+`o` on Mac, then start to type name name of the file you want to open (e.g., `counter.component.ts`)
|
||||
|
||||
With source maps enabled (which is the case in the project templates in this repo), you'll be able to see your original TypeScript source code, set breakpoints on it, etc.
|
||||
|
||||
##### Using Internet Explorer/Edge's developer tools (F12) for debugging
|
||||
|
||||
In Internet Explorer or Edge, with your application running in the browser, open the F12 developer tools by pressing `F12`. You can now find your code:
|
||||
|
||||
* In the F12 tools *Debugger* tab, expand folders in the hierarchy pane on the left to find the file you want
|
||||
* Or, press `ctrl`+`o`, then start to type name name of the file you want to open (e.g., `counter.component.ts`)
|
||||
|
||||
With source maps enabled (which is the case in the project templates in this repo), you'll be able to see your original TypeScript source code, set breakpoints on it, etc.
|
||||
|
||||
##### Using Firefox's developer tools for debugging
|
||||
|
||||
In Firefox, with your application running in the browser, open the developer tools by pressing `F12`. You can now find your code:
|
||||
|
||||
* In the developer tools *Debugger* tab, expand folders in the hierarchy pane titled *Sources* towards the bottom to find the file you want
|
||||
* Or, press `ctrl`+`o` (on Windows) or `cmd`+`o` on Mac, then start to type name name of the file you want to open (e.g., `counter.component.ts`)
|
||||
|
||||
With source maps enabled (which is the case in the project templates in this repo), you'll be able to see your original TypeScript source code, set breakpoints on it, etc.
|
||||
|
||||
##### How browser-based debugging interacts with Hot Module Replacement (HMR)
|
||||
|
||||
If you're using HMR, then each time you modify a file, the Webpack dev middleware restarts your client-side application, adding a new version of each affected module, without reloading the page. This can be confusing during debugging, because any breakpoints set on the old version of the code will still be there, but they will no longer get hit, because the old version of the module is no longer in use.
|
||||
|
||||
You have two options to get breakpoints that will be hit as expected:
|
||||
|
||||
* **Reload the page** (e.g., by pressing `F5`). Then your existing breakpoints will be applied to the new version of the module. This is obviously the easiest solution.
|
||||
* Or, if you don't want to reload the page, you can **set new breakpoints on the new version of the module**. To do this, look in your browser's debug tools' list of source files, and identify the newly-injected copy of the module you want to debug. It will typically have a suffix on its URL such as `?4a2c`, and may appear in a new top-level hierarchy entry called `webpack://`. Set a breakpoint in the newly-injected module, and it will be hit as expected as your application runs.
|
||||
|
||||
#### Using Visual Studio Code's "Debugger for Chrome" extension
|
||||
|
||||
If you're using Visual Studio Code and Chrome, you can set breakpoints directly on your TypeScript source code in the IDE. To do this:
|
||||
|
||||
1. Install VS Code's [*Debugger for Chrome* extension](https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome)
|
||||
2. Ensure your application server has started and can be reached with a browser (for example, run `dotnet watch run`)
|
||||
3. In VS Code, open its *Debug* view (on Windows/Linux, press `ctrl`+`shift`+`d`; on Mac, press `cmd`+`shift`+`d`).
|
||||
4. Press the cog icon and when prompted to *Select environment*, choose `Chrome`. VS Code will create a `launch.json` file for you. This describes how the debugger and browser should be launched.
|
||||
5. Edit your new `.vscode/launch.json` file to specify the correct `url` and `webRoot` for your application. If you're using the project templates in this repo, then the values you probably want are:
|
||||
* For `url`, put `"http://localhost:5000"` (but of course, change this if you're using a different port)
|
||||
* For `port`, put `5000` (or your custom port number if applicable)
|
||||
* For `workspace` in **both** configurations, put `"${workspaceRoot}/wwwroot"`
|
||||
* This tells the debugger how URLs within your application correspond to files in your VS Code workspace. By default, ASP.NET Core projects treat `wwwroot` as the root directory for publicly-served files, so `http://localhost:5000/dist/myfile.js` corresponds to `<yourprojectroot>/wwwroot/dist/myfile.js`. VS Code doesn't know about `wwwroot` unless you tell it.
|
||||
* **Important:** If your VS Code window's workspace root is not the same as your ASP.NET Core project root (for example, if VS Code is opened at a higher-level directory to show both your ASP.NET Core project plus other peer-level directories), then you will need to amend `workspace` correspondingly (e.g., to `"${workspaceRoot}/SomeDir/MyAspNetProject/wwwroot"`).
|
||||
6. Start the debugger:
|
||||
* While still on the *Debug* view, from the dropdown near the top-left, choose "*Launch Chrome against localhost, with sourcemaps*".
|
||||
* Press the *Play* icon. Your application will launch in Chrome.
|
||||
* If it does nothing for a while, then eventually gives the error *Cannot connect to runtime process*, that's because you already have an instance of Chrome running. Close it first, then try again.
|
||||
7. Finally, you can now set and hit breakpoints in your TypeScript code in VS Code.
|
||||
|
||||
For more information about VS Code's built-in debugging facilities, [see its documentation](https://code.visualstudio.com/Docs/editor/debugging).
|
||||
|
||||
Caveats:
|
||||
|
||||
* The debugging interface between VS Code and Chrome occasionally has issues. If you're unable to set or hit breakpoints, or if you try to set a breakpoint but it appears in the wrong place, you may need to stop and restart the debugger (and often, the whole Chrome process).
|
||||
* If you're using Hot Module Replacement (HMR), then whenever you edit a file, the breakpoints in it will no longer hit. This is because HMR loads a new version of the module into the browser, so the old code no longer runs. To fix this, you must:
|
||||
* Reload the page in Chrome (e.g., by pressing `F5`)
|
||||
* **Then** (and only then), remove and re-add the breakpoint in VS Code. It will now be attached to the current version of your module. Alternatively, stop and restart debugging altogether.
|
||||
* If you prefer, you can use "*Attach to Chrome, with sourcemaps*" instead of launching a new Chrome instance, but this is a bit trickier: you must first start Chrome using the command-line option `--remote-debugging-port=9222`, and you must ensure there are no other tabs opened (otherwise, it might try to connect to the wrong one).
|
||||
|
||||
|
||||
#### Using Visual Studio's built-in debugger for Internet Explorer
|
||||
|
||||
If you're using Visual Studio on Windows, and are running your app in Internet Explorer 11 (not Edge!), then you can use VS's built-in debugger rather than Interner Explorer's F12 tools if you prefer. To do this:
|
||||
|
||||
1. In Internet Explorer, [enable script debugging](https://msdn.microsoft.com/en-us/library/ms241741\(v=vs.100\).aspx)
|
||||
2. In Visual Studio, [set the default "*Browse with*" option](http://stackoverflow.com/a/31959053) to Internet Explorer
|
||||
3. In Visual Studio, press F5 to launch your application with the debugger in Internet Explorer.
|
||||
* When the page has loaded in the browser, you'll be able to set and hit breakpoints in your TypeScript source files in Visual Studio.
|
||||
|
||||
Caveats:
|
||||
|
||||
* If you're using Hot Module Replacement, you'll need to stop and restart the debugger any time you change a source file. VS's IE debugger does not recognise that source files might change while the debugging session is in progress.
|
||||
* Realistically, you are not going to be as productive using this approach to debugging as you would be if you used your browser's built-in debugging tools. The browser's built-in debugging tools are far more effective: they are always available (you don't have to have launched your application in a special way), they better handle HMR, and they don't make your application very slow to launch.
|
||||
|
||||
## Debugging your JavaScript/TypeScript code when it runs on the server
|
||||
|
||||
When you're using NodeServices or the server-side prerendering feature included in the project templates in this repo, your JavaScript/TypeScript code will execute on the server in a background instance of Node.js. You can enable debugging on that Node.js instance. Here's how to do it.
|
||||
|
||||
First, in your `Startup.cs` file, in the `ConfigureServices` method, add the following:
|
||||
|
||||
```
|
||||
services.AddNodeServices(options => {
|
||||
options.LaunchWithDebugging = true;
|
||||
options.DebuggingPort = 5858;
|
||||
});
|
||||
```
|
||||
|
||||
Now, run your application from that command line (e.g., `dotnet run`). Then in a browser visit one of your pages that causes server-side JS to execute.
|
||||
|
||||
In the console, you should see all the normal trace messages appear, plus among them will be:
|
||||
|
||||
-----
|
||||
*** Node.js debugging is enabled ***
|
||||
Debugger listening on port 5858
|
||||
|
||||
To debug, run:
|
||||
node-inspector
|
||||
|
||||
If you haven't yet installed node-inspector, you can do so as follows:
|
||||
npm install -g node-inspector
|
||||
-----
|
||||
|
||||
In some other command line window, follow those instructions (i.e., install `node-inspector` as it describes, then run `node-inspector`). Then you can open a browser at `http://127.0.0.1:8080/?port=5858` and you'll see the debugger UI.
|
||||
|
||||
By expanding the `webpack://` entry in the sidebar, you'll be able to find your original TypeScript code (it's using source maps), and then set breakpoints in it. When you re-run your app in another browser window, your breakpoints will be hit, then you can debug the server-side execution just like you'd debug client-side execution. It looks like this:
|
||||
|
||||

|
||||
|
||||
(Note: although this looks like Chrome's native debugger for client-side code, it is actually a JavaScript-powered debugger UI that's connected to the server-side runtime)
|
||||
|
||||
@@ -7,10 +7,22 @@ using Microsoft.AspNetCore.SpaServices;
|
||||
|
||||
namespace Microsoft.AspNetCore.Builder
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods useful for configuring routing in a single-page application (SPA).
|
||||
/// </summary>
|
||||
public static class SpaRouteExtensions
|
||||
{
|
||||
private const string ClientRouteTokenName = "clientRoute";
|
||||
|
||||
/// <summary>
|
||||
/// Configures a route that is automatically bypassed if the requested URL appears to be for a static file
|
||||
/// (e.g., if it has a filename extension).
|
||||
/// </summary>
|
||||
/// <param name="routeBuilder">The <see cref="IRouteBuilder"/>.</param>
|
||||
/// <param name="name">The route name.</param>
|
||||
/// <param name="defaults">Default route parameters.</param>
|
||||
/// <param name="constraints">Route constraints.</param>
|
||||
/// <param name="dataTokens">Route data tokens.</param>
|
||||
public static void MapSpaFallbackRoute(
|
||||
this IRouteBuilder routeBuilder,
|
||||
string name,
|
||||
@@ -27,6 +39,16 @@ namespace Microsoft.AspNetCore.Builder
|
||||
dataTokens);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures a route that is automatically bypassed if the requested URL appears to be for a static file
|
||||
/// (e.g., if it has a filename extension).
|
||||
/// </summary>
|
||||
/// <param name="routeBuilder">The <see cref="IRouteBuilder"/>.</param>
|
||||
/// <param name="name">The route name.</param>
|
||||
/// <param name="templatePrefix">The template prefix.</param>
|
||||
/// <param name="defaults">Default route parameters.</param>
|
||||
/// <param name="constraints">Route constraints.</param>
|
||||
/// <param name="dataTokens">Route data tokens.</param>
|
||||
public static void MapSpaFallbackRoute(
|
||||
this IRouteBuilder routeBuilder,
|
||||
string name,
|
||||
|
||||
115
src/Microsoft.AspNetCore.SpaServices/TypeScript/Prerenderer.ts
Normal file
115
src/Microsoft.AspNetCore.SpaServices/TypeScript/Prerenderer.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
/// <reference path="../npm/aspnet-prerendering/src/PrerenderingInterfaces.d.ts" />
|
||||
import * as url from 'url';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
declare var __non_webpack_require__;
|
||||
|
||||
// Separate declaration and export just to add type checking on function signature
|
||||
export const renderToString: RenderToStringFunc = renderToStringImpl;
|
||||
|
||||
// This function is invoked by .NET code (via NodeServices). Its job is to hand off execution to the application's
|
||||
// prerendering boot function. It can operate in two modes:
|
||||
// [1] Legacy mode
|
||||
// This is for backward compatibility with projects created with templates older than the generator version 0.6.0.
|
||||
// In this mode, we don't really do anything here - we just load the 'aspnet-prerendering' NPM module (which must
|
||||
// exist in node_modules, and must be v1.x (not v2+)), and pass through all the parameters to it. Code in
|
||||
// 'aspnet-prerendering' v1.x will locate the boot function and invoke it.
|
||||
// The drawback to this mode is that, for it to work, you have to deploy node_modules to production.
|
||||
// [2] Current mode
|
||||
// This is for projects created with the Yeoman generator 0.6.0+ (or projects manually updated). In this mode,
|
||||
// we don't invoke 'require' at runtime at all. All our dependencies are bundled into the NuGet package, so you
|
||||
// don't have to deploy node_modules to production.
|
||||
// To determine whether we're in mode [1] or [2], the code locates your prerendering boot function, and checks whether
|
||||
// a certain flag is attached to the function instance.
|
||||
function renderToStringImpl(callback: RenderToStringCallback, applicationBasePath: string, bootModule: BootModuleInfo, absoluteRequestUrl: string, requestPathAndQuery: string, customDataParameter: any, overrideTimeoutMilliseconds: number) {
|
||||
try {
|
||||
const forceLegacy = isLegacyAspNetPrerendering();
|
||||
const renderToStringFunc = !forceLegacy && findRenderToStringFunc(applicationBasePath, bootModule);
|
||||
const isNotLegacyMode = renderToStringFunc && renderToStringFunc['isServerRenderer'];
|
||||
|
||||
if (isNotLegacyMode) {
|
||||
// Current (non-legacy) mode - we invoke the exported function directly (instead of going through aspnet-prerendering)
|
||||
// It's type-safe to just apply the incoming args to this function, because we already type-checked that it's a RenderToStringFunc,
|
||||
// just like renderToStringImpl itself is.
|
||||
renderToStringFunc.apply(null, arguments);
|
||||
} else {
|
||||
// Legacy mode - just hand off execution to 'aspnet-prerendering' v1.x, which must exist in node_modules at runtime
|
||||
const aspNetPrerenderingV1RenderToString = require('aspnet-prerendering').renderToString;
|
||||
if (aspNetPrerenderingV1RenderToString) {
|
||||
aspNetPrerenderingV1RenderToString(callback, applicationBasePath, bootModule, absoluteRequestUrl, requestPathAndQuery, customDataParameter, overrideTimeoutMilliseconds);
|
||||
} else {
|
||||
callback('If you use aspnet-prerendering >= 2.0.0, you must update your server-side boot module to call createServerRenderer. '
|
||||
+ 'Either update your boot module code, or revert to aspnet-prerendering version 1.x');
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
// Make sure loading errors are reported back to the .NET part of the app
|
||||
callback(
|
||||
'Prerendering failed because of error: '
|
||||
+ ex.stack
|
||||
+ '\nCurrent directory is: '
|
||||
+ process.cwd()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
function findBootModule(applicationBasePath: string, bootModule: BootModuleInfo): any {
|
||||
const bootModuleNameFullPath = path.resolve(applicationBasePath, bootModule.moduleName);
|
||||
if (bootModule.webpackConfig) {
|
||||
// If you're using asp-prerender-webpack-config, you're definitely in legacy mode
|
||||
return null;
|
||||
} else {
|
||||
return __non_webpack_require__(bootModuleNameFullPath);
|
||||
}
|
||||
}
|
||||
|
||||
function findRenderToStringFunc(applicationBasePath: string, bootModule: BootModuleInfo): RenderToStringFunc {
|
||||
// First try to load the module
|
||||
const foundBootModule = findBootModule(applicationBasePath, bootModule);
|
||||
if (foundBootModule === null) {
|
||||
return null; // Must be legacy mode
|
||||
}
|
||||
|
||||
// Now try to pick out the function they want us to invoke
|
||||
let renderToStringFunc: RenderToStringFunc;
|
||||
if (bootModule.exportName) {
|
||||
// Explicitly-named export
|
||||
renderToStringFunc = foundBootModule[bootModule.exportName];
|
||||
} else if (typeof foundBootModule !== 'function') {
|
||||
// TypeScript-style default export
|
||||
renderToStringFunc = foundBootModule.default;
|
||||
} else {
|
||||
// Native default export
|
||||
renderToStringFunc = foundBootModule;
|
||||
}
|
||||
|
||||
// Validate the result
|
||||
if (typeof renderToStringFunc !== 'function') {
|
||||
if (bootModule.exportName) {
|
||||
throw new Error(`The module at ${ bootModule.moduleName } has no function export named ${ bootModule.exportName }.`);
|
||||
} else {
|
||||
throw new Error(`The module at ${ bootModule.moduleName } does not export a default function, and you have not specified which export to invoke.`);
|
||||
}
|
||||
}
|
||||
|
||||
return renderToStringFunc;
|
||||
}
|
||||
|
||||
function isLegacyAspNetPrerendering() {
|
||||
const version = getAspNetPrerenderingPackageVersion();
|
||||
return version && /^1\./.test(version);
|
||||
}
|
||||
|
||||
function getAspNetPrerenderingPackageVersion() {
|
||||
try {
|
||||
const packageEntryPoint = __non_webpack_require__.resolve('aspnet-prerendering');
|
||||
const packageDir = path.dirname(packageEntryPoint);
|
||||
const packageJsonPath = path.join(packageDir, 'package.json');
|
||||
const packageJson = __non_webpack_require__(packageJsonPath);
|
||||
return packageJson.version.toString();
|
||||
} catch(ex) {
|
||||
// Implies aspnet-prerendering isn't in node_modules at all (or node_modules itself doesn't exist,
|
||||
// which will be the case in production based on latest templates).
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Pass through the invocation to the 'aspnet-webpack' package, verifying that it can be loaded
|
||||
export function createWebpackDevServer(callback) {
|
||||
let aspNetWebpack;
|
||||
try {
|
||||
aspNetWebpack = require('aspnet-webpack');
|
||||
} catch (ex) {
|
||||
// Developers sometimes have trouble with badly-configured Node installations, where it's unable
|
||||
// to find node_modules. Or they accidentally fail to deploy node_modules, or even to run 'npm install'.
|
||||
// Make sure such errors are reported back to the .NET part of the app.
|
||||
callback(
|
||||
'Webpack dev middleware failed because of an error while loading \'aspnet-webpack\'. Error was: '
|
||||
+ ex.stack
|
||||
+ '\nCurrent directory is: '
|
||||
+ process.cwd()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
return aspNetWebpack.createWebpackDevServer.apply(this, arguments);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es3",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"types": ["node"],
|
||||
"lib": ["es2015"]
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
@@ -8,16 +8,29 @@ using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
// Putting in this namespace so it's always available whenever MapRoute is
|
||||
|
||||
namespace Microsoft.AspNetCore.Builder
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods that can be used to enable Webpack dev middleware support.
|
||||
/// </summary>
|
||||
public static class WebpackDevMiddleware
|
||||
{
|
||||
private const string WebpackDevMiddlewareScheme = "http";
|
||||
private const string WebpackHotMiddlewareEndpoint = "/__webpack_hmr";
|
||||
private const string DefaultConfigFile = "webpack.config.js";
|
||||
|
||||
/// <summary>
|
||||
/// Enables Webpack dev middleware support. This hosts an instance of the Webpack compiler in memory
|
||||
/// in your application so that you can always serve up-to-date Webpack-built resources without having
|
||||
/// to run the compiler manually. Since the Webpack compiler instance is retained in memory, incremental
|
||||
/// compilation is vastly faster that re-running the compiler from scratch.
|
||||
///
|
||||
/// Incoming requests that match Webpack-built files will be handled by returning the Webpack compiler
|
||||
/// output directly, regardless of files on disk. If compilation is in progress when the request arrives,
|
||||
/// the response will pause until updated compiler output is ready.
|
||||
/// </summary>
|
||||
/// <param name="appBuilder">The <see cref="IApplicationBuilder"/>.</param>
|
||||
/// <param name="options">Options for configuring the Webpack compiler instance.</param>
|
||||
public static void UseWebpackDevMiddleware(
|
||||
this IApplicationBuilder appBuilder,
|
||||
WebpackDevMiddlewareOptions options = null)
|
||||
@@ -42,6 +55,19 @@ namespace Microsoft.AspNetCore.Builder
|
||||
// as fast as some theoretical future alternative.
|
||||
var nodeServicesOptions = new NodeServicesOptions(appBuilder.ApplicationServices);
|
||||
nodeServicesOptions.WatchFileExtensions = new string[] {}; // Don't watch anything
|
||||
if (!string.IsNullOrEmpty(options.ProjectPath))
|
||||
{
|
||||
nodeServicesOptions.ProjectPath = options.ProjectPath;
|
||||
}
|
||||
|
||||
if (options.EnvironmentVariables != null)
|
||||
{
|
||||
foreach (var kvp in options.EnvironmentVariables)
|
||||
{
|
||||
nodeServicesOptions.EnvironmentVariables[kvp.Key] = kvp.Value;
|
||||
}
|
||||
}
|
||||
|
||||
var nodeServices = NodeServicesFactory.CreateNodeServices(nodeServicesOptions);
|
||||
|
||||
// Get a filename matching the middleware Node script
|
||||
@@ -50,17 +76,23 @@ namespace Microsoft.AspNetCore.Builder
|
||||
var nodeScript = new StringAsTempFile(script); // Will be cleaned up on process exit
|
||||
|
||||
// Tell Node to start the server hosting webpack-dev-middleware
|
||||
var hostEnv = (IHostingEnvironment)appBuilder.ApplicationServices.GetService(typeof(IHostingEnvironment));
|
||||
var projectPath = options.ProjectPath ?? hostEnv.ContentRootPath;
|
||||
var devServerOptions = new
|
||||
{
|
||||
webpackConfigPath = Path.Combine(projectPath, options.ConfigFile ?? DefaultConfigFile),
|
||||
suppliedOptions = options
|
||||
webpackConfigPath = Path.Combine(nodeServicesOptions.ProjectPath, options.ConfigFile ?? DefaultConfigFile),
|
||||
suppliedOptions = options,
|
||||
understandsMultiplePublicPaths = true
|
||||
};
|
||||
var devServerInfo =
|
||||
nodeServices.InvokeExportAsync<WebpackDevServerInfo>(nodeScript.FileName, "createWebpackDevServer",
|
||||
JsonConvert.SerializeObject(devServerOptions)).Result;
|
||||
|
||||
// If we're talking to an older version of aspnet-webpack, it will return only a single PublicPath,
|
||||
// not an array of PublicPaths. Handle that scenario.
|
||||
if (devServerInfo.PublicPaths == null)
|
||||
{
|
||||
devServerInfo.PublicPaths = new[] { devServerInfo.PublicPath };
|
||||
}
|
||||
|
||||
// Proxy the corresponding requests through ASP.NET and into the Node listener
|
||||
// Note that this is hardcoded to make requests to "localhost" regardless of the hostname of the
|
||||
// server as far as the client is concerned. This is because ConditionalProxyMiddlewareOptions is
|
||||
@@ -70,7 +102,10 @@ namespace Microsoft.AspNetCore.Builder
|
||||
// able to make outbound requests to it from here.
|
||||
var proxyOptions = new ConditionalProxyMiddlewareOptions(WebpackDevMiddlewareScheme,
|
||||
"localhost", devServerInfo.Port.ToString());
|
||||
appBuilder.UseMiddleware<ConditionalProxyMiddleware>(devServerInfo.PublicPath, proxyOptions);
|
||||
foreach (var publicPath in devServerInfo.PublicPaths)
|
||||
{
|
||||
appBuilder.UseMiddleware<ConditionalProxyMiddleware>(publicPath, proxyOptions);
|
||||
}
|
||||
|
||||
// While it would be nice to proxy the /__webpack_hmr requests too, these return an EventStream,
|
||||
// and the Microsoft.AspNetCore.Proxy code doesn't handle that entirely - it throws an exception after
|
||||
@@ -92,6 +127,10 @@ namespace Microsoft.AspNetCore.Builder
|
||||
class WebpackDevServerInfo
|
||||
{
|
||||
public int Port { get; set; }
|
||||
public string[] PublicPaths { get; set; }
|
||||
|
||||
// For back-compatibility with older versions of aspnet-webpack, in the case where your webpack
|
||||
// configuration contains exactly one config entry. This will be removed soon.
|
||||
public string PublicPath { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,43 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNetCore.SpaServices.Webpack
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for configuring a Webpack dev middleware compiler.
|
||||
/// </summary>
|
||||
public class WebpackDevMiddlewareOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// If true, hot module replacement (HMR) will be enabled. This automatically updates Webpack-built
|
||||
/// resources (such as JavaScript, CSS, or images) in your web browser whenever source files are changed.
|
||||
/// </summary>
|
||||
public bool HotModuleReplacement { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the internal port number that client-side HMR code will connect to.
|
||||
/// </summary>
|
||||
public int HotModuleReplacementServerPort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, enables React-specific extensions to Webpack's hot module replacement (HMR) feature.
|
||||
/// This enables React components to be updated without losing their in-memory state.
|
||||
/// </summary>
|
||||
public bool ReactHotModuleReplacement { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the Webpack configuration file to be used. If not set, defaults to 'webpack.config.js'.
|
||||
/// </summary>
|
||||
public string ConfigFile { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The root path of your project. Webpack runs in this context.
|
||||
/// </summary>
|
||||
public string ProjectPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies additional environment variables to be passed to the Node instance hosting
|
||||
/// the webpack compiler.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> EnvironmentVariables { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
/typings/
|
||||
/node_modules/
|
||||
/*.js
|
||||
/*.d.ts
|
||||
/**/*.js
|
||||
|
||||
/**/.d.ts
|
||||
!/src/**/*.d.ts
|
||||
|
||||
@@ -1,20 +1,28 @@
|
||||
{
|
||||
"name": "aspnet-prerendering",
|
||||
"version": "1.0.5",
|
||||
"version": "2.0.0",
|
||||
"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": {
|
||||
"prepublish": "rimraf *.d.ts && tsd update && tsc && echo 'Finished building NPM package \"aspnet-prerendering\"'",
|
||||
"prepublish": "rimraf *.d.ts && tsc && echo 'Finished building NPM package \"aspnet-prerendering\"'",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Microsoft",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/aspnet/JavaScriptServices/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aspnet/JavaScriptServices.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"domain-task": "^2.0.1",
|
||||
"es6-promise": "^3.1.2"
|
||||
"domain-task": "^2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^6.0.42",
|
||||
"@types/whatwg-fetch": "0.0.31",
|
||||
"rimraf": "^2.5.4",
|
||||
"typescript": "^1.8.10"
|
||||
"typescript": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'es6-promise';
|
||||
/// <reference path="./PrerenderingInterfaces.d.ts" />
|
||||
import * as url from 'url';
|
||||
import * as path from 'path';
|
||||
import * as domain from 'domain';
|
||||
@@ -7,41 +7,8 @@ import { baseUrl } from 'domain-task/fetch';
|
||||
|
||||
const defaultTimeoutMilliseconds = 30 * 1000;
|
||||
|
||||
export interface RenderToStringCallback {
|
||||
(error: any, result: RenderToStringResult): void;
|
||||
}
|
||||
|
||||
export interface RenderToStringResult {
|
||||
html: string;
|
||||
globals: { [key: string]: any };
|
||||
}
|
||||
|
||||
export interface BootFunc {
|
||||
(params: BootFuncParams): Promise<RenderToStringResult>;
|
||||
}
|
||||
|
||||
export interface BootFuncParams {
|
||||
location: url.Url; // e.g., Location object containing information '/some/path'
|
||||
origin: string; // e.g., 'https://example.com:1234'
|
||||
url: string; // e.g., '/some/path'
|
||||
absoluteUrl: string; // e.g., 'https://example.com:1234/some/path'
|
||||
domainTasks: Promise<any>;
|
||||
data: any; // any custom object passed through from .NET
|
||||
}
|
||||
|
||||
export interface BootModuleInfo {
|
||||
moduleName: string;
|
||||
exportName?: string;
|
||||
webpackConfig?: string;
|
||||
}
|
||||
|
||||
export function renderToString(callback: RenderToStringCallback, applicationBasePath: string, bootModule: BootModuleInfo, absoluteRequestUrl: string, requestPathAndQuery: string, customDataParameter: any, overrideTimeoutMilliseconds: number) {
|
||||
findBootFunc(applicationBasePath, bootModule, (findBootFuncError, bootFunc) => {
|
||||
if (findBootFuncError) {
|
||||
callback(findBootFuncError, null);
|
||||
return;
|
||||
}
|
||||
|
||||
export function createServerRenderer(bootFunc: BootFunc): RenderToStringFunc {
|
||||
const resultFunc = (callback: RenderToStringCallback, applicationBasePath: string, bootModule: BootModuleInfo, absoluteRequestUrl: string, requestPathAndQuery: string, customDataParameter: any, overrideTimeoutMilliseconds: number) => {
|
||||
// Prepare a promise that will represent the completion of all domain tasks in this execution context.
|
||||
// The boot code will wait for this before performing its final render.
|
||||
let domainTaskCompletionPromiseResolve;
|
||||
@@ -76,7 +43,7 @@ export function renderToString(callback: RenderToStringCallback, applicationBase
|
||||
}
|
||||
const timeoutMilliseconds = overrideTimeoutMilliseconds || defaultTimeoutMilliseconds; // e.g., pass -1 to override as 'never time out'
|
||||
const bootFuncPromiseWithTimeout = timeoutMilliseconds > 0
|
||||
? wrapWithTimeout(bootFuncPromise, timeoutMilliseconds,
|
||||
? wrapWithTimeout(bootFuncPromise, timeoutMilliseconds,
|
||||
`Prerendering timed out after ${timeoutMilliseconds}ms because the boot function in '${bootModule.moduleName}' `
|
||||
+ 'returned a promise that did not resolve or reject. Make sure that your boot function always resolves or '
|
||||
+ 'rejects its promise. You can change the timeout value using the \'asp-prerender-timeout\' tag helper.')
|
||||
@@ -84,7 +51,7 @@ export function renderToString(callback: RenderToStringCallback, applicationBase
|
||||
|
||||
// Actually perform the rendering
|
||||
bootFuncPromiseWithTimeout.then(successResult => {
|
||||
callback(null, { html: successResult.html, globals: successResult.globals });
|
||||
callback(null, successResult);
|
||||
}, error => {
|
||||
callback(error, null);
|
||||
});
|
||||
@@ -97,7 +64,14 @@ export function renderToString(callback: RenderToStringCallback, applicationBase
|
||||
domainTaskCompletionPromiseResolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Indicate to the prerendering code bundled into Microsoft.AspNetCore.SpaServices that this is a serverside rendering
|
||||
// function, so it can be invoked directly. This flag exists only so that, in its absence, we can run some different
|
||||
// backward-compatibility logic.
|
||||
resultFunc['isServerRenderer'] = true;
|
||||
|
||||
return resultFunc;
|
||||
}
|
||||
|
||||
function wrapWithTimeout<T>(promise: Promise<T>, timeoutMilliseconds: number, timeoutRejectionValue: any): Promise<T> {
|
||||
@@ -119,62 +93,9 @@ function wrapWithTimeout<T>(promise: Promise<T>, timeoutMilliseconds: number, ti
|
||||
});
|
||||
}
|
||||
|
||||
function findBootModule<T>(applicationBasePath: string, bootModule: BootModuleInfo, callback: (error: any, foundModule: T) => void) {
|
||||
const bootModuleNameFullPath = path.resolve(applicationBasePath, bootModule.moduleName);
|
||||
if (bootModule.webpackConfig) {
|
||||
const webpackConfigFullPath = path.resolve(applicationBasePath, bootModule.webpackConfig);
|
||||
|
||||
let aspNetWebpackModule: any;
|
||||
try {
|
||||
aspNetWebpackModule = require('aspnet-webpack');
|
||||
} catch (ex) {
|
||||
callback('To load your boot module via webpack (i.e., if you specify a \'webpackConfig\' option), you must install the \'aspnet-webpack\' NPM package.', null);
|
||||
return;
|
||||
}
|
||||
|
||||
aspNetWebpackModule.loadViaWebpack(webpackConfigFullPath, bootModuleNameFullPath, callback);
|
||||
} else {
|
||||
callback(null, require(bootModuleNameFullPath));
|
||||
}
|
||||
}
|
||||
|
||||
function findBootFunc(applicationBasePath: string, bootModule: BootModuleInfo, callback: (error: any, bootFunc: BootFunc) => void) {
|
||||
// First try to load the module (possibly via Webpack)
|
||||
findBootModule<any>(applicationBasePath, bootModule, (findBootModuleError, foundBootModule) => {
|
||||
if (findBootModuleError) {
|
||||
callback(findBootModuleError, null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Now try to pick out the function they want us to invoke
|
||||
let bootFunc: BootFunc;
|
||||
if (bootModule.exportName) {
|
||||
// Explicitly-named export
|
||||
bootFunc = foundBootModule[bootModule.exportName];
|
||||
} else if (typeof foundBootModule !== 'function') {
|
||||
// TypeScript-style default export
|
||||
bootFunc = foundBootModule.default;
|
||||
} else {
|
||||
// Native default export
|
||||
bootFunc = foundBootModule;
|
||||
}
|
||||
|
||||
// Validate the result
|
||||
if (typeof bootFunc !== 'function') {
|
||||
if (bootModule.exportName) {
|
||||
callback(`The module at ${ bootModule.moduleName } has no function export named ${ bootModule.exportName }.`, null);
|
||||
} else {
|
||||
callback(`The module at ${ bootModule.moduleName } does not export a default function, and you have not specified which export to invoke.`, null);
|
||||
}
|
||||
} else {
|
||||
callback(null, bootFunc);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function bindPromiseContinuationsToDomain(promise: Promise<any>, domainInstance: domain.Domain) {
|
||||
const originalThen = promise.then;
|
||||
promise.then = function then(resolve, reject) {
|
||||
promise.then = (function then(resolve, reject) {
|
||||
if (typeof resolve === 'function') {
|
||||
resolve = domainInstance.bind(resolve);
|
||||
}
|
||||
@@ -184,5 +105,5 @@ function bindPromiseContinuationsToDomain(promise: Promise<any>, domainInstance:
|
||||
}
|
||||
|
||||
return originalThen.call(this, resolve, reject);
|
||||
};
|
||||
}) as any;
|
||||
}
|
||||
|
||||
35
src/Microsoft.AspNetCore.SpaServices/npm/aspnet-prerendering/src/PrerenderingInterfaces.d.ts
vendored
Normal file
35
src/Microsoft.AspNetCore.SpaServices/npm/aspnet-prerendering/src/PrerenderingInterfaces.d.ts
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
interface RenderToStringFunc {
|
||||
(callback: RenderToStringCallback, applicationBasePath: string, bootModule: BootModuleInfo, absoluteRequestUrl: string, requestPathAndQuery: string, customDataParameter: any, overrideTimeoutMilliseconds: number): void;
|
||||
}
|
||||
|
||||
interface RenderToStringCallback {
|
||||
(error: any, result?: RenderToStringResult): void;
|
||||
}
|
||||
|
||||
interface RenderToStringResult {
|
||||
html: string;
|
||||
globals?: { [key: string]: any };
|
||||
}
|
||||
|
||||
interface RedirectResult {
|
||||
redirectUrl: string;
|
||||
}
|
||||
|
||||
interface BootFunc {
|
||||
(params: BootFuncParams): Promise<RenderToStringResult>;
|
||||
}
|
||||
|
||||
interface BootFuncParams {
|
||||
location: any; // e.g., Location object containing information '/some/path'
|
||||
origin: string; // e.g., 'https://example.com:1234'
|
||||
url: string; // e.g., '/some/path'
|
||||
absoluteUrl: string; // e.g., 'https://example.com:1234/some/path'
|
||||
domainTasks: Promise<any>;
|
||||
data: any; // any custom object passed through from .NET
|
||||
}
|
||||
|
||||
interface BootModuleInfo {
|
||||
moduleName: string;
|
||||
exportName?: string;
|
||||
webpackConfig?: string;
|
||||
}
|
||||
@@ -1 +1,5 @@
|
||||
/// <reference path="./PrerenderingInterfaces.d.ts" />
|
||||
|
||||
export * from './Prerendering';
|
||||
|
||||
export type RenderResult = RenderToStringResult | RedirectResult;
|
||||
|
||||
@@ -4,8 +4,12 @@
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"declaration": true,
|
||||
"outDir": "."
|
||||
"outDir": ".",
|
||||
"lib": ["es2015", "dom"]
|
||||
},
|
||||
"files": [
|
||||
"src/index.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"version": "v4",
|
||||
"repo": "borisyankov/DefinitelyTyped",
|
||||
"ref": "master",
|
||||
"path": "typings",
|
||||
"bundle": "typings/tsd.d.ts",
|
||||
"installed": {
|
||||
"node/node.d.ts": {
|
||||
"commit": "0144ad5a74053f2292424847259c4c8e1d0fecaa"
|
||||
},
|
||||
"es6-promise/es6-promise.d.ts": {
|
||||
"commit": "0144ad5a74053f2292424847259c4c8e1d0fecaa"
|
||||
},
|
||||
"whatwg-fetch/whatwg-fetch.d.ts": {
|
||||
"commit": "dade4414712ce84e3c63393f1aae407e9e7e6af7"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
/typings/
|
||||
/node_modules/
|
||||
/*.js
|
||||
/*.d.ts
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
{
|
||||
"name": "aspnet-webpack-react",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"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": {
|
||||
"prepublish": "rimraf *.d.ts && tsd update && tsc && echo 'Finished building NPM package \"aspnet-webpack-react\"'",
|
||||
"prepublish": "rimraf *.d.ts && tsc && echo 'Finished building NPM package \"aspnet-webpack-react\"'",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Microsoft",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/aspnet/JavaScriptServices/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aspnet/JavaScriptServices.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-core": "^6.7.2",
|
||||
"babel-loader": "^6.2.4",
|
||||
@@ -16,11 +23,15 @@
|
||||
"babel-preset-es2015": "^6.6.0",
|
||||
"babel-preset-react": "^6.5.0",
|
||||
"react": "^15.0.0",
|
||||
"react-transform-hmr": "^1.0.4",
|
||||
"webpack": "^1.12.14"
|
||||
"react-transform-hmr": "^1.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/webpack": "^1.12.34",
|
||||
"rimraf": "^2.5.4",
|
||||
"typescript": "^1.8.10"
|
||||
"typescript": "^2.0.0",
|
||||
"webpack": "^1.12.14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"webpack": "^1.12.14"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import * as webpack from 'webpack';
|
||||
|
||||
export function addReactHotModuleReplacementBabelTransform(webpackConfig: webpack.Configuration) {
|
||||
webpackConfig.module.loaders.forEach(loaderConfig => {
|
||||
const moduleRules: webpack.Loader[] =
|
||||
(webpackConfig.module as any).rules // Webpack < 2.1.0 beta 23
|
||||
|| webpackConfig.module.loaders; // Webpack >= 2.1.0 beta 23
|
||||
|
||||
moduleRules.forEach(loaderConfig => {
|
||||
if (loaderConfig.loader && loaderConfig.loader.match(/\bbabel-loader\b/)) {
|
||||
// Ensure the babel-loader options includes a 'query'
|
||||
const query = loaderConfig.query = loaderConfig.query || {};
|
||||
|
||||
@@ -4,8 +4,12 @@
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"declaration": true,
|
||||
"outDir": "."
|
||||
"outDir": ".",
|
||||
"lib": ["es2015"]
|
||||
},
|
||||
"files": [
|
||||
"src/index.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"version": "v4",
|
||||
"repo": "borisyankov/DefinitelyTyped",
|
||||
"ref": "master",
|
||||
"path": "typings",
|
||||
"bundle": "typings/tsd.d.ts",
|
||||
"installed": {
|
||||
"source-map/source-map.d.ts": {
|
||||
"commit": "0144ad5a74053f2292424847259c4c8e1d0fecaa"
|
||||
},
|
||||
"webpack/webpack.d.ts": {
|
||||
"commit": "0144ad5a74053f2292424847259c4c8e1d0fecaa"
|
||||
},
|
||||
"uglify-js/uglify-js.d.ts": {
|
||||
"commit": "0144ad5a74053f2292424847259c4c8e1d0fecaa"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
/typings/
|
||||
/node_modules/
|
||||
/*.js
|
||||
/*.d.ts
|
||||
|
||||
@@ -1,25 +1,38 @@
|
||||
{
|
||||
"name": "aspnet-webpack",
|
||||
"version": "1.0.9",
|
||||
"version": "1.0.24",
|
||||
"description": "Helpers for using Webpack in ASP.NET Core projects. Works in conjunction with the Microsoft.AspNetCore.SpaServices NuGet package.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"prepublish": "rimraf *.d.ts && tsd update && tsc && echo 'Finished building NPM package \"aspnet-webpack\"'",
|
||||
"prepublish": "rimraf *.d.ts && tsc && echo 'Finished building NPM package \"aspnet-webpack\"'",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Microsoft",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/aspnet/JavaScriptServices/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aspnet/JavaScriptServices.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"es6-promise": "^3.1.2",
|
||||
"connect": "^3.4.1",
|
||||
"es6-promise": "^3.1.2",
|
||||
"memory-fs": "^0.3.0",
|
||||
"require-from-string": "^1.1.0",
|
||||
"webpack": "^1.12.14",
|
||||
"webpack-dev-middleware": "^1.5.1",
|
||||
"webpack-externals-plugin": "^1.0.0"
|
||||
"webpack-dev-middleware": "^1.8.4",
|
||||
"webpack-node-externals": "^1.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/connect": "^3.4.30",
|
||||
"@types/node": "^6.0.42",
|
||||
"@types/webpack": "^1.12.34",
|
||||
"rimraf": "^2.5.4",
|
||||
"typescript": "^1.8.10"
|
||||
"typescript": "^2.0.0",
|
||||
"webpack": "^1.13.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"webpack": "^1.13.2 || ^2.1.0-beta"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,9 @@ import * as webpack from 'webpack';
|
||||
import { requireNewCopy } from './RequireNewCopy';
|
||||
|
||||
// Strange import syntax to work around https://github.com/Microsoft/TypeScript/issues/2719
|
||||
import { webpackexternals } from './typings/webpack-externals-plugin';
|
||||
import { requirefromstring } from './typings/require-from-string';
|
||||
import { memoryfs } from './typings/memory-fs';
|
||||
const ExternalsPlugin = require('webpack-externals-plugin') as typeof webpackexternals.ExternalsPlugin;
|
||||
const nodeExternals = require('webpack-node-externals');
|
||||
const requireFromString = require('require-from-string') as typeof requirefromstring.requireFromString;
|
||||
const MemoryFS = require('memory-fs') as typeof memoryfs.MemoryFS;
|
||||
|
||||
@@ -57,11 +56,38 @@ function loadViaWebpackNoCache<T>(webpackConfigPath: string, modulePath: string)
|
||||
webpackConfig.output.libraryTarget = 'commonjs';
|
||||
const outputVirtualPath = path.join(webpackConfig.output.path, webpackConfig.output.filename);
|
||||
|
||||
// In Node, we want anything under /node_modules/ to be loaded natively and not bundled into the output
|
||||
// (partly because it's faster, but also because otherwise there'd be different instances of modules
|
||||
// depending on how they were loaded, which could lead to errors)
|
||||
webpackConfig.plugins = webpackConfig.plugins || [];
|
||||
webpackConfig.plugins.push(new ExternalsPlugin({ type: 'commonjs', include: /node_modules/ }));
|
||||
// In Node, we want any JavaScript modules under /node_modules/ to be loaded natively and not bundled into the
|
||||
// output (partly because it's faster, but also because otherwise there'd be different instances of modules
|
||||
// depending on how they were loaded, which could lead to errors).
|
||||
// ---
|
||||
// NOTE: We have to use webpack-node-externals rather than webpack-externals-plugin because
|
||||
// webpack-externals-plugin doesn't correctly resolve relative paths, which means you can't
|
||||
// use css-loader, since tries to require('./../../node_modules/css-loader/lib/css-base.js') (see #132)
|
||||
// ---
|
||||
// So, ensure that webpackConfig.externals is an array, and push WebpackNodeExternals into it:
|
||||
let externalsArray: any[] = (webpackConfig.externals as any[]) || [];
|
||||
if (!(externalsArray instanceof Array)) {
|
||||
externalsArray = [externalsArray];
|
||||
}
|
||||
webpackConfig.externals = externalsArray;
|
||||
externalsArray.push(nodeExternals({
|
||||
// However, we do *not* want to treat non-JS files under /node_modules/ as externals (i.e., things
|
||||
// that should be loaded via regular CommonJS 'require' statements). For example, if you reference
|
||||
// a .css file inside an NPM module (e.g., require('somepackage/somefile.css')), then we do need to
|
||||
// load that via Webpack rather than as a regular CommonJS module.
|
||||
//
|
||||
// So, configure webpack-externals-plugin to 'whitelist' (i.e., not treat as external) any file
|
||||
// that has an extension other than .js. Also, since some libraries such as font-awesome refer to
|
||||
// their own files with cache-busting querystrings (e.g., (url('./something.css?v=4.1.2'))), we
|
||||
// need to treat '?' as an alternative 'end of filename' marker.
|
||||
//
|
||||
// The complex, awkward regex can be eliminated once webpack-externals-plugin merges
|
||||
// https://github.com/liady/webpack-node-externals/pull/12
|
||||
//
|
||||
// This regex looks for at least one dot character that is *not* followed by "js<end-or-questionmark>", but
|
||||
// is followed by some series of non-dot characters followed by <end-or-questionmark>:
|
||||
whitelist: [/\.(?!js(\?|$))([^.]+(\?|$))/]
|
||||
}));
|
||||
|
||||
// The CommonsChunkPlugin is not compatible with a CommonJS environment like Node, nor is it needed in that case
|
||||
webpackConfig.plugins = webpackConfig.plugins.filter(plugin => {
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
import * as connect from 'connect';
|
||||
import * as webpack from 'webpack';
|
||||
import * as url from 'url';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { requireNewCopy } from './RequireNewCopy';
|
||||
|
||||
export type CreateDevServerResult = {
|
||||
Port: number,
|
||||
PublicPaths: string[],
|
||||
PublicPath: string // For backward compatibility with older verions of Microsoft.AspNetCore.SpaServices. Will be removed soon.
|
||||
};
|
||||
|
||||
export interface CreateDevServerCallback {
|
||||
(error: any, result: { Port: number, PublicPath: string }): void;
|
||||
(error: any, result: CreateDevServerResult): void;
|
||||
}
|
||||
|
||||
// These are the options passed by WebpackDevMiddleware.cs
|
||||
@@ -20,13 +28,143 @@ interface DevServerOptions {
|
||||
ReactHotModuleReplacement: boolean;
|
||||
}
|
||||
|
||||
function attachWebpackDevMiddleware(app: any, webpackConfig: webpack.Configuration, enableHotModuleReplacement: boolean, enableReactHotModuleReplacement: boolean, hmrEndpoint: string) {
|
||||
// Build the final Webpack config based on supplied options
|
||||
if (enableHotModuleReplacement) {
|
||||
// For this, we only support the key/value config format, not string or string[], since
|
||||
// those ones don't clearly indicate what the resulting bundle name will be
|
||||
const entryPoints = webpackConfig.entry;
|
||||
const isObjectStyleConfig = entryPoints
|
||||
&& typeof entryPoints === 'object'
|
||||
&& !(entryPoints instanceof Array);
|
||||
if (!isObjectStyleConfig) {
|
||||
throw new Error('To use HotModuleReplacement, your webpack config must specify an \'entry\' value as a key-value object (e.g., "entry: { main: \'ClientApp/boot-client.ts\' }")');
|
||||
}
|
||||
|
||||
// Augment all entry points so they support HMR (unless they already do)
|
||||
Object.getOwnPropertyNames(entryPoints).forEach(entryPointName => {
|
||||
const webpackHotMiddlewareEntryPoint = 'webpack-hot-middleware/client';
|
||||
const webpackHotMiddlewareOptions = `?path=` + encodeURIComponent(hmrEndpoint);
|
||||
if (typeof entryPoints[entryPointName] === 'string') {
|
||||
entryPoints[entryPointName] = [webpackHotMiddlewareEntryPoint + webpackHotMiddlewareOptions, entryPoints[entryPointName]];
|
||||
} else if (firstIndexOfStringStartingWith(entryPoints[entryPointName], webpackHotMiddlewareEntryPoint) < 0) {
|
||||
entryPoints[entryPointName].unshift(webpackHotMiddlewareEntryPoint + webpackHotMiddlewareOptions);
|
||||
}
|
||||
|
||||
// Now also inject eventsource polyfill so this can work on IE/Edge (unless it's already there)
|
||||
// To avoid this being a breaking change for everyone who uses aspnet-webpack, we only do this if you've
|
||||
// referenced event-source-polyfill in your package.json. Note that having event-source-polyfill available
|
||||
// on the server in node_modules doesn't imply that you've also included it in your client-side bundle,
|
||||
// but the converse is true (if it's not in node_modules, then you obviously aren't trying to use it at
|
||||
// all, so it would definitely not work to take a dependency on it).
|
||||
const eventSourcePolyfillEntryPoint = 'event-source-polyfill';
|
||||
if (npmModuleIsPresent(eventSourcePolyfillEntryPoint)) {
|
||||
const entryPointsArray: string[] = entryPoints[entryPointName]; // We know by now that it's an array, because if it wasn't, we already wrapped it in one
|
||||
if (entryPointsArray.indexOf(eventSourcePolyfillEntryPoint) < 0) {
|
||||
const webpackHmrIndex = firstIndexOfStringStartingWith(entryPointsArray, webpackHotMiddlewareEntryPoint);
|
||||
if (webpackHmrIndex < 0) {
|
||||
// This should not be possible, since we just added it if it was missing
|
||||
throw new Error('Cannot find ' + webpackHotMiddlewareEntryPoint + ' in entry points array: ' + entryPointsArray);
|
||||
}
|
||||
|
||||
// Insert the polyfill just before the HMR entrypoint
|
||||
entryPointsArray.splice(webpackHmrIndex, 0, eventSourcePolyfillEntryPoint);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
webpackConfig.plugins = [].concat(webpackConfig.plugins || []); // Be sure not to mutate the original array, as it might be shared
|
||||
webpackConfig.plugins.push(
|
||||
new webpack.HotModuleReplacementPlugin()
|
||||
);
|
||||
|
||||
// Set up React HMR support if requested. This requires the 'aspnet-webpack-react' package.
|
||||
if (enableReactHotModuleReplacement) {
|
||||
let aspNetWebpackReactModule: any;
|
||||
try {
|
||||
aspNetWebpackReactModule = require('aspnet-webpack-react');
|
||||
} catch(ex) {
|
||||
throw new Error('ReactHotModuleReplacement failed because of an error while loading \'aspnet-webpack-react\'. Error was: ' + ex.stack);
|
||||
}
|
||||
|
||||
aspNetWebpackReactModule.addReactHotModuleReplacementBabelTransform(webpackConfig);
|
||||
}
|
||||
}
|
||||
|
||||
// Attach Webpack dev middleware and optional 'hot' middleware
|
||||
const compiler = webpack(webpackConfig);
|
||||
app.use(require('webpack-dev-middleware')(compiler, {
|
||||
noInfo: true,
|
||||
publicPath: webpackConfig.output.publicPath
|
||||
}));
|
||||
|
||||
// After each compilation completes, copy the in-memory filesystem to disk.
|
||||
// This is needed because the debuggers in both VS and VS Code assume that they'll be able to find
|
||||
// the compiled files on the local disk (though it would be better if they got the source file from
|
||||
// the browser they are debugging, which would be more correct and make this workaround unnecessary).
|
||||
// Without this, Webpack plugins like HMR that dynamically modify the compiled output in the dev
|
||||
// middleware's in-memory filesystem only (and not on disk) would confuse the debugger, because the
|
||||
// file on disk wouldn't match the file served to the browser, and the source map line numbers wouldn't
|
||||
// match up. Breakpoints would either not be hit, or would hit the wrong lines.
|
||||
(compiler as any).plugin('done', stats => {
|
||||
copyRecursiveToRealFsSync(compiler.outputFileSystem, '/', [/\.hot-update\.(js|json)$/]);
|
||||
});
|
||||
|
||||
if (enableHotModuleReplacement) {
|
||||
let webpackHotMiddlewareModule;
|
||||
try {
|
||||
webpackHotMiddlewareModule = require('webpack-hot-middleware');
|
||||
} catch (ex) {
|
||||
throw new Error('HotModuleReplacement failed because of an error while loading \'webpack-hot-middleware\'. Error was: ' + ex.stack);
|
||||
}
|
||||
app.use(webpackHotMiddlewareModule(compiler));
|
||||
}
|
||||
}
|
||||
|
||||
function copyRecursiveToRealFsSync(from: typeof fs, rootDir: string, exclude: RegExp[]) {
|
||||
from.readdirSync(rootDir).forEach(filename => {
|
||||
const fullPath = pathJoinSafe(rootDir, filename);
|
||||
const shouldExclude = exclude.filter(re => re.test(fullPath)).length > 0;
|
||||
if (!shouldExclude) {
|
||||
const fileStat = from.statSync(fullPath);
|
||||
if (fileStat.isFile()) {
|
||||
const fileBuf = from.readFileSync(fullPath);
|
||||
fs.writeFileSync(fullPath, fileBuf);
|
||||
} else if (fileStat.isDirectory()) {
|
||||
if (!fs.existsSync(fullPath)) {
|
||||
fs.mkdirSync(fullPath);
|
||||
}
|
||||
copyRecursiveToRealFsSync(from, fullPath, exclude);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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
|
||||
// names at the root, and adding a backslash (so 'C:' becomes 'C:\', which works).
|
||||
if (rootPath === '/' && path.sep === '\\' && filePath.match(/^[a-z0-9]+\:$/i)) {
|
||||
return filePath + '\\';
|
||||
} else {
|
||||
return path.join(rootPath, filePath);
|
||||
}
|
||||
}
|
||||
|
||||
function beginWebpackWatcher(webpackConfig: webpack.Configuration) {
|
||||
const compiler = webpack(webpackConfig);
|
||||
compiler.watch({ /* watchOptions */ }, (err, stats) => {
|
||||
// The default error reporter is fine for now, but could be customized here in the future if desired
|
||||
});
|
||||
}
|
||||
|
||||
export function createWebpackDevServer(callback: CreateDevServerCallback, optionsJson: string) {
|
||||
const options: CreateDevServerOptions = JSON.parse(optionsJson);
|
||||
const webpackConfig: webpack.Configuration = requireNewCopy(options.webpackConfigPath);
|
||||
const publicPath = (webpackConfig.output.publicPath || '').trim();
|
||||
if (!publicPath) {
|
||||
callback('To use the Webpack dev server, you must specify a value for \'publicPath\' on the \'output\' section of your webpack.config.', null);
|
||||
return;
|
||||
|
||||
// Read the webpack config's export, and normalize it into the more general 'array of configs' format
|
||||
let webpackConfigArray: webpack.Configuration[] = requireNewCopy(options.webpackConfigPath);
|
||||
if (!(webpackConfigArray instanceof Array)) {
|
||||
webpackConfigArray = [webpackConfigArray as webpack.Configuration];
|
||||
}
|
||||
|
||||
const enableHotModuleReplacement = options.suppliedOptions.HotModuleReplacement;
|
||||
@@ -41,55 +179,42 @@ export function createWebpackDevServer(callback: CreateDevServerCallback, option
|
||||
|
||||
const app = connect();
|
||||
const listener = app.listen(suggestedHMRPortOrZero, () => {
|
||||
// Build the final Webpack config based on supplied options
|
||||
if (enableHotModuleReplacement) {
|
||||
// TODO: Stop assuming there's an entry point called 'main'
|
||||
if (typeof webpackConfig.entry['main'] === 'string') {
|
||||
webpackConfig.entry['main'] = ['webpack-hot-middleware/client', webpackConfig.entry['main']];
|
||||
} else {
|
||||
webpackConfig.entry['main'].unshift('webpack-hot-middleware/client');
|
||||
}
|
||||
webpackConfig.plugins.push(
|
||||
new webpack.HotModuleReplacementPlugin()
|
||||
);
|
||||
try {
|
||||
// For each webpack config that specifies a public path, add webpack dev middleware for it
|
||||
const normalizedPublicPaths: string[] = [];
|
||||
webpackConfigArray.forEach(webpackConfig => {
|
||||
if (webpackConfig.target === 'node') {
|
||||
// For configs that target Node, it's meaningless to set up an HTTP listener, since
|
||||
// Node isn't going to load those modules over HTTP anyway. It just loads them directly
|
||||
// from disk. So the most relevant thing we can do with such configs is just write
|
||||
// updated builds to disk, just like "webpack --watch".
|
||||
beginWebpackWatcher(webpackConfig);
|
||||
} else {
|
||||
// For configs that target browsers, we can set up an HTTP listener, and dynamically
|
||||
// modify the config to enable HMR etc. This just requires that we have a publicPath.
|
||||
const publicPath = (webpackConfig.output.publicPath || '').trim();
|
||||
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));
|
||||
|
||||
// Set up React HMR support if requested. This requires the 'aspnet-webpack-react' package.
|
||||
if (enableReactHotModuleReplacement) {
|
||||
let aspNetWebpackReactModule: any;
|
||||
try {
|
||||
aspNetWebpackReactModule = require('aspnet-webpack-react');
|
||||
} catch(ex) {
|
||||
callback('To use ReactHotModuleReplacement, you must install the NPM package \'aspnet-webpack-react\'.', null);
|
||||
return;
|
||||
const hmrEndpoint = `http://localhost:${listener.address().port}/__webpack_hmr`;
|
||||
attachWebpackDevMiddleware(app, webpackConfig, enableHotModuleReplacement, enableReactHotModuleReplacement, hmrEndpoint);
|
||||
}
|
||||
});
|
||||
|
||||
aspNetWebpackReactModule.addReactHotModuleReplacementBabelTransform(webpackConfig);
|
||||
}
|
||||
// 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]
|
||||
});
|
||||
} catch (ex) {
|
||||
callback(ex.stack, null);
|
||||
}
|
||||
|
||||
// Attach Webpack dev middleware and optional 'hot' middleware
|
||||
const compiler = webpack(webpackConfig);
|
||||
app.use(require('webpack-dev-middleware')(compiler, {
|
||||
noInfo: true,
|
||||
publicPath: publicPath
|
||||
}));
|
||||
|
||||
if (enableHotModuleReplacement) {
|
||||
let webpackHotMiddlewareModule;
|
||||
try {
|
||||
webpackHotMiddlewareModule = require('webpack-hot-middleware');
|
||||
} catch (ex) {
|
||||
callback('To use HotModuleReplacement, you must install the NPM package \'webpack-hot-middleware\'.', null);
|
||||
return;
|
||||
}
|
||||
app.use(webpackHotMiddlewareModule(compiler));
|
||||
}
|
||||
|
||||
// Tell the ASP.NET app what addresses we're listening on, so that it can proxy requests here
|
||||
callback(null, {
|
||||
Port: listener.address().port,
|
||||
PublicPath: removeTrailingSlash(getPath(publicPath))
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -104,3 +229,23 @@ function removeTrailingSlash(str: string) {
|
||||
function getPath(publicPath: string) {
|
||||
return url.parse(publicPath).path;
|
||||
}
|
||||
|
||||
function firstIndexOfStringStartingWith(array: string[], prefixToFind: string) {
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
const candidate = array[index];
|
||||
if ((typeof candidate === 'string') && (candidate.substring(0, prefixToFind.length) === prefixToFind)) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1; // Not found
|
||||
}
|
||||
|
||||
function npmModuleIsPresent(moduleName: string) {
|
||||
try {
|
||||
require.resolve(moduleName);
|
||||
return true;
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user