Skip to content

Commit 1a62df8

Browse files
committed
Initial port from aspnet-core-react-template
0 parents  commit 1a62df8

File tree

110 files changed

+9569
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+9569
-0
lines changed

.editorconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
root = true
2+
3+
[*]
4+
end_of_line = lf
5+
charset = utf-8
6+
indent_style = space
7+
trim_trailing_whitespace = true
8+
insert_final_newline = true
9+
indent_size = 2
10+
11+
[*.{js,ts,tsx}]
12+
indent_size = 4

.gitignore

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
.DS_Store
2+
3+
# dotnet core
4+
bin/
5+
obj/
6+
project.lock.json
7+
8+
api/wwwroot/**
9+
!api/wwwroot/scratch.html
10+
!api/wwwroot/favicon.ico
11+
12+
# node
13+
node_modules/
14+
typings/
15+
npm-debug.log
16+
17+
# client-react
18+
client-react/components/*.js
19+
client-react.test/build
20+
!client-react.test/build/client-react/styles/
21+
22+
# ops
23+
ops/hosts
24+
ops/*.retry
25+
26+
# other
27+
*.js.map
28+

.vscode/launch.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"version": "0.2.0",
3+
"configurations": [
4+
{
5+
"name": "Debug api/ (server)",
6+
"type": "coreclr",
7+
"request": "launch",
8+
"preLaunchTask": "build",
9+
"program": "${workspaceRoot}/api/bin/Debug/netcoreapp1.1/api.dll",
10+
"args": [],
11+
"env": {
12+
"ASPNETCORE_ENVIRONMENT": "Development",
13+
"NODE_PATH": "../node_modules/"
14+
},
15+
"cwd": "${workspaceRoot}/api",
16+
"externalConsole": false,
17+
"stopAtEntry": false,
18+
"internalConsoleOptions": "openOnSessionStart"
19+
},
20+
{
21+
"name": "Debug client-web.test/ (Mocha tests)",
22+
"type": "node",
23+
"request": "launch",
24+
"protocol": "inspector",
25+
"program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
26+
"stopOnEntry": false,
27+
"args": [
28+
"--require",
29+
"ignore-styles",
30+
"--recursive",
31+
"client-web.test/build/client-web.test"
32+
],
33+
"cwd": "${workspaceRoot}",
34+
"preLaunchTask": "pretest:client",
35+
"runtimeArgs": [
36+
"--nolazy"
37+
],
38+
"env": {
39+
"NODE_ENV": "development"
40+
},
41+
"sourceMaps": true
42+
},
43+
{
44+
"name": ".NET Core Attach",
45+
"type": "coreclr",
46+
"request": "attach",
47+
"processId": "${command:pickProcess}"
48+
}
49+
]
50+
}

.vscode/settings.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"files.exclude": {
3+
"**/.git": true,
4+
"**/.svn": true,
5+
"**/.hg": true,
6+
"**/CVS": true,
7+
"**/.DS_Store": true,
8+
"**/bin": true,
9+
"**/obj": true
10+
}
11+
}

.vscode/tasks.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
// See https://go.microsoft.com/fwlink/?LinkId=733558
3+
// for the documentation about the tasks.json format
4+
"version": "0.1.0",
5+
"command": "npm",
6+
"isShellCommand": true,
7+
"showOutput": "always",
8+
"suppressTaskName": true,
9+
"tasks": [
10+
{
11+
"taskName": "build",
12+
"args": [
13+
"run",
14+
"build"
15+
],
16+
"isBuildCommand": true
17+
},
18+
{
19+
"taskName": "test",
20+
"args": [
21+
"run",
22+
"test"
23+
],
24+
"isTestCommand": true
25+
},
26+
{
27+
"taskName": "pretest:client",
28+
"args":[
29+
"run",
30+
"pretest:client"
31+
]
32+
}
33+
]
34+
}

