mirror of
https://github.com/aspnet/JavaScriptServices.git
synced 2025-12-24 02:30:13 +00:00
Compare commits
2 Commits
example-us
...
redux-type
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7783ca707 | ||
|
|
973668289b |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -37,5 +37,4 @@ npm-debug.log
|
||||
/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.25420.1
|
||||
VisualStudioVersion = 14.0.25123.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{E6E88944-4800-40BA-8AF5-069EA3ADFEB8}"
|
||||
EndProject
|
||||
@@ -46,10 +46,6 @@ 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
|
||||
@@ -112,14 +108,6 @@ 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
|
||||
@@ -138,7 +126,5 @@ 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
|
||||
|
||||
@@ -33,7 +33,7 @@ cd $PSScriptRoot
|
||||
$repoFolder = $PSScriptRoot
|
||||
$env:REPO_FOLDER = $repoFolder
|
||||
|
||||
$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip"
|
||||
$koreBuildZip="https://codeload.github.com/aspnet/KoreBuild/zip/stevesa/npm-in-series"
|
||||
if ($env:KOREBUILD_ZIP)
|
||||
{
|
||||
$koreBuildZip=$env:KOREBUILD_ZIP
|
||||
|
||||
2
build.sh
2
build.sh
@@ -2,7 +2,7 @@
|
||||
repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
cd $repoFolder
|
||||
|
||||
koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip"
|
||||
koreBuildZip="https://codeload.github.com/aspnet/KoreBuild/zip/stevesa/npm-in-series"
|
||||
if [ ! -z $KOREBUILD_ZIP ]; then
|
||||
koreBuildZip=$KOREBUILD_ZIP
|
||||
fi
|
||||
|
||||
@@ -2,7 +2,6 @@ versionSuffix=$1
|
||||
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
projects=(
|
||||
./src/Microsoft.AspNetCore.NodeServices
|
||||
./src/Microsoft.AspNetCore.NodeServices.Sockets
|
||||
./src/Microsoft.AspNetCore.SpaServices
|
||||
./src/Microsoft.AspNetCore.AngularServices
|
||||
./src/Microsoft.AspNetCore.ReactServices
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
"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",
|
||||
|
||||
@@ -15,28 +15,28 @@
|
||||
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.1.0",
|
||||
"version": "1.0.1",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.AngularServices": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
|
||||
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.1.0",
|
||||
"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.1.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0",
|
||||
"Microsoft.EntityFrameworkCore.SQLite": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.1.0",
|
||||
"Microsoft.Extensions.Logging": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.1.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.EntityFrameworkCore.SQLite": "1.0.0",
|
||||
"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"
|
||||
},
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"netcoreapp1.1": {
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"portable-net45+win8"
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.NodeServices;
|
||||
using Microsoft.AspNetCore.NodeServices.Sockets;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ConsoleApplication
|
||||
@@ -17,10 +16,7 @@ namespace ConsoleApplication
|
||||
// Set up the DI system
|
||||
var services = new ServiceCollection();
|
||||
services.AddNodeServices(options => {
|
||||
// To compare with Socket hosting, uncomment the following line
|
||||
// Since .NET Core 1.1, the HTTP hosting model has become basically as fast as the Socket hosting model
|
||||
//options.UseSocketHosting();
|
||||
|
||||
options.HostingModel = NodeServicesOptions.DefaultNodeHostingModel;
|
||||
options.ProjectPath = Directory.GetCurrentDirectory();
|
||||
options.WatchFileExtensions = new string[] {}; // Don't watch anything
|
||||
});
|
||||
|
||||
@@ -5,12 +5,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.1.0",
|
||||
"version": "1.0.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.NodeServices": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.NodeServices.Sockets": "1.1.0-*",
|
||||
"Microsoft.Extensions.DependencyInjection": "1.1.0"
|
||||
"Microsoft.AspNetCore.NodeServices": "1.0.0-*",
|
||||
"Microsoft.Extensions.DependencyInjection": "1.0.0"
|
||||
},
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
|
||||
@@ -12,22 +12,29 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.1.0",
|
||||
"version": "1.0.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.1.0",
|
||||
"Microsoft.AspNetCore.NodeServices": "1.1.0-*"
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"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.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.AspNetCore.NodeServices": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {}
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
},
|
||||
"publishExclude": [
|
||||
"node_modules",
|
||||
|
||||
3
samples/misc/Webpack/.gitignore
vendored
3
samples/misc/Webpack/.gitignore
vendored
@@ -1,9 +1,6 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
yarn.lock
|
||||
wwwroot/dist
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
"webpack-hot-middleware": "^2.7.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"aspnet-prerendering": "^1.0.4",
|
||||
"aspnet-webpack": "^1.0.3",
|
||||
"aspnet-prerendering": "^1.0.4",
|
||||
"ts-loader": "^0.8.1",
|
||||
"typescript": "^2.0.0",
|
||||
"webpack": "^1.13.3"
|
||||
"typescript": "^1.7.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,22 +12,29 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.1.0",
|
||||
"version": "1.0.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.1.0",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.1.0-*"
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"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.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.AspNetCore.SpaServices": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {}
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
},
|
||||
"publishOptions": {
|
||||
"exclude": [
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"target": "es6",
|
||||
"jsx": "preserve",
|
||||
"sourceMap": true,
|
||||
"lib": ["es6", "dom"]
|
||||
"sourceMap": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
|
||||
@@ -2,7 +2,7 @@ module.exports = {
|
||||
devtool: 'inline-source-map',
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }
|
||||
{ test: /\.less$/, loader: 'style!css!less' }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,11 +5,11 @@ var extractLESS = new ExtractTextPlugin('my-styles.css');
|
||||
module.exports = {
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.less$/, loader: extractLESS.extract(['css-loader', 'less-loader']) },
|
||||
{ test: /\.less$/, loader: extractLESS.extract(['css', 'less']) },
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
extractLESS,
|
||||
new webpack.optimize.UglifyJsPlugin({ minimize: true, compressor: { warnings: false } })
|
||||
new webpack.optimize.UglifyJsPlugin({ minimize: true })
|
||||
]
|
||||
};
|
||||
|
||||
1
samples/react/MusicStore/.gitignore
vendored
1
samples/react/MusicStore/.gitignore
vendored
@@ -1,4 +1,3 @@
|
||||
music-db.sqlite
|
||||
/wwwroot/dist/
|
||||
/node_modules/
|
||||
yarn.lock
|
||||
|
||||
@@ -5,29 +5,19 @@ import { match, RouterContext } from 'react-router';
|
||||
import createMemoryHistory from 'history/lib/createMemoryHistory';
|
||||
import { routes } from './routes';
|
||||
import configureStore from './configureStore';
|
||||
type BootResult = { html?: string, globals?: { [key: string]: any }, redirectUrl?: string};
|
||||
React;
|
||||
|
||||
export default function (params: any): Promise<{ html: string }> {
|
||||
return new Promise<BootResult>((resolve, reject) => {
|
||||
return new Promise<{ html: string, globals: { [key: string]: any } }>((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 store = configureStore();
|
||||
const history = createMemoryHistory(params.url);
|
||||
const store = configureStore(history);
|
||||
const app = (
|
||||
<Provider store={ store }>
|
||||
<RouterContext {...renderProps} />
|
||||
|
||||
@@ -1,25 +1,21 @@
|
||||
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';
|
||||
import { syncHistoryWithStore } from 'react-router-redux';
|
||||
import { routes } from './routes';
|
||||
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 { routes } from './routes';
|
||||
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(initialState);
|
||||
const history = syncHistoryWithStore(browserHistory, store);
|
||||
const store = configureStore(browserHistory, initialState);
|
||||
|
||||
// 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={ history } children={ routes } />
|
||||
<Router history={ browserHistory } children={ routes } />
|
||||
</Provider>,
|
||||
document.getElementById('react-app')
|
||||
);
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
import { createStore, applyMiddleware, compose, combineReducers, GenericStoreEnhancer } from 'redux';
|
||||
import thunk from 'redux-thunk';
|
||||
import { routerReducer } from 'react-router-redux';
|
||||
import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
|
||||
import * as thunkModule from 'redux-thunk';
|
||||
import { syncHistory, routeReducer } from 'react-router-redux';
|
||||
import * as Store from './store';
|
||||
import { typedToPlain } from 'redux-typed';
|
||||
|
||||
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);
|
||||
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
|
||||
|
||||
// Combine all reducers and instantiate the app-wide store instance
|
||||
const finalCreateStore = compose(
|
||||
applyMiddleware(...middlewares),
|
||||
devToolsExtension ? devToolsExtension() : f => f
|
||||
)(createStore)
|
||||
|
||||
// Combine all reducers
|
||||
const allReducers = buildRootReducer(Store.reducers);
|
||||
const store = createStoreWithMiddleware(allReducers, initialState) as Redux.Store<Store.ApplicationState>;
|
||||
|
||||
const store = finalCreateStore(allReducers, initialState) as Redux.Store;
|
||||
|
||||
// Required for replaying actions from devtools to work
|
||||
reduxRouterMiddleware.listenForReplays(store);
|
||||
|
||||
// Enable Webpack hot module replacement for reducers
|
||||
if (module.hot) {
|
||||
@@ -30,5 +36,5 @@ export default function configureStore(initialState?: Store.ApplicationState) {
|
||||
}
|
||||
|
||||
function buildRootReducer(allReducers) {
|
||||
return combineReducers<Store.ApplicationState>(Object.assign({}, allReducers, { routing: routerReducer }));
|
||||
return combineReducers(Object.assign({}, allReducers, { routing: routeReducer })) as Redux.Reducer;
|
||||
}
|
||||
|
||||
@@ -1,51 +1,45 @@
|
||||
{
|
||||
"name": "music-store",
|
||||
"name": "MusicStore",
|
||||
"version": "0.0.0",
|
||||
"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-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",
|
||||
"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",
|
||||
"css-loader": "^0.23.1",
|
||||
"domain-task": "^2.0.1",
|
||||
"event-source-polyfill": "^0.0.7",
|
||||
"express": "^4.13.4",
|
||||
"extract-text-webpack-plugin": "^1.0.1",
|
||||
"file-loader": "^0.8.5",
|
||||
"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",
|
||||
"react-transform-hmr": "^1.0.2",
|
||||
"style-loader": "^0.13.0",
|
||||
"ts-loader": "^0.8.1",
|
||||
"typescript": "2.0.3",
|
||||
"ts-loader": "^0.8.0",
|
||||
"typescript": "^1.7.5",
|
||||
"url-loader": "^0.5.7",
|
||||
"webpack": "^1.13.2",
|
||||
"webpack-hot-middleware": "^2.12.2",
|
||||
"webpack-merge": "^0.14.1",
|
||||
"webpack-node-externals": "^1.4.3"
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,80 +1,56 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.1.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.ReactServices": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
|
||||
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.1.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.1.0",
|
||||
"Microsoft.AspNetCore.Razor.Tools": {
|
||||
"version": "1.0.0-preview2-final",
|
||||
"type": "build"
|
||||
},
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0",
|
||||
"Microsoft.EntityFrameworkCore.SQLite": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.1.0",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "1.1.0",
|
||||
"Microsoft.Extensions.Logging": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Debug": "1.1.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.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": []
|
||||
}
|
||||
},
|
||||
|
||||
"version": "1.0.0-*",
|
||||
"buildOptions": {
|
||||
"emitEntryPoint": true,
|
||||
"preserveCompilationContext": true,
|
||||
"compile": {
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
"preserveCompilationContext": true
|
||||
},
|
||||
|
||||
"runtimeOptions": {
|
||||
"configProperties": {
|
||||
"System.GC.Server": true
|
||||
}
|
||||
"gcServer": true
|
||||
},
|
||||
|
||||
"publishOptions": {
|
||||
"include": [
|
||||
"appsettings.json",
|
||||
"ClientApp/dist",
|
||||
"node_modules",
|
||||
"Views",
|
||||
"web.config",
|
||||
"wwwroot"
|
||||
],
|
||||
"exclude": [
|
||||
"wwwroot/dist/*.map"
|
||||
]
|
||||
},
|
||||
|
||||
"scripts": {
|
||||
"prepublish": [
|
||||
"npm install",
|
||||
"node node_modules/webpack/bin/webpack.js"
|
||||
],
|
||||
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
|
||||
},
|
||||
|
||||
"tooling": {
|
||||
"defaultNamespace": "MusicStore"
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.0.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0",
|
||||
"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.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"
|
||||
},
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
},
|
||||
"publishOptions": {
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"**.xproj",
|
||||
"**.user",
|
||||
"**.vspscc"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"prepublish": [ "npm install" ],
|
||||
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
"target": "es6",
|
||||
"jsx": "preserve",
|
||||
"sourceMap": true,
|
||||
"experimentalDecorators": true,
|
||||
"types": [ "webpack-env", "whatwg-fetch" ]
|
||||
"experimentalDecorators": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
|
||||
45
samples/react/MusicStore/tsd.json
Normal file
45
samples/react/MusicStore/tsd.json
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
976
samples/react/MusicStore/typings/react-bootstrap/react-bootstrap.d.ts
vendored
Normal file
976
samples/react/MusicStore/typings/react-bootstrap/react-bootstrap.d.ts
vendored
Normal file
@@ -0,0 +1,976 @@
|
||||
// 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;
|
||||
}
|
||||
69
samples/react/MusicStore/typings/react-redux/react-redux.d.ts
vendored
Normal file
69
samples/react/MusicStore/typings/react-redux/react-redux.d.ts
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// 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, {}> { }
|
||||
}
|
||||
46
samples/react/MusicStore/typings/react-router-bootstrap/react-router-bootstrap.d.ts
vendored
Normal file
46
samples/react/MusicStore/typings/react-router-bootstrap/react-router-bootstrap.d.ts
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
// 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
|
||||
}
|
||||
|
||||
}
|
||||
48
samples/react/MusicStore/typings/react-router-redux/react-router-redux.d.ts
vendored
Normal file
48
samples/react/MusicStore/typings/react-router-redux/react-router-redux.d.ts
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
// 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;
|
||||
}
|
||||
192
samples/react/MusicStore/typings/react-router/history.d.ts
vendored
Normal file
192
samples/react/MusicStore/typings/react-router/history.d.ts
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
// 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 }
|
||||
|
||||
}
|
||||
474
samples/react/MusicStore/typings/react-router/react-router.d.ts
vendored
Normal file
474
samples/react/MusicStore/typings/react-router/react-router.d.ts
vendored
Normal file
@@ -0,0 +1,474 @@
|
||||
// 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
|
||||
|
||||
}
|
||||
66
samples/react/MusicStore/typings/react/react-dom.d.ts
vendored
Normal file
66
samples/react/MusicStore/typings/react/react-dom.d.ts
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
// 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
Normal file
2274
samples/react/MusicStore/typings/react/react.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
18
samples/react/MusicStore/typings/redux-thunk/redux-thunk.d.ts
vendored
Normal file
18
samples/react/MusicStore/typings/redux-thunk/redux-thunk.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// 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;
|
||||
}
|
||||
52
samples/react/MusicStore/typings/redux/redux.d.ts
vendored
Normal file
52
samples/react/MusicStore/typings/redux/redux.d.ts
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
// 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
Normal file
12
samples/react/MusicStore/typings/tsd.d.ts
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
/// <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" />
|
||||
232
samples/react/MusicStore/typings/webpack/webpack-env.d.ts
vendored
Normal file
232
samples/react/MusicStore/typings/webpack/webpack-env.d.ts
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
// 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;
|
||||
85
samples/react/MusicStore/typings/whatwg-fetch/whatwg-fetch.d.ts
vendored
Normal file
85
samples/react/MusicStore/typings/whatwg-fetch/whatwg-fetch.d.ts
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
// 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;
|
||||
@@ -10,7 +10,7 @@ module.exports = {
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.ts(x?)$/, include: /ReactApp/, exclude: /node_modules/, loader: 'babel-loader' },
|
||||
{ test: /\.ts(x?)$/, include: /ReactApp/, exclude: /node_modules/, loader: 'ts-loader?silent' },
|
||||
{ test: /\.ts(x?)$/, include: /ReactApp/, exclude: /node_modules/, loader: 'ts-loader' },
|
||||
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') },
|
||||
{ test: /\.(png|woff|woff2|eot|ttf|svg)$/, loader: 'url-loader?limit=100000' }
|
||||
]
|
||||
|
||||
@@ -9,17 +9,29 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"version": "1.1.0",
|
||||
"version": "1.0.0",
|
||||
"type": "platform"
|
||||
},
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.1.0",
|
||||
"Microsoft.AspNetCore.ReactServices": "1.1.0-*",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.1.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.1.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.1.0"
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"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.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.AspNetCore.ReactServices": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {}
|
||||
"netcoreapp1.0": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
},
|
||||
"publishOptions": {
|
||||
"exclude": [
|
||||
|
||||
@@ -9,31 +9,14 @@ 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
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
// 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")]
|
||||
@@ -18,12 +18,12 @@
|
||||
"url": "https://github.com/aspnet/JavaScriptServices.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"angular2": "2.0.0-beta.13",
|
||||
"reflect-metadata": "0.1.2",
|
||||
"angular2": "^2.0.0-beta.13",
|
||||
"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": "^2.0.0",
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
{
|
||||
"version": "1.0.0-*",
|
||||
"description": "Helpers for building Angular 2 applications on ASP.NET Core.",
|
||||
"version": "1.1.0-*",
|
||||
"packOptions": {
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/aspnet/javascriptservices"
|
||||
},
|
||||
"tags": [
|
||||
"aspnetcore",
|
||||
"aspnetcoremvc",
|
||||
"nodeservices"
|
||||
]
|
||||
"compilationOptions": {
|
||||
"keyFile": "../../tools/Key.snk"
|
||||
},
|
||||
"buildOptions": {
|
||||
"warningsAsErrors": true,
|
||||
"keyFile": "../../tools/Key.snk",
|
||||
"xmlDoc": true
|
||||
"authors": [ "Microsoft" ],
|
||||
"tooling": {
|
||||
"defaultNamespace": "Microsoft.AspNetCore.AngularServices"
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.1.0",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.1.0-*"
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.1",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {},
|
||||
"netstandard1.6": {}
|
||||
"net451": {
|
||||
},
|
||||
"netstandard1.6": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
/bin/
|
||||
/node_modules/
|
||||
yarn.lock
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.Sockets
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods that help with populating a <see cref="NodeServicesOptions"/> object.
|
||||
/// </summary>
|
||||
public static class NodeServicesOptionsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Configures the <see cref="INodeServices"/> service so that it will use out-of-process
|
||||
/// Node.js instances and perform RPC calls over binary sockets (on Windows, this is
|
||||
/// implemented as named pipes; on other platforms it uses domain sockets).
|
||||
/// </summary>
|
||||
public static void UseSocketHosting(this NodeServicesOptions options)
|
||||
{
|
||||
var pipeName = "pni-" + Guid.NewGuid().ToString("D"); // Arbitrary non-clashing string
|
||||
options.NodeInstanceFactory = () => new SocketNodeInstance(options, pipeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es3",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"types": ["node"]
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"name": "nodeservices.sockets",
|
||||
"version": "1.0.0",
|
||||
"description": "This is not really an NPM package and will not be published. This file exists only to reference compilation tools.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "./node_modules/.bin/webpack"
|
||||
},
|
||||
"author": "Microsoft",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@types/node": "^6.0.42",
|
||||
"ts-loader": "^0.8.2",
|
||||
"typescript": "^2.0.0",
|
||||
"webpack": "^1.13.1"
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
{
|
||||
"description": "Socket-based RPC for Microsoft.AspNetCore.NodeServices",
|
||||
"version": "1.1.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
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.NodeServices": "1.1.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {
|
||||
"dependencies": {
|
||||
"Microsoft.Tpl.Dataflow": "4.5.24"
|
||||
}
|
||||
},
|
||||
"netstandard1.6": {
|
||||
"dependencies": {
|
||||
"System.IO.Pipes": "4.3.0",
|
||||
"System.Threading.Tasks.Dataflow": "4.7.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
module.exports = {
|
||||
target: 'node',
|
||||
externals: ['fs', 'net', 'events', 'readline', 'stream'],
|
||||
resolve: {
|
||||
extensions: [ '.ts' ]
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.ts$/, loader: 'ts-loader' },
|
||||
]
|
||||
},
|
||||
entry: {
|
||||
'entrypoint-socket': ['./TypeScript/SocketNodeInstanceEntryPoint'],
|
||||
},
|
||||
output: {
|
||||
libraryTarget: 'commonjs',
|
||||
path: './Content/Node',
|
||||
filename: '[name].js'
|
||||
}
|
||||
};
|
||||
@@ -1,3 +1,2 @@
|
||||
/bin/
|
||||
/node_modules/
|
||||
yarn.lock
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Microsoft.AspNetCore.NodeServices
|
||||
{
|
||||
public enum NodeHostingModel
|
||||
{
|
||||
Http,
|
||||
Socket,
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,43 @@
|
||||
using System;
|
||||
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)
|
||||
{
|
||||
throw new ArgumentNullException(nameof (options));
|
||||
}
|
||||
|
||||
return new NodeServicesImpl(() => CreateNodeInstance(options));
|
||||
}
|
||||
|
||||
return new NodeServicesImpl(options.NodeInstanceFactory);
|
||||
private static INodeInstance CreateNodeInstance(NodeServicesOptions options)
|
||||
{
|
||||
if (options.NodeInstanceFactory != null)
|
||||
{
|
||||
// If you've explicitly supplied an INodeInstance factory, we'll use that. This is useful for
|
||||
// custom INodeInstance implementations.
|
||||
return options.NodeInstanceFactory();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (options.HostingModel)
|
||||
{
|
||||
case NodeHostingModel.Http:
|
||||
return new HttpNodeInstance(options.ProjectPath, options.WatchFileExtensions, options.NodeInstanceOutputLogger,
|
||||
options.EnvironmentVariables, options.InvocationTimeoutMilliseconds, options.LaunchWithDebugging, options.DebuggingPort, /* port */ 0);
|
||||
case NodeHostingModel.Socket:
|
||||
var pipeName = "pni-" + Guid.NewGuid().ToString("D"); // Arbitrary non-clashing string
|
||||
return new SocketNodeInstance(options.ProjectPath, options.WatchFileExtensions, pipeName, options.NodeInstanceOutputLogger,
|
||||
options.EnvironmentVariables, options.InvocationTimeoutMilliseconds, options.LaunchWithDebugging, options.DebuggingPort);
|
||||
default:
|
||||
throw new ArgumentException("Unknown hosting model: " + options.HostingModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,20 +8,14 @@ using Microsoft.Extensions.Logging.Console;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes options used to configure an <see cref="INodeServices"/> instance.
|
||||
/// </summary>
|
||||
public class NodeServicesOptions
|
||||
{
|
||||
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)
|
||||
@@ -31,6 +25,7 @@ namespace Microsoft.AspNetCore.NodeServices
|
||||
|
||||
EnvironmentVariables = new Dictionary<string, string>();
|
||||
InvocationTimeoutMilliseconds = DefaultInvocationTimeoutMilliseconds;
|
||||
HostingModel = DefaultNodeHostingModel;
|
||||
WatchFileExtensions = (string[])DefaultWatchFileExtensions.Clone();
|
||||
|
||||
// In an ASP.NET environment, we can use the IHostingEnvironment data to auto-populate a few
|
||||
@@ -47,51 +42,16 @@ namespace Microsoft.AspNetCore.NodeServices
|
||||
NodeInstanceOutputLogger = loggerFactory != null
|
||||
? loggerFactory.CreateLogger(LogCategoryName)
|
||||
: new ConsoleLogger(LogCategoryName, null, false);
|
||||
|
||||
// By default, we use this package's built-in out-of-process-via-HTTP hosting/transport
|
||||
this.UseHttpHosting();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies how to construct Node.js instances. An <see cref="INodeInstance"/> encapsulates all details about
|
||||
/// how Node.js instances are launched and communicated with. A new <see cref="INodeInstance"/> will be created
|
||||
/// automatically if the previous instance has terminated (e.g., because a source file changed).
|
||||
/// </summary>
|
||||
public NodeHostingModel HostingModel { get; set; }
|
||||
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; }
|
||||
|
||||
/// <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 DebuggingPort { get; set; }
|
||||
public int InvocationTimeoutMilliseconds { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -8,18 +8,9 @@ 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)
|
||||
{
|
||||
@@ -29,11 +20,6 @@ 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)
|
||||
|
||||
@@ -44,81 +44,11 @@
|
||||
/* 0 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
module.exports = __webpack_require__(1);
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 1 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
// Limit dependencies to core Node modules. This means the code in this file has to be very low-level and unattractive,
|
||||
// but simplifies things for the consumer of this module.
|
||||
__webpack_require__(2);
|
||||
var net = __webpack_require__(3);
|
||||
var path = __webpack_require__(4);
|
||||
var readline = __webpack_require__(5);
|
||||
var ArgsUtil_1 = __webpack_require__(6);
|
||||
var ExitWhenParentExits_1 = __webpack_require__(7);
|
||||
var virtualConnectionServer = __webpack_require__(8);
|
||||
// Webpack doesn't support dynamic requires for files not present at compile time, so grab a direct
|
||||
// reference to Node's runtime 'require' function.
|
||||
var dynamicRequire = eval('require');
|
||||
// Signal to the .NET side when we're ready to accept invocations
|
||||
var server = net.createServer().on('listening', function () {
|
||||
console.log('[Microsoft.AspNetCore.NodeServices:Listening]');
|
||||
});
|
||||
// Each virtual connection represents a separate invocation
|
||||
virtualConnectionServer.createInterface(server).on('connection', function (connection) {
|
||||
readline.createInterface(connection, null).on('line', function (line) {
|
||||
try {
|
||||
// Get a reference to the function to invoke
|
||||
var invocation = JSON.parse(line);
|
||||
var invokedModule = dynamicRequire(path.resolve(process.cwd(), invocation.moduleName));
|
||||
var invokedFunction = invocation.exportedFunctionName ? invokedModule[invocation.exportedFunctionName] : invokedModule;
|
||||
// Prepare a callback for accepting non-streamed JSON responses
|
||||
var hasInvokedCallback_1 = false;
|
||||
var invocationCallback = function (errorValue, successValue) {
|
||||
if (hasInvokedCallback_1) {
|
||||
throw new Error('Cannot supply more than one result. The callback has already been invoked,'
|
||||
+ ' or the result stream has already been accessed');
|
||||
}
|
||||
hasInvokedCallback_1 = true;
|
||||
connection.end(JSON.stringify({
|
||||
result: successValue,
|
||||
errorMessage: errorValue && (errorValue.message || errorValue),
|
||||
errorDetails: errorValue && (errorValue.stack || null)
|
||||
}));
|
||||
};
|
||||
// Also support streamed binary responses
|
||||
Object.defineProperty(invocationCallback, 'stream', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
hasInvokedCallback_1 = true;
|
||||
return connection;
|
||||
}
|
||||
});
|
||||
// Actually invoke it, passing through any supplied args
|
||||
invokedFunction.apply(null, [invocationCallback].concat(invocation.args));
|
||||
}
|
||||
catch (ex) {
|
||||
connection.end(JSON.stringify({
|
||||
errorMessage: ex.message,
|
||||
errorDetails: ex.stack
|
||||
}));
|
||||
}
|
||||
});
|
||||
});
|
||||
// Begin listening now. The underlying transport varies according to the runtime platform.
|
||||
// On Windows it's Named Pipes; on Linux/OSX it's Domain Sockets.
|
||||
var useWindowsNamedPipes = /^win/.test(process.platform);
|
||||
var parsedArgs = ArgsUtil_1.parseArgs(process.argv);
|
||||
var listenAddress = (useWindowsNamedPipes ? '\\\\.\\pipe\\' : '/tmp/') + parsedArgs.listenAddress;
|
||||
server.listen(listenAddress);
|
||||
ExitWhenParentExits_1.exitWhenParentExits(parseInt(parsedArgs.parentPid));
|
||||
module.exports = __webpack_require__(7);
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 1 */,
|
||||
/* 2 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
@@ -160,12 +90,7 @@
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 3 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
module.exports = require("net");
|
||||
|
||||
/***/ },
|
||||
/* 3 */,
|
||||
/* 4 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
@@ -173,12 +98,6 @@
|
||||
|
||||
/***/ },
|
||||
/* 5 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
module.exports = require("readline");
|
||||
|
||||
/***/ },
|
||||
/* 6 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
"use strict";
|
||||
@@ -204,7 +123,7 @@
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 7 */
|
||||
/* 6 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
/*
|
||||
@@ -271,12 +190,95 @@
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 8 */
|
||||
/* 7 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
var events_1 = __webpack_require__(9);
|
||||
var VirtualConnection_1 = __webpack_require__(10);
|
||||
// Limit dependencies to core Node modules. This means the code in this file has to be very low-level and unattractive,
|
||||
// but simplifies things for the consumer of this module.
|
||||
__webpack_require__(2);
|
||||
var net = __webpack_require__(8);
|
||||
var path = __webpack_require__(4);
|
||||
var readline = __webpack_require__(9);
|
||||
var ArgsUtil_1 = __webpack_require__(5);
|
||||
var ExitWhenParentExits_1 = __webpack_require__(6);
|
||||
var virtualConnectionServer = __webpack_require__(10);
|
||||
// Webpack doesn't support dynamic requires for files not present at compile time, so grab a direct
|
||||
// reference to Node's runtime 'require' function.
|
||||
var dynamicRequire = eval('require');
|
||||
// Signal to the .NET side when we're ready to accept invocations
|
||||
var server = net.createServer().on('listening', function () {
|
||||
console.log('[Microsoft.AspNetCore.NodeServices:Listening]');
|
||||
});
|
||||
// Each virtual connection represents a separate invocation
|
||||
virtualConnectionServer.createInterface(server).on('connection', function (connection) {
|
||||
readline.createInterface(connection, null).on('line', function (line) {
|
||||
try {
|
||||
// Get a reference to the function to invoke
|
||||
var invocation = JSON.parse(line);
|
||||
var invokedModule = dynamicRequire(path.resolve(process.cwd(), invocation.moduleName));
|
||||
var invokedFunction = invocation.exportedFunctionName ? invokedModule[invocation.exportedFunctionName] : invokedModule;
|
||||
// Prepare a callback for accepting non-streamed JSON responses
|
||||
var hasInvokedCallback_1 = false;
|
||||
var invocationCallback = function (errorValue, successValue) {
|
||||
if (hasInvokedCallback_1) {
|
||||
throw new Error('Cannot supply more than one result. The callback has already been invoked,'
|
||||
+ ' or the result stream has already been accessed');
|
||||
}
|
||||
hasInvokedCallback_1 = true;
|
||||
connection.end(JSON.stringify({
|
||||
result: successValue,
|
||||
errorMessage: errorValue && (errorValue.message || errorValue),
|
||||
errorDetails: errorValue && (errorValue.stack || null)
|
||||
}));
|
||||
};
|
||||
// Also support streamed binary responses
|
||||
Object.defineProperty(invocationCallback, 'stream', {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
hasInvokedCallback_1 = true;
|
||||
return connection;
|
||||
}
|
||||
});
|
||||
// Actually invoke it, passing through any supplied args
|
||||
invokedFunction.apply(null, [invocationCallback].concat(invocation.args));
|
||||
}
|
||||
catch (ex) {
|
||||
connection.end(JSON.stringify({
|
||||
errorMessage: ex.message,
|
||||
errorDetails: ex.stack
|
||||
}));
|
||||
}
|
||||
});
|
||||
});
|
||||
// Begin listening now. The underlying transport varies according to the runtime platform.
|
||||
// On Windows it's Named Pipes; on Linux/OSX it's Domain Sockets.
|
||||
var useWindowsNamedPipes = /^win/.test(process.platform);
|
||||
var parsedArgs = ArgsUtil_1.parseArgs(process.argv);
|
||||
var listenAddress = (useWindowsNamedPipes ? '\\\\.\\pipe\\' : '/tmp/') + parsedArgs.listenAddress;
|
||||
server.listen(listenAddress);
|
||||
ExitWhenParentExits_1.exitWhenParentExits(parseInt(parsedArgs.parentPid));
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 8 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
module.exports = require("net");
|
||||
|
||||
/***/ },
|
||||
/* 9 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
module.exports = require("readline");
|
||||
|
||||
/***/ },
|
||||
/* 10 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
var events_1 = __webpack_require__(11);
|
||||
var VirtualConnection_1 = __webpack_require__(12);
|
||||
// Keep this in sync with the equivalent constant in the .NET code. Both sides split up their transmissions into frames with this max length,
|
||||
// and both will reject longer frames.
|
||||
var MaxFrameBodyLength = 16 * 1024;
|
||||
@@ -458,13 +460,13 @@
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 9 */
|
||||
/* 11 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
module.exports = require("events");
|
||||
|
||||
/***/ },
|
||||
/* 10 */
|
||||
/* 12 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
@@ -473,18 +475,17 @@
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
var stream_1 = __webpack_require__(11);
|
||||
var stream_1 = __webpack_require__(13);
|
||||
/**
|
||||
* Represents a virtual connection. Multiple virtual connections may be multiplexed over a single physical socket connection.
|
||||
*/
|
||||
var VirtualConnection = (function (_super) {
|
||||
__extends(VirtualConnection, _super);
|
||||
function VirtualConnection(_beginWriteCallback) {
|
||||
var _this = _super.call(this) || this;
|
||||
_this._beginWriteCallback = _beginWriteCallback;
|
||||
_this._flowing = false;
|
||||
_this._receivedDataQueue = [];
|
||||
return _this;
|
||||
_super.call(this);
|
||||
this._beginWriteCallback = _beginWriteCallback;
|
||||
this._flowing = false;
|
||||
this._receivedDataQueue = [];
|
||||
}
|
||||
VirtualConnection.prototype._read = function () {
|
||||
this._flowing = true;
|
||||
@@ -515,7 +516,7 @@
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 11 */
|
||||
/* 13 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
module.exports = require("stream");
|
||||
@@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
@@ -34,19 +36,21 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
private bool _disposed;
|
||||
private int _portNumber;
|
||||
|
||||
public HttpNodeInstance(NodeServicesOptions options, int port = 0)
|
||||
public HttpNodeInstance(string projectPath, string[] watchFileExtensions, ILogger nodeInstanceOutputLogger,
|
||||
IDictionary<string, string> environmentVars, int invocationTimeoutMilliseconds, bool launchWithDebugging,
|
||||
int debuggingPort, int port = 0)
|
||||
: base(
|
||||
EmbeddedResourceReader.Read(
|
||||
typeof(HttpNodeInstance),
|
||||
"/Content/Node/entrypoint-http.js"),
|
||||
options.ProjectPath,
|
||||
options.WatchFileExtensions,
|
||||
projectPath,
|
||||
watchFileExtensions,
|
||||
MakeCommandLineOptions(port),
|
||||
options.NodeInstanceOutputLogger,
|
||||
options.EnvironmentVariables,
|
||||
options.InvocationTimeoutMilliseconds,
|
||||
options.LaunchWithDebugging,
|
||||
options.DebuggingPort)
|
||||
nodeInstanceOutputLogger,
|
||||
environmentVars,
|
||||
invocationTimeoutMilliseconds,
|
||||
launchWithDebugging,
|
||||
debuggingPort)
|
||||
{
|
||||
_client = new HttpClient();
|
||||
}
|
||||
|
||||
@@ -4,20 +4,8 @@ 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,33 +2,15 @@ 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,24 +1,9 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods that help with populating a <see cref="NodeServicesOptions"/> object.
|
||||
/// </summary>
|
||||
public static class NodeServicesOptionsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Configures the <see cref="INodeServices"/> service so that it will use out-of-process
|
||||
/// Node.js instances and perform RPC calls over HTTP.
|
||||
/// </summary>
|
||||
public static void UseHttpHosting(this NodeServicesOptions options)
|
||||
{
|
||||
options.NodeInstanceFactory = () => new HttpNodeInstance(options);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,11 +21,7 @@ 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 ***
|
||||
@@ -47,18 +43,6 @@ 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,
|
||||
@@ -87,15 +71,6 @@ 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)
|
||||
{
|
||||
@@ -179,41 +154,21 @@ 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);
|
||||
|
||||
/// <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>
|
||||
// This method is virtual, as it provides a way to override the NODE_PATH or the path to node.exe
|
||||
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)
|
||||
{
|
||||
@@ -262,28 +217,16 @@ 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)
|
||||
@@ -460,9 +403,6 @@ 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);
|
||||
|
||||
@@ -2,7 +2,7 @@ using System.IO;
|
||||
using System.IO.Pipes;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
|
||||
{
|
||||
internal class NamedPipeConnection : StreamConnection
|
||||
{
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
|
||||
{
|
||||
internal abstract class StreamConnection : IDisposable
|
||||
{
|
||||
@@ -2,7 +2,7 @@ using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
|
||||
{
|
||||
internal class UnixDomainSocketConnection : StreamConnection
|
||||
{
|
||||
@@ -3,7 +3,7 @@ using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
|
||||
{
|
||||
// From System.IO.Pipes/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs (an internal class in System.IO.Pipes)
|
||||
internal sealed class UnixDomainSocketEndPoint : EndPoint
|
||||
@@ -1,15 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.NodeServices.HostingModels;
|
||||
using Microsoft.AspNetCore.NodeServices.Sockets.PhysicalConnections;
|
||||
using Microsoft.AspNetCore.NodeServices.Sockets.VirtualConnections;
|
||||
using Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections;
|
||||
using Microsoft.AspNetCore.NodeServices.HostingModels.VirtualConnections;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.Sockets
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||
{
|
||||
/// <summary>
|
||||
/// A specialisation of the OutOfProcessNodeInstance base class that uses a lightweight binary streaming protocol
|
||||
@@ -41,19 +42,21 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets
|
||||
private string _socketAddress;
|
||||
private VirtualConnectionClient _virtualConnectionClient;
|
||||
|
||||
public SocketNodeInstance(NodeServicesOptions options, string socketAddress)
|
||||
public SocketNodeInstance(string projectPath, string[] watchFileExtensions, string socketAddress,
|
||||
ILogger nodeInstanceOutputLogger, IDictionary<string, string> environmentVars,
|
||||
int invocationTimeoutMilliseconds, bool launchWithDebugging, int debuggingPort)
|
||||
: base(
|
||||
EmbeddedResourceReader.Read(
|
||||
typeof(SocketNodeInstance),
|
||||
"/Content/Node/entrypoint-socket.js"),
|
||||
options.ProjectPath,
|
||||
options.WatchFileExtensions,
|
||||
projectPath,
|
||||
watchFileExtensions,
|
||||
MakeNewCommandLineOptions(socketAddress),
|
||||
options.NodeInstanceOutputLogger,
|
||||
options.EnvironmentVariables,
|
||||
options.InvocationTimeoutMilliseconds,
|
||||
options.LaunchWithDebugging,
|
||||
options.DebuggingPort)
|
||||
nodeInstanceOutputLogger,
|
||||
environmentVars,
|
||||
invocationTimeoutMilliseconds,
|
||||
launchWithDebugging,
|
||||
debuggingPort)
|
||||
{
|
||||
_socketAddress = socketAddress;
|
||||
}
|
||||
@@ -76,7 +79,7 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets
|
||||
// wait for the same connection task. There's no reason why the first caller should have the
|
||||
// special ability to cancel the connection process in a way that would affect subsequent
|
||||
// callers. So, each caller just independently stops awaiting connection if that call is cancelled.
|
||||
await ThrowOnCancellation(EnsureVirtualConnectionClientCreated(), cancellationToken);
|
||||
await EnsureVirtualConnectionClientCreated().OrThrowOnCancellation(cancellationToken);
|
||||
}
|
||||
|
||||
// For each invocation, we open a new virtual connection. This gives an API equivalent to opening a new
|
||||
@@ -212,17 +215,6 @@ namespace Microsoft.AspNetCore.NodeServices.Sockets
|
||||
return $"--listenAddress {listenAddress}";
|
||||
}
|
||||
|
||||
private static Task ThrowOnCancellation(Task task, CancellationToken cancellationToken)
|
||||
{
|
||||
return task.IsCompleted
|
||||
? task // If the task is already completed, no need to wrap it in a further layer of task
|
||||
: task.ContinueWith(
|
||||
_ => {}, // If the task completes, allow execution to continue
|
||||
cancellationToken,
|
||||
TaskContinuationOptions.ExecuteSynchronously,
|
||||
TaskScheduler.Default);
|
||||
}
|
||||
|
||||
#pragma warning disable 649 // These properties are populated via JSON deserialization
|
||||
private class RpcJsonResponse<TResult>
|
||||
{
|
||||
@@ -4,7 +4,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks.Dataflow;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.Sockets.VirtualConnections
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels.VirtualConnections
|
||||
{
|
||||
/// <summary>
|
||||
/// A virtual read/write connection, typically to a remote process. Multiple virtual connections can be
|
||||
@@ -5,12 +5,8 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.Sockets.VirtualConnections
|
||||
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,71 +4,18 @@ 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);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.NodeServices
|
||||
return InvokeExportWithPossibleRetryAsync<T>(moduleName, exportedFunctionName, args, /* allowRetry */ true, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<T> InvokeExportWithPossibleRetryAsync<T>(string moduleName, string exportedFunctionName, object[] args, bool allowRetry, CancellationToken cancellationToken)
|
||||
public async Task<T> InvokeExportWithPossibleRetryAsync<T>(string moduleName, string exportedFunctionName, object[] args, bool allowRetry, CancellationToken cancellationToken)
|
||||
{
|
||||
ThrowAnyOutstandingDelayedDisposalException();
|
||||
var nodeInstance = GetOrCreateCurrentNodeInstance();
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
// 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,12 +1,12 @@
|
||||
// Limit dependencies to core Node modules. This means the code in this file has to be very low-level and unattractive,
|
||||
// but simplifies things for the consumer of this module.
|
||||
import '../../Microsoft.AspNetCore.NodeServices/TypeScript/Util/OverrideStdOutputs';
|
||||
import './Util/OverrideStdOutputs';
|
||||
import * as net from 'net';
|
||||
import * as path from 'path';
|
||||
import * as readline from 'readline';
|
||||
import { Duplex } from 'stream';
|
||||
import { parseArgs } from '../../Microsoft.AspNetCore.NodeServices/TypeScript/Util/ArgsUtil';
|
||||
import { exitWhenParentExits } from '../../Microsoft.AspNetCore.NodeServices/TypeScript/Util/ExitWhenParentExits';
|
||||
import { parseArgs } from './Util/ArgsUtil';
|
||||
import { exitWhenParentExits } from './Util/ExitWhenParentExits';
|
||||
import * as virtualConnectionServer from './VirtualConnections/VirtualConnectionServer';
|
||||
|
||||
// Webpack doesn't support dynamic requires for files not present at compile time, so grab a direct
|
||||
@@ -4,17 +4,8 @@ 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,45 +3,19 @@ using System.IO;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices
|
||||
{
|
||||
/// <summary>
|
||||
/// 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
|
||||
public sealed class StringAsTempFile : IDisposable
|
||||
{
|
||||
private bool _disposedValue;
|
||||
private bool _hasDeletedTempFile;
|
||||
private object _fileDeletionLock = new object();
|
||||
|
||||
/// <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);
|
||||
|
||||
// Because .NET finalizers don't reliably run when the process is terminating, also
|
||||
// add event handlers for other shutdown scenarios.
|
||||
#if NET451
|
||||
AppDomain.CurrentDomain.ProcessExit += HandleProcessExit;
|
||||
AppDomain.CurrentDomain.DomainUnload += HandleProcessExit;
|
||||
#else
|
||||
// Note that this still doesn't capture SIGKILL (at least on macOS) - there doesn't
|
||||
// appear to be a way of doing that. So in that case, the temporary file will be
|
||||
// left behind.
|
||||
System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += HandleAssemblyUnloading;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <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);
|
||||
@@ -54,48 +28,15 @@ namespace Microsoft.AspNetCore.NodeServices
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// Dispose managed state
|
||||
#if NET451
|
||||
AppDomain.CurrentDomain.ProcessExit -= HandleProcessExit;
|
||||
AppDomain.CurrentDomain.DomainUnload -= HandleProcessExit;
|
||||
#else
|
||||
System.Runtime.Loader.AssemblyLoadContext.Default.Unloading -= HandleAssemblyUnloading;
|
||||
#endif
|
||||
// Would dispose managed state here, if there was any
|
||||
}
|
||||
|
||||
EnsureTempFileDeleted();
|
||||
File.Delete(FileName);
|
||||
|
||||
_disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureTempFileDeleted()
|
||||
{
|
||||
lock (_fileDeletionLock)
|
||||
{
|
||||
if (!_hasDeletedTempFile)
|
||||
{
|
||||
File.Delete(FileName);
|
||||
_hasDeletedTempFile = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if NET451
|
||||
private void HandleProcessExit(object sender, EventArgs args)
|
||||
{
|
||||
EnsureTempFileDeleted();
|
||||
}
|
||||
#else
|
||||
private void HandleAssemblyUnloading(System.Runtime.Loader.AssemblyLoadContext context)
|
||||
{
|
||||
EnsureTempFileDeleted();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Implements the finalization part of the IDisposable pattern by calling Dispose(false).
|
||||
/// </summary>
|
||||
~StringAsTempFile()
|
||||
{
|
||||
DisposeImpl(false);
|
||||
|
||||
@@ -1,45 +1,48 @@
|
||||
{
|
||||
"version": "1.0.0-*",
|
||||
"description": "Invoke Node.js modules at runtime in ASP.NET Core applications.",
|
||||
"version": "1.1.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
|
||||
"compilationOptions": {
|
||||
"keyFile": "../../tools/Key.snk"
|
||||
},
|
||||
"authors": [ "Microsoft" ],
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Hosting.Abstractions": "1.1.0",
|
||||
"Microsoft.Extensions.Logging.Console": "1.1.0",
|
||||
"Newtonsoft.Json": "9.0.1",
|
||||
"NETStandard.Library": "1.6.1-*"
|
||||
"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"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {},
|
||||
"netstandard1.6": {
|
||||
"net451": {
|
||||
"frameworkAssemblies": {
|
||||
"System.Net.Http": "4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"System.Diagnostics.Process": "4.3.0",
|
||||
"System.IO.FileSystem.Watcher": "4.3.0",
|
||||
"System.Runtime.Loader": "4.3.0"
|
||||
"Microsoft.Tpl.Dataflow": "4.5.24"
|
||||
}
|
||||
},
|
||||
"netstandard1.3": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
],
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"prepublish": [
|
||||
"npm install",
|
||||
"node node_modules/webpack/bin/webpack.js"
|
||||
"buildOptions": {
|
||||
"embed": [
|
||||
"Content/**/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,8 @@ module.exports = {
|
||||
]
|
||||
},
|
||||
entry: {
|
||||
'entrypoint-http': ['./TypeScript/HttpNodeInstanceEntryPoint']
|
||||
'entrypoint-http': ['./TypeScript/HttpNodeInstanceEntryPoint'],
|
||||
'entrypoint-socket': ['./TypeScript/SocketNodeInstanceEntryPoint'],
|
||||
},
|
||||
output: {
|
||||
libraryTarget: 'commonjs',
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
// 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,3 +1,4 @@
|
||||
/typings/
|
||||
/node_modules/
|
||||
/*.js
|
||||
/*.d.ts
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "redux-typed",
|
||||
"version": "2.0.0",
|
||||
"version": "1.0.2",
|
||||
"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 && tsc && echo 'Finished building NPM package \"redux-typed\"'",
|
||||
"prepublish": "rimraf *.d.ts && tsd update && tsc && echo 'Finished building NPM package \"redux-typed\"'",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Microsoft",
|
||||
@@ -18,10 +18,7 @@
|
||||
"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": "^2.0.0"
|
||||
"typescript": "^1.8.10"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,8 @@
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"declaration": true,
|
||||
"outDir": ".",
|
||||
"lib": ["es2015", "dom"]
|
||||
"outDir": "."
|
||||
},
|
||||
"files": [
|
||||
"src/main.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"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,28 +1,26 @@
|
||||
{
|
||||
"version": "1.0.0-*",
|
||||
"description": "Helpers for building React applications on ASP.NET Core.",
|
||||
"version": "1.1.0-*",
|
||||
"packOptions": {
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/aspnet/javascriptservices"
|
||||
},
|
||||
"tags": [
|
||||
"aspnetcore",
|
||||
"aspnetcoremvc",
|
||||
"nodeservices"
|
||||
]
|
||||
"compilationOptions": {
|
||||
"keyFile": "../../tools/Key.snk"
|
||||
},
|
||||
"buildOptions": {
|
||||
"warningsAsErrors": true,
|
||||
"keyFile": "../../tools/Key.snk",
|
||||
"xmlDoc": true
|
||||
"authors": [ "Microsoft" ],
|
||||
"tooling": {
|
||||
"defaultNamespace": "Microsoft.AspNetCore.ReactServices"
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.1.0",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.1.0-*"
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.1",
|
||||
"Microsoft.AspNetCore.SpaServices": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {},
|
||||
"netstandard1.6": {}
|
||||
"net451": {
|
||||
},
|
||||
"netstandard1.6": {
|
||||
"imports": [
|
||||
"dotnet5.6",
|
||||
"dnxcore50",
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
/bin/
|
||||
/node_modules/
|
||||
|
||||
@@ -1,178 +1,20 @@
|
||||
(function(e, a) { for(var i in a) e[i] = a[i]; }(exports, /******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
// 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) {
|
||||
// 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(
|
||||
'Prerendering failed because of an error while loading \'aspnet-prerendering\'. Error was: '
|
||||
+ ex.stack
|
||||
+ '\nCurrent directory is: '
|
||||
+ process.cwd()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
/******/ // 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");
|
||||
|
||||
/***/ }
|
||||
/******/ ])));
|
||||
return aspNetPrerendering.renderToString.apply(this, arguments);
|
||||
};
|
||||
|
||||
@@ -1,86 +1,20 @@
|
||||
(function(e, a) { for(var i in a) e[i] = a[i]; }(exports, /******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
// 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) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
/******/ // 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");
|
||||
|
||||
/***/ }
|
||||
/******/ ])));
|
||||
return aspNetWebpack.createWebpackDevServer.apply(this, arguments);
|
||||
};
|
||||
|
||||
@@ -1,36 +1,14 @@
|
||||
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,9 +11,6 @@ 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
|
||||
{
|
||||
@@ -27,10 +24,6 @@ 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));
|
||||
@@ -46,51 +39,25 @@ 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
|
||||
@@ -112,15 +79,12 @@ 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,
|
||||
request.PathBase.ToString());
|
||||
TimeoutMillisecondsParameter);
|
||||
|
||||
if (!string.IsNullOrEmpty(result.RedirectUrl))
|
||||
{
|
||||
|
||||
@@ -4,9 +4,6 @@ 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;
|
||||
@@ -20,18 +17,6 @@ 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>
|
||||
/// <param name="requestPathBase">The PathBase for the currently-executing HTTP request.</param>
|
||||
/// <returns></returns>
|
||||
public static Task<RenderToStringResult> RenderToString(
|
||||
string applicationBasePath,
|
||||
INodeServices nodeServices,
|
||||
@@ -39,8 +24,7 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
string requestAbsoluteUrl,
|
||||
string requestPathAndQuery,
|
||||
object customDataParameter,
|
||||
int timeoutMilliseconds,
|
||||
string requestPathBase)
|
||||
int timeoutMilliseconds)
|
||||
{
|
||||
return nodeServices.InvokeExportAsync<RenderToStringResult>(
|
||||
NodeScript.Value.FileName,
|
||||
@@ -50,8 +34,7 @@ namespace Microsoft.AspNetCore.SpaServices.Prerendering
|
||||
requestAbsoluteUrl,
|
||||
requestPathAndQuery,
|
||||
customDataParameter,
|
||||
timeoutMilliseconds,
|
||||
requestPathBase);
|
||||
timeoutMilliseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,28 +2,10 @@ 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; }
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
// 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,8 +38,6 @@ 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.
|
||||
@@ -48,12 +46,9 @@ Instead, what `SpaServices` offers is ASP.NET Core APIs that know how to invoke
|
||||
|
||||
### 1. Enable the asp-prerender-* tag helpers
|
||||
|
||||
Make sure you've installed into your project:
|
||||
Make sure you've installed the `Microsoft.AspNetCore.SpaServices` NuGet package and the `aspnet-prerendering` NPM package. Together these contain the server-side and client-side library code you'll need.
|
||||
|
||||
* The `Microsoft.AspNetCore.SpaServices` NuGet package, version 1.1.0-* or later
|
||||
* The `aspnet-prerendering` NPM package, version 2.0.1 or later
|
||||
|
||||
Together these contain the server-side and client-side library code you'll need. Now go to your `Views/_ViewImports.cshtml` file, and add the following line:
|
||||
Now go to your `Views/_ViewImports.cshtml` file, and add the following line:
|
||||
|
||||
@addTagHelper "*, Microsoft.AspNetCore.SpaServices"
|
||||
|
||||
@@ -70,9 +65,7 @@ If you run your application now, and browse to whatever page renders the view yo
|
||||
Create a JavaScript file at the path matching the `asp-prerender-module` value you specified above. In this example, that means creating a folder called `ClientApp` at the root of your project, and creating a file inside it called `boot-server.js`. Try putting the following into it:
|
||||
|
||||
```javascript
|
||||
var prerendering = require('aspnet-prerendering');
|
||||
|
||||
module.exports = prerendering.createServerRenderer(function(params) {
|
||||
module.exports = function(params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var result = '<h1>Hello world!</h1>'
|
||||
+ '<p>Current time in Node is: ' + new Date() + '</p>'
|
||||
@@ -81,7 +74,7 @@ module.exports = prerendering.createServerRenderer(function(params) {
|
||||
|
||||
resolve({ html: result });
|
||||
});
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
If you try running your app now, you should see the HTML snippet generated by your JavaScript getting injected into your page.
|
||||
@@ -103,9 +96,7 @@ For example, in your `cshtml`,
|
||||
Now in your JavaScript prerendering function, you can access this data by reading `params.data`, e.g.:
|
||||
|
||||
```javascript
|
||||
var prerendering = require('aspnet-prerendering');
|
||||
|
||||
module.exports = prerendering.createServerRenderer(function(params) {
|
||||
module.exports = function(params) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var result = '<h1>Hello world!</h1>'
|
||||
+ '<p>Is gold user: ' + params.data.isGoldUser + '</p>'
|
||||
@@ -113,7 +104,7 @@ module.exports = prerendering.createServerRenderer(function(params) {
|
||||
|
||||
resolve({ html: result });
|
||||
});
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
Notice that the property names are received in JavaScript-style casing (e.g., `isGoldUser`) even though they were sent in C#-style casing (e.g., `IsGoldUser`). This is because of how the JSON serialization is configured by default.
|
||||
@@ -138,60 +129,49 @@ 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 need to set up a build system.
|
||||
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:
|
||||
|
||||
#### Example: Configuring Webpack to build TypeScript
|
||||
* 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.
|
||||
|
||||
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:
|
||||
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.:
|
||||
|
||||
npm install -g webpack
|
||||
npm install --save ts-loader typescript
|
||||
<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
|
||||
|
||||
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
|
||||
import { createServerRenderer } from 'aspnet-prerendering';
|
||||
|
||||
export default createServerRenderer(params => {
|
||||
export default function (params: any): Promise<{ html: string}> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const html = `
|
||||
<h1>Hello world!</h1>
|
||||
@@ -201,12 +181,15 @@ export default createServerRenderer(params => {
|
||||
|
||||
resolve({ html });
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
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:
|
||||
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`:
|
||||
|
||||
<div id="my-spa" asp-prerender-module="ClientApp/dist/main-server"></div>
|
||||
<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.
|
||||
|
||||
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/).
|
||||
|
||||
@@ -293,7 +276,30 @@ 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>
|
||||
|
||||
If you want to enable server-side prerendering too, follow the same process as described under [server-side prerendering](#server-side-prerendering).
|
||||
#### 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).
|
||||
|
||||
#### Realistic React apps and Redux
|
||||
|
||||
@@ -400,7 +406,7 @@ To make this work, the template has Webpack configured to inject the contents of
|
||||
|
||||
```javascript
|
||||
// This goes into webpack.config.js, in the module loaders array:
|
||||
{ test: /\.css/, include: /ClientApp/, loader: 'raw-loader' }
|
||||
{ test: /\.css/, include: /ClientApp/, loader: 'raw' }
|
||||
```
|
||||
|
||||
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:
|
||||
@@ -412,10 +418,10 @@ 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' }
|
||||
{ test: /\.less/, include: /ClientApp/, loader: 'raw!less' }
|
||||
```
|
||||
|
||||
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:
|
||||
Notice how this chains together the `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({
|
||||
@@ -456,7 +462,7 @@ 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-loader!css-loader!less-loader' }
|
||||
{ test: /\.less/, loader: 'style!css!less' }
|
||||
```
|
||||
|
||||
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.
|
||||
@@ -498,7 +504,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-loader!less-loader') }
|
||||
{ test: /\.less$/, loader: extractStyles.extract('css!less') }
|
||||
```
|
||||
|
||||
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.:
|
||||
@@ -527,7 +533,7 @@ if (env.IsDevelopment()) {
|
||||
app.UseWebpackDevMiddleware();
|
||||
}
|
||||
|
||||
// Your call to app.UseStaticFiles(); should be here
|
||||
// You 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:
|
||||
@@ -598,14 +604,6 @@ 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:
|
||||
@@ -666,141 +664,3 @@ 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,22 +7,10 @@ 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,
|
||||
@@ -39,16 +27,6 @@ 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,
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
// 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);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es3",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"types": ["node"],
|
||||
"lib": ["es2015"]
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
@@ -30,7 +30,6 @@ namespace Microsoft.AspNetCore.SpaServices.Webpack
|
||||
_pathPrefix = pathPrefix;
|
||||
_options = options;
|
||||
_httpClient = new HttpClient(new HttpClientHandler());
|
||||
_httpClient.Timeout = _options.RequestTimeout;
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext context)
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.SpaServices.Webpack
|
||||
{
|
||||
internal class ConditionalProxyMiddlewareOptions
|
||||
{
|
||||
public ConditionalProxyMiddlewareOptions(string scheme, string host, string port, TimeSpan requestTimeout)
|
||||
public ConditionalProxyMiddlewareOptions(string scheme, string host, string port)
|
||||
{
|
||||
Scheme = scheme;
|
||||
Host = host;
|
||||
Port = port;
|
||||
RequestTimeout = requestTimeout;
|
||||
}
|
||||
|
||||
public string Scheme { get; }
|
||||
public string Host { get; }
|
||||
public string Port { get; }
|
||||
public TimeSpan RequestTimeout { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.NodeServices;
|
||||
using Microsoft.AspNetCore.SpaServices.Webpack;
|
||||
@@ -8,29 +7,17 @@ using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using Newtonsoft.Json;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
// 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)
|
||||
@@ -60,14 +47,6 @@ namespace Microsoft.AspNetCore.Builder
|
||||
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
|
||||
@@ -75,18 +54,12 @@ namespace Microsoft.AspNetCore.Builder
|
||||
"/Content/Node/webpack-dev-middleware.js");
|
||||
var nodeScript = new StringAsTempFile(script); // Will be cleaned up on process exit
|
||||
|
||||
// Ideally, this would be relative to the application's PathBase (so it could work in virtual directories)
|
||||
// but it's not clear that such information exists during application startup, as opposed to within the context
|
||||
// of a request.
|
||||
var hmrEndpoint = "/__webpack_hmr";
|
||||
|
||||
// Tell Node to start the server hosting webpack-dev-middleware
|
||||
var devServerOptions = new
|
||||
{
|
||||
webpackConfigPath = Path.Combine(nodeServicesOptions.ProjectPath, options.ConfigFile ?? DefaultConfigFile),
|
||||
suppliedOptions = options,
|
||||
understandsMultiplePublicPaths = true,
|
||||
hotModuleReplacementEndpointUrl = hmrEndpoint
|
||||
understandsMultiplePublicPaths = true
|
||||
};
|
||||
var devServerInfo =
|
||||
nodeServices.InvokeExportAsync<WebpackDevServerInfo>(nodeScript.FileName, "createWebpackDevServer",
|
||||
@@ -100,30 +73,33 @@ namespace Microsoft.AspNetCore.Builder
|
||||
}
|
||||
|
||||
// Proxy the corresponding requests through ASP.NET and into the Node listener
|
||||
// Anything under /<publicpath> (e.g., /dist) is proxied as a normal HTTP request with a typical timeout (100s is the default from HttpClient),
|
||||
// plus /__webpack_hmr is proxied with infinite timeout, because it's an EventSource (long-lived request).
|
||||
foreach (var publicPath in devServerInfo.PublicPaths)
|
||||
{
|
||||
appBuilder.UseProxyToLocalWebpackDevMiddleware(publicPath, devServerInfo.Port, TimeSpan.FromSeconds(100));
|
||||
}
|
||||
appBuilder.UseProxyToLocalWebpackDevMiddleware(hmrEndpoint, devServerInfo.Port, Timeout.InfiniteTimeSpan);
|
||||
}
|
||||
|
||||
private static void UseProxyToLocalWebpackDevMiddleware(this IApplicationBuilder appBuilder, string publicPath, int proxyToPort, TimeSpan requestTimeout)
|
||||
{
|
||||
// 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
|
||||
// the one making the internal HTTP requests, and it's going to be to some port on this machine
|
||||
// because aspnet-webpack hosts the dev server there. We can't use the hostname that the client
|
||||
// sees, because that could be anything (e.g., some upstream load balancer) and we might not be
|
||||
// able to make outbound requests to it from here.
|
||||
// Also note that the webpack HMR service always uses HTTP, even if your app server uses HTTPS,
|
||||
// because the HMR service has no need for HTTPS (the client doesn't see it directly - all traffic
|
||||
// to it is proxied), and the HMR service couldn't use HTTPS anyway (in general it wouldn't have
|
||||
// the necessary certificate).
|
||||
var proxyOptions = new ConditionalProxyMiddlewareOptions(
|
||||
"http", "localhost", proxyToPort.ToString(), requestTimeout);
|
||||
appBuilder.UseMiddleware<ConditionalProxyMiddleware>(publicPath, proxyOptions);
|
||||
var proxyOptions = new ConditionalProxyMiddlewareOptions(WebpackDevMiddlewareScheme,
|
||||
"localhost", devServerInfo.Port.ToString());
|
||||
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
|
||||
// a while. So, just serve a 302 for those. But note that we must use the hostname that the client
|
||||
// sees, not "localhost", so that it works even when you're not running on localhost (e.g., Docker).
|
||||
appBuilder.Map(WebpackHotMiddlewareEndpoint, builder =>
|
||||
{
|
||||
builder.Use(next => ctx =>
|
||||
{
|
||||
var hostname = ctx.Request.Host.Host;
|
||||
ctx.Response.Redirect(
|
||||
$"{WebpackDevMiddlewareScheme}://{hostname}:{devServerInfo.Port.ToString()}{WebpackHotMiddlewareEndpoint}");
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#pragma warning disable CS0649
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user