Skip to content

Commit 76bf405

Browse files
committed
Refactor AddNodeApp
- Obsolete the existing AddNodeApp that takes a file path only - Introduce a new AddNodeApp that takes a directory path and a file path relative to that directory - Includes a default Dockerfile for the Node application - Add Npm package manager support if the directory contains a package.json file
1 parent 6a3a7ac commit 76bf405

File tree

12 files changed

+1836
-12
lines changed

12 files changed

+1836
-12
lines changed

playground/AspireWithJavaScript/AspireJavaScript.AppHost/AppHost.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
.WithExternalHttpEndpoints();
55

66
builder.AddJavaScriptApp("angular", "../AspireJavaScript.Angular")
7+
.WithRunScript("start")
78
.WithReference(weatherApi)
89
.WaitFor(weatherApi)
910
.WithHttpEndpoint(env: "PORT")
1011
.WithExternalHttpEndpoints()
1112
.PublishAsDockerFile();
1213

1314
builder.AddJavaScriptApp("react", "../AspireJavaScript.React")
15+
.WithRunScript("start")
1416
.WithReference(weatherApi)
1517
.WaitFor(weatherApi)
1618
.WithEnvironment("BROWSER", "none") // Disable opening browser on npm start
@@ -19,6 +21,7 @@
1921
.PublishAsDockerFile();
2022

2123
builder.AddJavaScriptApp("vue", "../AspireJavaScript.Vue")
24+
.WithRunScript("start")
2225
.WithNpm(installCommand: "ci") // Use 'npm ci' for clean install, requires lock file
2326
.WithReference(weatherApi)
2427
.WaitFor(weatherApi)
@@ -31,6 +34,12 @@
3134
.WithEnvironment("BROWSER", "none")
3235
.WithExternalHttpEndpoints();
3336

37+
builder.AddNodeApp("node", "../AspireJavaScript.NodeApp", "app.js")
38+
.WithRunScript("dev") // Use 'npm run dev' for development
39+
.WithHttpEndpoint(env: "PORT")
40+
.WithExternalHttpEndpoints()
41+
.PublishAsDockerFile();
42+
3443
weatherApi.PublishWithContainerFiles(reactvite, "./wwwroot");
3544

3645
builder.Build().Run();
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# AspireJavaScript Node.js App
2+
3+
A default Node.js application built with Express.js for the AspireJavaScript project.
4+
5+
## Features
6+
7+
- Express.js web server
8+
- CORS support
9+
- JSON middleware
10+
- Static file serving
11+
- Health check endpoint
12+
- Mock weather API endpoint
13+
- Error handling middleware
14+
- Development and production configurations
15+
16+
## Getting Started
17+
18+
### Prerequisites
19+
20+
- Node.js (v14 or higher)
21+
- npm or yarn
22+
23+
### Installation
24+
25+
1. Navigate to the project directory:
26+
```bash
27+
cd AspireJavaScript.NodeApp
28+
```
29+
30+
2. Install dependencies:
31+
```bash
32+
npm install
33+
```
34+
35+
### Running the Application
36+
37+
#### Development Mode
38+
```bash
39+
npm run dev
40+
```
41+
This runs the app with nodemon for automatic restarts on file changes.
42+
43+
#### Production Mode
44+
```bash
45+
npm start
46+
```
47+
48+
The application will start on port 3000 by default, or on the port specified in the `PORT` environment variable.
49+
50+
## API Endpoints
51+
52+
- `GET /` - Welcome message with timestamp
53+
- `GET /api/health` - Health check endpoint
54+
- `GET /api/weather` - Mock weather data (compatible with other Aspire apps)
55+
56+
## Project Structure
57+
58+
```
59+
AspireJavaScript.NodeApp/
60+
├── app.js # Main application file
61+
├── package.json # Project configuration
62+
├── README.md # This file
63+
└── public/ # Static files (created automatically)
64+
```
65+
66+
## Environment Variables
67+
68+
- `PORT` - Server port (default: 3000)
69+
- `NODE_ENV` - Environment mode (development/production)
70+
71+
## License
72+
73+
MIT
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
const express = require('express');
2+
const cors = require('cors');
3+
const path = require('path');
4+
5+
const app = express();
6+
const PORT = process.env.PORT || 3000;
7+
8+
// Middleware
9+
app.use(cors());
10+
app.use(express.json());
11+
app.use(express.urlencoded({ extended: true }));
12+
13+
// Root route for browsers (serves HTML)
14+
app.get('/', (req, res) => {
15+
res.sendFile(path.join(__dirname, 'public', 'index.html'));
16+
});
17+
18+
app.get('/api/welcome', (req, res) => {
19+
res.json({
20+
message: 'Welcome to AspireJavaScript Node.js App!',
21+
timestamp: new Date().toISOString(),
22+
version: '1.0.0'
23+
});
24+
});
25+
26+
app.get('/api/health', (req, res) => {
27+
res.json({
28+
status: 'healthy',
29+
timestamp: new Date().toISOString()
30+
});
31+
});
32+
33+
app.get('/api/weather', (req, res) => {
34+
// Mock weather data similar to other Aspire apps
35+
const weatherData = [
36+
{
37+
date: new Date().toISOString().split('T')[0],
38+
temperatureC: Math.floor(Math.random() * 35) - 5,
39+
summary: 'Sunny'
40+
},
41+
{
42+
date: new Date(Date.now() + 86400000).toISOString().split('T')[0],
43+
temperatureC: Math.floor(Math.random() * 35) - 5,
44+
summary: 'Cloudy'
45+
},
46+
{
47+
date: new Date(Date.now() + 172800000).toISOString().split('T')[0],
48+
temperatureC: Math.floor(Math.random() * 35) - 5,
49+
summary: 'Rainy'
50+
}
51+
].map(item => ({
52+
...item,
53+
temperatureF: Math.round((item.temperatureC * 9/5) + 32)
54+
}));
55+
56+
res.json(weatherData);
57+
});
58+
59+
// Serve remaining static files from public directory (after API routes)
60+
app.use(express.static(path.join(__dirname, 'public')));
61+
62+
// Error handling middleware
63+
app.use((err, req, res, next) => {
64+
console.error(err.stack);
65+
res.status(500).json({
66+
message: 'Something went wrong!',
67+
error: process.env.NODE_ENV === 'production' ? {} : err.stack
68+
});
69+
});
70+
71+
// General 404 handler (for non-API routes)
72+
app.use('*', (req, res) => {
73+
res.status(404).json({
74+
message: 'Route not found',
75+
path: req.originalUrl
76+
});
77+
});
78+
79+
// Start server
80+
app.listen(PORT, () => {
81+
console.log(`Server is running on port ${PORT}`);
82+
console.log(`Environment: ${process.env.NODE_ENV || 'development'}`);
83+
console.log(`Visit: http://localhost:${PORT}`);
84+
});
85+
86+
module.exports = app;

0 commit comments

Comments
 (0)