README.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# ASP.NET Core / Vue.js SPA Template App
2+
3+
This app is a template application using ASP.NET Core for a REST/JSON API server and Vue.js for a web client.
4+
5+
## Overview of Stack
6+
- Server
7+
- ASP.NET Core
8+
- PostgresSQL
9+
- Entity Framework Core w/ EF Migrations
10+
- JSON Web Token (JWT) authorization with OpenIddict
11+
- Docker used for development PostgresSQL database and MailCatcher server
12+
- Client
13+
- Vue.js
14+
- Webpack for asset bundling and HMR (Hot Module Replacement)
15+
- CSS Modules
16+
- Testing
17+
- xUnit for .NET Core
18+
- MailCatcher for development email delivery
19+
- DevOps
20+
- Ansible playbook for provisioning (Nginx reverse proxy, SSL via Let's Encrypt, PostgresSQL backups to S3)
21+
- Ansible playbook for deployment
22+
23+
## Setup
24+
25+
1. Install the following:
26+
- [.NET Core 1.1](https://www.microsoft.com/net/core)
27+
- [Node.js >= v7.8.0](https://nodejs.org/en/download/)
28+
- [Ansible >= 2.0](http://docs.ansible.com/ansible/intro_installation.html)
29+
- [Docker](https://docs.docker.com/engine/installation/)
30+
2. Run `npm install && npm start`
31+
3. Open browser and navigate to [http://localhost:5000](http://localhost:5000).
32+
33+
## Scripts
34+
35+
### `npm install`
36+
37+
When first cloning the repo or adding new dependencies, run this command. This will:
38+
39+
- Install Node dependencies from package.json
40+
- Install .NET Core dependencies from api/api.csproj and api.test/api.test.csproj (using dotnet restore)
41+
42+
### `npm start`
43+
44+
To start the app for development, run this command. This will:
45+
46+
- Run `docker-compose up` to ensure the PostgreSQL and MailCatcher Docker images are up and running
47+
- Run dotnet watch run which will build the app (if changed), watch for changes and start the web server on http://localhost:5000
48+
- Run Webpack dev middleware with HMR via [ASP.NET JavaScriptServices](https://github.com/aspnet/JavaScriptServices)
49+
50+
### `npm run migrate`
51+
52+
After making changes to Entity Framework models in `api/Models/`, run this command to generate and run a migration on the database. A timestamp will be used for the migration name.
53+
54+
### `npm test`
55+
56+
This will run the xUnit tests in api.test/ and the Vue.js tests in client-web.test/.
57+
58+
### `npm run provision:prod`
59+
60+
_Before running this script, you need to create an ops/hosts file first. See the [ops README](ops/) for instructions._
61+
62+
This will run the ops/provision.yml Ansible playbook and provision hosts in ops/hosts inventory file. This prepares the hosts to recieve deployments by doing the following:
63+
- Install Nginx
64+
- Generate a SSL certificate from [Let's Encrypt](https://letsencrypt.org/) and configure Nginx to use it
65+
- Install .Net Core
66+
- Install Supervisor (will run/manage the ASP.NET app)
67+
- Install PostgreSQL
68+
- Setup a cron job to automatically backup the PostgresSQL database, compress it, and upload it to S3.
69+
- Setup UFW (firewall) to lock everything down except inbound SSH and web traffic
70+
- Create a deploy user, directory for deployments and configure Nginx to serve from this directory
71+
72+
### `npm run deploy:prod`
73+
74+
_Before running this script, you need to create a ops/hosts file first. See the [ops README](ops/) for instructions._
75+
76+
This script will:
77+
- Build release Webpack bundles
78+
- Package the .NET Core application in Release mode (dotnet publish)
79+
- Run the ops/deploy.yml Ansible playbook to deploy this app to hosts in /ops/hosts inventory file. This does the following:
80+
- Copies the build assets to the remote host(s)
81+
- Updates the `appsettings.json` file with PostgresSQL credentials specified in ops/hosts file and the app URL (needed for JWT tokens)
82+
- Restarts the app so that changes will be picked up
83+
84+
## Development Email Delivery
85+
86+
This template includes a [MailCatcher](https://mailcatcher.me/) Docker image so that when email is sent during development (i.e. new user registration), it can be viewed
87+
in the MailCacher web interface at [http://localhost:1080/](http://localhost:1080/).
88+
89+
## Visual Studio Code config
90+
91+
This project has [Visual Studio Code](https://code.visualstudio.com/) tasks and debugger launch config located in .vscode/.
92+
93+
### Tasks
94+
95+
- **Command+Shift+B** - Runs the "build" task which builds the api/ project
96+
- **Command+Shift+T** - Runs the "test" task which runs the xUnit tests in api.test/ and Mocha/Enzyme tests in client-react.test/.
97+
98+
### Debug Launcher
99+
100+
With the following debugger launch configs, you can set breakpoints in api/ or the the Mocha tests in client-react.test/ and have full debugging support.
101+
102+
- **Debug api/ (server)** - Runs the vscode debugger (breakpoints) on the api/ .NET Core app
103+
- **Debug client-web.test/ (Mocha tests)** - Runs the vscode debugger on the client-web.test/ Mocha tests
104+
105+
## Credit
106+
107+
The following resources were helpful in setting up this template:
108+
109+
- [Sample for implementing Authentication with a React Flux app and JWTs](https://github.com/auth0-blog/react-flux-jwt-authentication-sample)
110+
- [Angular 2, React, and Knockout apps on ASP.NET Core](http://blog.stevensanderson.com/2016/05/02/angular2-react-knockout-apps-on-aspnet-core/)
111+
- [Setting up ASP.NET v5 (vNext) to use JWT tokens (using OpenIddict)](http://capesean.co.za/blog/asp-net-5-jwt-tokens/)
112+
- [Cross-platform Single Page Applications with ASP.NET Core 1.0, Angular 2 & TypeScript](https://chsakell.com/2016/01/01/cross-platform-single-page-applications-with-asp-net-5-angular-2-typescript/)
113+
- [Stack Overflow - Token Based Authentication in ASP.NET Core](http://stackoverflow.com/questions/30546542/token-based-authentication-in-asp-net-core-refreshed)
114+
- [SPA example of a token based authentication implementation using the Aurelia front end framework and ASP.NET core]( https://github.com/alexandre-spieser/AureliaAspNetCoreAuth)
115+
- [A Real-World React.js Setup for ASP.NET Core and MVC5](https://www.simple-talk.com/dotnet/asp-net/a-real-world-react-js-setup-for-asp-net-core-and-mvc)
116+
- My own perseverance because this took a _lot_ of time to get right 😁

api.test/Controller/Tests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using Xunit;
4+
using app = aspnetCoreReactTemplate;
5+
6+
namespace Tests.Controller
7+
{
8+
public class Tests
9+
{
10+
// [Fact]
11+
// public void Index_ReturnsAViewResult_WithAListOfBrainstormSessions()
12+
// {
13+
// var controller = new app.Controllers.ContactsController(null);
14+
// var result = (IEnumerable<app.Models.Contact>)controller.Get();
15+
16+
// Assert.NotEqual(result.Count(), 0);
17+
// }
18+
}
19+
}

api.test/ControllerTests.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using Xunit;
2+
3+
namespace Tests
4+
{
5+
public class ControllerTests
6+
{
7+
[Fact]
8+
public void Test1()
9+
{
10+
var contact = new aspnetCoreReactTemplate.Models.Contact();
11+
Assert.True(string.IsNullOrEmpty(contact.email));
12+
}
13+
}
14+
}

api.test/NuGet.Config

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<packageSources>
4+
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
5+
<add key="aspnet-contrib" value="https://www.myget.org/F/aspnet-contrib/api/v3/index.json" />
6+
</packageSources>
7+
</configuration>

api.test/Unit/Tests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Xunit;
2+
using app = aspnetCoreReactTemplate;
3+
4+
namespace Tests.Unit
5+
{
6+
public class Tests
7+
{
8+
[Fact]
9+
public void TestNewContactProperties()
10+
{
11+
var contact = new app.Models.Contact();
12+
13+
Assert.True(string.IsNullOrEmpty(contact.lastName));
14+
Assert.True(string.IsNullOrEmpty(contact.firstName));
15+
Assert.True(string.IsNullOrEmpty(contact.email));
16+
Assert.True(string.IsNullOrEmpty(contact.phone));
17+
}
18+
}
19+
}

0 commit comments

Comments
 (0)