@ -0,0 +1,30 @@ | |||||
**/.classpath | |||||
**/.dockerignore | |||||
**/.env | |||||
**/.git | |||||
**/.gitignore | |||||
**/.project | |||||
**/.settings | |||||
**/.toolstarget | |||||
**/.vs | |||||
**/.vscode | |||||
**/*.*proj.user | |||||
**/*.dbmdl | |||||
**/*.jfm | |||||
**/azds.yaml | |||||
**/bin | |||||
**/charts | |||||
**/docker-compose* | |||||
**/Dockerfile* | |||||
**/node_modules | |||||
**/npm-debug.log | |||||
**/obj | |||||
**/secrets.dev.yaml | |||||
**/values.dev.yaml | |||||
LICENSE | |||||
README.md | |||||
!**/.gitignore | |||||
!.git/HEAD | |||||
!.git/config | |||||
!.git/packed-refs | |||||
!.git/refs/heads/** |
@ -0,0 +1,29 @@ | |||||
<Project Sdk="Microsoft.NET.Sdk.Web"> | |||||
<PropertyGroup> | |||||
<TargetFramework>net8.0</TargetFramework> | |||||
<Nullable>enable</Nullable> | |||||
<ImplicitUsings>enable</ImplicitUsings> | |||||
<UserSecretsId>25c82ccd-f64b-45a0-98a0-b0393dd84477</UserSecretsId> | |||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> | |||||
<DockerfileContext>..\..</DockerfileContext> | |||||
<SpaRoot>..\awesomemicroservices.client</SpaRoot> | |||||
<SpaProxyLaunchCommand>npm start</SpaProxyLaunchCommand> | |||||
<SpaProxyServerUrl>https://localhost:56902</SpaProxyServerUrl> | |||||
</PropertyGroup> | |||||
<ItemGroup> | |||||
<PackageReference Include="Microsoft.AspNetCore.SpaProxy"> | |||||
<Version>8.*-*</Version> | |||||
</PackageReference> | |||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" /> | |||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ProjectReference Include="..\awesomemicroservices.client\awesomemicroservices.client.esproj"> | |||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly> | |||||
</ProjectReference> | |||||
</ItemGroup> | |||||
</Project> |
@ -0,0 +1,6 @@ | |||||
@AwesomeMicroservices.Server_HostAddress = http://localhost:5188 | |||||
GET {{AwesomeMicroservices.Server_HostAddress}}/weatherforecast/ | |||||
Accept: application/json | |||||
### |
@ -0,0 +1,9 @@ | |||||
This file explains how Visual Studio created the project. | |||||
The following steps were used to generate this project: | |||||
- Create new ASP\.NET Core Web API project. | |||||
- Update `launchSettings.json` to register the SPA proxy as a startup assembly. | |||||
- Update project file to add a reference to the frontend project and set SPA properties. | |||||
- Add `dockerfile` to set up docker build. | |||||
- Add project to the startup projects list. | |||||
- Write this file. |
@ -0,0 +1,33 @@ | |||||
using Microsoft.AspNetCore.Mvc; | |||||
namespace AwesomeMicroservices.Server.Controllers | |||||
{ | |||||
[ApiController] | |||||
[Route("[controller]")] | |||||
public class WeatherForecastController : ControllerBase | |||||
{ | |||||
private static readonly string[] Summaries = new[] | |||||
{ | |||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" | |||||
}; | |||||
private readonly ILogger<WeatherForecastController> _logger; | |||||
public WeatherForecastController(ILogger<WeatherForecastController> logger) | |||||
{ | |||||
_logger = logger; | |||||
} | |||||
[HttpGet(Name = "GetWeatherForecast")] | |||||
public IEnumerable<WeatherForecast> Get() | |||||
{ | |||||
return Enumerable.Range(1, 5).Select(index => new WeatherForecast | |||||
{ | |||||
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), | |||||
TemperatureC = Random.Shared.Next(-20, 55), | |||||
Summary = Summaries[Random.Shared.Next(Summaries.Length)] | |||||
}) | |||||
.ToArray(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,38 @@ | |||||
# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. | |||||
# This stage is used when running from VS in fast mode (Default for Debug configuration) | |||||
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base | |||||
USER $APP_UID | |||||
WORKDIR /app | |||||
EXPOSE 8080 | |||||
EXPOSE 8081 | |||||
# This stage is used to build the service project | |||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS with-node | |||||
RUN apt-get update | |||||
RUN apt-get install curl | |||||
RUN curl -sL https://deb.nodesource.com/setup_20.x | bash | |||||
RUN apt-get -y install nodejs | |||||
RUN npm install -g @angular/cli | |||||
FROM with-node AS build | |||||
ARG BUILD_CONFIGURATION=Release | |||||
WORKDIR /src | |||||
COPY ["AwesomeMicroservices/AwesomeMicroservices.Server/AwesomeMicroservices.Server.csproj", "AwesomeMicroservices/AwesomeMicroservices.Server/"] | |||||
COPY ["awesomemicroservices.client/awesomemicroservices.client.esproj", "awesomemicroservices.client/"] | |||||
RUN dotnet restore "./AwesomeMicroservices/AwesomeMicroservices.Server/AwesomeMicroservices.Server.csproj" | |||||
COPY . . | |||||
WORKDIR "/src/AwesomeMicroservices/AwesomeMicroservices.Server" | |||||
RUN dotnet build "./AwesomeMicroservices.Server.csproj" -c $BUILD_CONFIGURATION -o /app/build | |||||
# This stage is used to publish the service project to be copied to the final stage | |||||
FROM build AS publish | |||||
ARG BUILD_CONFIGURATION=Release | |||||
RUN dotnet publish "./AwesomeMicroservices.Server.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false | |||||
# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration) | |||||
FROM base AS final | |||||
WORKDIR /app | |||||
COPY --from=publish /app/publish . | |||||
ENTRYPOINT ["dotnet", "AwesomeMicroservices.Server.dll"] |
@ -0,0 +1,41 @@ | |||||
namespace AwesomeMicroservices.Server | |||||
{ | |||||
public class Program | |||||
{ | |||||
public static void Main(string[] args) | |||||
{ | |||||
var builder = WebApplication.CreateBuilder(args); | |||||
// Add services to the container. | |||||
builder.Services.AddControllers(); | |||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle | |||||
builder.Services.AddEndpointsApiExplorer(); | |||||
builder.Services.AddSwaggerGen(); | |||||
var app = builder.Build(); | |||||
app.UseDefaultFiles(); | |||||
app.UseStaticFiles(); | |||||
// Configure the HTTP request pipeline. | |||||
if (app.Environment.IsDevelopment()) | |||||
{ | |||||
app.UseSwagger(); | |||||
app.UseSwaggerUI(); | |||||
} | |||||
app.UseHttpsRedirection(); | |||||
app.UseAuthorization(); | |||||
app.MapControllers(); | |||||
app.MapFallbackToFile("/index.html"); | |||||
app.Run(); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,55 @@ | |||||
{ | |||||
"profiles": { | |||||
"http": { | |||||
"commandName": "Project", | |||||
"launchBrowser": true, | |||||
"launchUrl": "swagger", | |||||
"environmentVariables": { | |||||
"ASPNETCORE_ENVIRONMENT": "Development", | |||||
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy" | |||||
}, | |||||
"dotnetRunMessages": true, | |||||
"applicationUrl": "http://localhost:5188" | |||||
}, | |||||
"https": { | |||||
"commandName": "Project", | |||||
"launchBrowser": true, | |||||
"launchUrl": "swagger", | |||||
"environmentVariables": { | |||||
"ASPNETCORE_ENVIRONMENT": "Development", | |||||
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy" | |||||
}, | |||||
"dotnetRunMessages": true, | |||||
"applicationUrl": "https://localhost:7223;http://localhost:5188" | |||||
}, | |||||
"IIS Express": { | |||||
"commandName": "IISExpress", | |||||
"launchBrowser": true, | |||||
"launchUrl": "swagger", | |||||
"environmentVariables": { | |||||
"ASPNETCORE_ENVIRONMENT": "Development", | |||||
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy" | |||||
} | |||||
}, | |||||
"Container (Dockerfile)": { | |||||
"commandName": "Docker", | |||||
"launchBrowser": true, | |||||
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", | |||||
"environmentVariables": { | |||||
"ASPNETCORE_HTTPS_PORTS": "8081", | |||||
"ASPNETCORE_HTTP_PORTS": "8080" | |||||
}, | |||||
"publishAllPorts": true, | |||||
"useSSL": true | |||||
} | |||||
}, | |||||
"$schema": "http://json.schemastore.org/launchsettings.json", | |||||
"iisSettings": { | |||||
"windowsAuthentication": false, | |||||
"anonymousAuthentication": true, | |||||
"iisExpress": { | |||||
"applicationUrl": "http://localhost:22279", | |||||
"sslPort": 44347 | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,13 @@ | |||||
namespace AwesomeMicroservices.Server | |||||
{ | |||||
public class WeatherForecast | |||||
{ | |||||
public DateOnly Date { get; set; } | |||||
public int TemperatureC { get; set; } | |||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); | |||||
public string? Summary { get; set; } | |||||
} | |||||
} |
@ -0,0 +1,8 @@ | |||||
{ | |||||
"Logging": { | |||||
"LogLevel": { | |||||
"Default": "Information", | |||||
"Microsoft.AspNetCore": "Warning" | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,9 @@ | |||||
{ | |||||
"Logging": { | |||||
"LogLevel": { | |||||
"Default": "Information", | |||||
"Microsoft.AspNetCore": "Warning" | |||||
} | |||||
}, | |||||
"AllowedHosts": "*" | |||||
} |
@ -0,0 +1,17 @@ | |||||
# Editor configuration, see https://editorconfig.org | |||||
root = true | |||||
[*] | |||||
charset = utf-8 | |||||
indent_style = space | |||||
indent_size = 2 | |||||
insert_final_newline = true | |||||
trim_trailing_whitespace = true | |||||
[*.ts] | |||||
quote_type = single | |||||
ij_typescript_use_double_quotes = false | |||||
[*.md] | |||||
max_line_length = off | |||||
trim_trailing_whitespace = false |
@ -0,0 +1,42 @@ | |||||
# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files. | |||||
# Compiled output | |||||
/dist | |||||
/tmp | |||||
/out-tsc | |||||
/bazel-out | |||||
# Node | |||||
/node_modules | |||||
npm-debug.log | |||||
yarn-error.log | |||||
# IDEs and editors | |||||
.idea/ | |||||
.project | |||||
.classpath | |||||
.c9/ | |||||
*.launch | |||||
.settings/ | |||||
*.sublime-workspace | |||||
# Visual Studio Code | |||||
.vscode/* | |||||
!.vscode/settings.json | |||||
!.vscode/tasks.json | |||||
!.vscode/launch.json | |||||
!.vscode/extensions.json | |||||
.history/* | |||||
# Miscellaneous | |||||
/.angular/cache | |||||
.sass-cache/ | |||||
/connect.lock | |||||
/coverage | |||||
/libpeerconnection.log | |||||
testem.log | |||||
/typings | |||||
# System files | |||||
.DS_Store | |||||
Thumbs.db |
@ -0,0 +1,4 @@ | |||||
{ | |||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 | |||||
"recommendations": ["angular.ng-template"] | |||||
} |
@ -0,0 +1,19 @@ | |||||
{ | |||||
"version": "0.2.0", | |||||
"configurations": [ | |||||
{ | |||||
"type": "edge", | |||||
"request": "launch", | |||||
"name": "localhost (Edge)", | |||||
"url": "https://localhost:56902", | |||||
"webRoot": "${workspaceFolder}" | |||||
}, | |||||
{ | |||||
"type": "chrome", | |||||
"request": "launch", | |||||
"name": "localhost (Chrome)", | |||||
"url": "https://localhost:56902", | |||||
"webRoot": "${workspaceFolder}" | |||||
} | |||||
] | |||||
} |
@ -0,0 +1,42 @@ | |||||
{ | |||||
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 | |||||
"version": "2.0.0", | |||||
"tasks": [ | |||||
{ | |||||
"type": "npm", | |||||
"script": "start", | |||||
"isBackground": true, | |||||
"problemMatcher": { | |||||
"owner": "typescript", | |||||
"pattern": "$tsc", | |||||
"background": { | |||||
"activeOnStart": true, | |||||
"beginsPattern": { | |||||
"regexp": "(.*?)" | |||||
}, | |||||
"endsPattern": { | |||||
"regexp": "bundle generation complete" | |||||
} | |||||
} | |||||
} | |||||
}, | |||||
{ | |||||
"type": "npm", | |||||
"script": "test", | |||||
"isBackground": true, | |||||
"problemMatcher": { | |||||
"owner": "typescript", | |||||
"pattern": "$tsc", | |||||
"background": { | |||||
"activeOnStart": true, | |||||
"beginsPattern": { | |||||
"regexp": "(.*?)" | |||||
}, | |||||
"endsPattern": { | |||||
"regexp": "bundle generation complete" | |||||
} | |||||
} | |||||
} | |||||
} | |||||
] | |||||
} |
@ -0,0 +1,24 @@ | |||||
This file explains how Visual Studio created the project. | |||||
The following tools were used to generate this project: | |||||
- Angular CLI (ng) | |||||
The following steps were used to generate this project: | |||||
- Create Angular project with ng: `ng new awesomemicroservices.client --defaults --skip-install --skip-git --no-standalone `. | |||||
- Add `proxy.conf.js` to proxy calls to the backend ASP.NET server. | |||||
- Add `aspnetcore-https.js` script to install https certs. | |||||
- Update `package.json` to call `aspnetcore-https.js` and serve with https. | |||||
- Update `angular.json` to point to `proxy.conf.js`. | |||||
- Update `app.component.ts` component to fetch and display weather information. | |||||
- Modify `app.component.spec.ts` with updated tests. | |||||
- Update `app.module.ts` to import the HttpClientModule. | |||||
- Create project file (`awesomemicroservices.client.esproj`). | |||||
- Create `launch.json` to enable debugging. | |||||
- Update package.json to add `jest-editor-support`. | |||||
- Update package.json to add `run-script-os`. | |||||
- Add `karma.conf.js` for unit tests. | |||||
- Update `angular.json` to point to `karma.conf.js`. | |||||
- Add project to solution. | |||||
- Update proxy endpoint to be the backend server endpoint. | |||||
- Add project to the startup projects list. | |||||
- Write this file. |
@ -0,0 +1,27 @@ | |||||
# AwesomemicroservicesClient | |||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 18.2.8. | |||||
## Development server | |||||
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. | |||||
## Code scaffolding | |||||
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. | |||||
## Build | |||||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. | |||||
## Running unit tests | |||||
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). | |||||
## Running end-to-end tests | |||||
Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. | |||||
## Further help | |||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page. |
@ -0,0 +1,111 @@ | |||||
{ | |||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json", | |||||
"version": 1, | |||||
"newProjectRoot": "projects", | |||||
"projects": { | |||||
"awesomemicroservices.client": { | |||||
"projectType": "application", | |||||
"schematics": { | |||||
"@schematics/angular:component": { | |||||
"standalone": false | |||||
}, | |||||
"@schematics/angular:directive": { | |||||
"standalone": false | |||||
}, | |||||
"@schematics/angular:pipe": { | |||||
"standalone": false | |||||
} | |||||
}, | |||||
"root": "", | |||||
"sourceRoot": "src", | |||||
"prefix": "app", | |||||
"architect": { | |||||
"build": { | |||||
"builder": "@angular-devkit/build-angular:application", | |||||
"options": { | |||||
"outputPath": "dist/awesomemicroservices.client", | |||||
"index": "src/index.html", | |||||
"browser": "src/main.ts", | |||||
"polyfills": [ | |||||
"zone.js" | |||||
], | |||||
"tsConfig": "tsconfig.app.json", | |||||
"assets": [ | |||||
{ | |||||
"glob": "**/*", | |||||
"input": "public" | |||||
} | |||||
], | |||||
"styles": [ | |||||
"src/styles.css" | |||||
], | |||||
"scripts": [] | |||||
}, | |||||
"configurations": { | |||||
"production": { | |||||
"budgets": [ | |||||
{ | |||||
"type": "initial", | |||||
"maximumWarning": "500kB", | |||||
"maximumError": "1MB" | |||||
}, | |||||
{ | |||||
"type": "anyComponentStyle", | |||||
"maximumWarning": "2kB", | |||||
"maximumError": "4kB" | |||||
} | |||||
], | |||||
"outputHashing": "all" | |||||
}, | |||||
"development": { | |||||
"optimization": false, | |||||
"extractLicenses": false, | |||||
"sourceMap": true | |||||
} | |||||
}, | |||||
"defaultConfiguration": "production" | |||||
}, | |||||
"serve": { | |||||
"builder": "@angular-devkit/build-angular:dev-server", | |||||
"configurations": { | |||||
"production": { | |||||
"buildTarget": "awesomemicroservices.client:build:production" | |||||
}, | |||||
"development": { | |||||
"buildTarget": "awesomemicroservices.client:build:development" | |||||
} | |||||
}, | |||||
"defaultConfiguration": "development", | |||||
"options": { | |||||
"proxyConfig": "src/proxy.conf.js", | |||||
"port": 56902 | |||||
} | |||||
}, | |||||
"extract-i18n": { | |||||
"builder": "@angular-devkit/build-angular:extract-i18n" | |||||
}, | |||||
"test": { | |||||
"builder": "@angular-devkit/build-angular:karma", | |||||
"options": { | |||||
"polyfills": [ | |||||
"zone.js", | |||||
"zone.js/testing" | |||||
], | |||||
"tsConfig": "tsconfig.spec.json", | |||||
"assets": [ | |||||
{ | |||||
"glob": "**/*", | |||||
"input": "public" | |||||
} | |||||
], | |||||
"styles": [ | |||||
"src/styles.css" | |||||
], | |||||
"scripts": [], | |||||
"karmaConfig": "karma.conf.js" | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,37 @@ | |||||
// This script sets up HTTPS for the application using the ASP.NET Core HTTPS certificate | |||||
const fs = require('fs'); | |||||
const spawn = require('child_process').spawn; | |||||
const path = require('path'); | |||||
const baseFolder = | |||||
process.env.APPDATA !== undefined && process.env.APPDATA !== '' | |||||
? `${process.env.APPDATA}/ASP.NET/https` | |||||
: `${process.env.HOME}/.aspnet/https`; | |||||
const certificateArg = process.argv.map(arg => arg.match(/--name=(?<value>.+)/i)).filter(Boolean)[0]; | |||||
const certificateName = certificateArg ? certificateArg.groups.value : process.env.npm_package_name; | |||||
if (!certificateName) { | |||||
console.error('Invalid certificate name. Run this script in the context of an npm/yarn script or pass --name=<<app>> explicitly.') | |||||
process.exit(-1); | |||||
} | |||||
const certFilePath = path.join(baseFolder, `${certificateName}.pem`); | |||||
const keyFilePath = path.join(baseFolder, `${certificateName}.key`); | |||||
if (!fs.existsSync(baseFolder)) { | |||||
fs.mkdirSync(baseFolder, { recursive: true }); | |||||
} | |||||
if (!fs.existsSync(certFilePath) || !fs.existsSync(keyFilePath)) { | |||||
spawn('dotnet', [ | |||||
'dev-certs', | |||||
'https', | |||||
'--export-path', | |||||
certFilePath, | |||||
'--format', | |||||
'Pem', | |||||
'--no-password', | |||||
], { stdio: 'inherit', }) | |||||
.on('exit', (code) => process.exit(code)); | |||||
} |
@ -0,0 +1,10 @@ | |||||
<Project Sdk="Microsoft.VisualStudio.JavaScript.Sdk/1.0.1738743"> | |||||
<PropertyGroup> | |||||
<StartupCommand>npm start</StartupCommand> | |||||
<JavaScriptTestFramework>Jasmine</JavaScriptTestFramework> | |||||
<!-- Allows the build (or compile) script located on package.json to run on Build --> | |||||
<ShouldRunBuildScript>false</ShouldRunBuildScript> | |||||
<!-- Folder where production build objects will be placed --> | |||||
<BuildOutputFolder>$(MSBuildProjectDirectory)\dist\awesomemicroservices.client\browser\</BuildOutputFolder> | |||||
</PropertyGroup> | |||||
</Project> |
@ -0,0 +1,44 @@ | |||||
module.exports = function (config) { | |||||
config.set({ | |||||
basePath: '', | |||||
frameworks: ['jasmine', '@angular-devkit/build-angular'], | |||||
plugins: [ | |||||
require('karma-jasmine'), | |||||
require('karma-chrome-launcher'), | |||||
require('karma-jasmine-html-reporter'), | |||||
require('karma-coverage'), | |||||
require('@angular-devkit/build-angular/plugins/karma') | |||||
], | |||||
client: { | |||||
jasmine: { | |||||
// you can add configuration options for Jasmine here | |||||
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html | |||||
// for example, you can disable the random execution with `random: false` | |||||
// or set a specific seed with `seed: 4321` | |||||
}, | |||||
clearContext: false // leave Jasmine Spec Runner output visible in browser | |||||
}, | |||||
jasmineHtmlReporter: { | |||||
suppressAll: true // removes the duplicated traces | |||||
}, | |||||
coverageReporter: { | |||||
dir: require('path').join(__dirname, './coverage/'), | |||||
subdir: '.', | |||||
reporters: [ | |||||
{ type: 'html' }, | |||||
{ type: 'text-summary' } | |||||
] | |||||
}, | |||||
reporters: ['progress', 'kjhtml'], | |||||
port: 9876, | |||||
colors: true, | |||||
logLevel: config.LOG_INFO, | |||||
autoWatch: true, | |||||
browsers: ['Chrome'], | |||||
singleRun: false, | |||||
restartOnFileChange: true, | |||||
listenAddress: 'localhost', | |||||
hostname: 'localhost' | |||||
}); | |||||
}; | |||||
@ -0,0 +1,43 @@ | |||||
{ | |||||
"name": "awesomemicroservices.client", | |||||
"version": "0.0.0", | |||||
"scripts": { | |||||
"ng": "ng", | |||||
"start": "run-script-os", | |||||
"build": "ng build", | |||||
"watch": "ng build --watch --configuration development", | |||||
"test": "ng test", | |||||
"prestart": "node aspnetcore-https", | |||||
"start:windows": "ng serve --ssl --ssl-cert \"%APPDATA%\\ASP.NET\\https\\%npm_package_name%.pem\" --ssl-key \"%APPDATA%\\ASP.NET\\https\\%npm_package_name%.key\" --host=127.0.0.1", | |||||
"start:default": "ng serve --ssl --ssl-cert \"$HOME/.aspnet/https/${npm_package_name}.pem\" --ssl-key \"$HOME/.aspnet/https/${npm_package_name}.key\" --host=127.0.0.1" | |||||
}, | |||||
"private": true, | |||||
"dependencies": { | |||||
"@angular/animations": "^18.2.0", | |||||
"@angular/common": "^18.2.0", | |||||
"@angular/compiler": "^18.2.0", | |||||
"@angular/core": "^18.2.0", | |||||
"@angular/forms": "^18.2.0", | |||||
"@angular/platform-browser": "^18.2.0", | |||||
"@angular/platform-browser-dynamic": "^18.2.0", | |||||
"@angular/router": "^18.2.0", | |||||
"rxjs": "~7.8.0", | |||||
"tslib": "^2.3.0", | |||||
"zone.js": "~0.14.10", | |||||
"jest-editor-support": "*", | |||||
"run-script-os": "*" | |||||
}, | |||||
"devDependencies": { | |||||
"@angular-devkit/build-angular": "^18.2.8", | |||||
"@angular/cli": "^18.2.8", | |||||
"@angular/compiler-cli": "^18.2.0", | |||||
"@types/jasmine": "~5.1.0", | |||||
"jasmine-core": "~5.2.0", | |||||
"karma": "~6.4.0", | |||||
"karma-chrome-launcher": "~3.2.0", | |||||
"karma-coverage": "~2.2.0", | |||||
"karma-jasmine": "~5.1.0", | |||||
"karma-jasmine-html-reporter": "~2.1.0", | |||||
"typescript": "~5.5.2" | |||||
} | |||||
} |
@ -0,0 +1,10 @@ | |||||
import { NgModule } from '@angular/core'; | |||||
import { RouterModule, Routes } from '@angular/router'; | |||||
const routes: Routes = []; | |||||
@NgModule({ | |||||
imports: [RouterModule.forRoot(routes)], | |||||
exports: [RouterModule] | |||||
}) | |||||
export class AppRoutingModule { } |
@ -0,0 +1,14 @@ | |||||
:host { | |||||
max-width: 1280px; | |||||
padding: 2rem; | |||||
text-align: center; | |||||
} | |||||
th, td { | |||||
padding-left: 1rem; | |||||
padding-right: 1rem; | |||||
} | |||||
table { | |||||
margin: 0 auto; | |||||
} |
@ -0,0 +1,24 @@ | |||||
<h1 id="tableLabel">Weather forecast</h1> | |||||
<p>This component demonstrates fetching data from the server.</p> | |||||
<p *ngIf="!forecasts"><em>Loading... Please refresh once the ASP.NET backend has started. See <a href="https://aka.ms/jspsintegrationangular">https://aka.ms/jspsintegrationangular</a> for more details.</em></p> | |||||
<table *ngIf="forecasts"> | |||||
<thead> | |||||
<tr> | |||||
<th>Date</th> | |||||
<th>Temp. (C)</th> | |||||
<th>Temp. (F)</th> | |||||
<th>Summary</th> | |||||
</tr> | |||||
</thead> | |||||
<tbody> | |||||
<tr *ngFor="let forecast of forecasts"> | |||||
<td>{{ forecast.date }}</td> | |||||
<td>{{ forecast.temperatureC }}</td> | |||||
<td>{{ forecast.temperatureF }}</td> | |||||
<td>{{ forecast.summary }}</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> |
@ -0,0 +1,45 @@ | |||||
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; | |||||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||||
import { AppComponent } from './app.component'; | |||||
describe('AppComponent', () => { | |||||
let component: AppComponent; | |||||
let fixture: ComponentFixture<AppComponent>; | |||||
let httpMock: HttpTestingController; | |||||
beforeEach(async () => { | |||||
await TestBed.configureTestingModule({ | |||||
declarations: [AppComponent], | |||||
imports: [HttpClientTestingModule] | |||||
}).compileComponents(); | |||||
}); | |||||
beforeEach(() => { | |||||
fixture = TestBed.createComponent(AppComponent); | |||||
component = fixture.componentInstance; | |||||
httpMock = TestBed.inject(HttpTestingController); | |||||
}); | |||||
afterEach(() => { | |||||
httpMock.verify(); | |||||
}); | |||||
it('should create the app', () => { | |||||
expect(component).toBeTruthy(); | |||||
}); | |||||
it('should retrieve weather forecasts from the server', () => { | |||||
const mockForecasts = [ | |||||
{ date: '2021-10-01', temperatureC: 20, temperatureF: 68, summary: 'Mild' }, | |||||
{ date: '2021-10-02', temperatureC: 25, temperatureF: 77, summary: 'Warm' } | |||||
]; | |||||
component.ngOnInit(); | |||||
const req = httpMock.expectOne('/weatherforecast'); | |||||
expect(req.request.method).toEqual('GET'); | |||||
req.flush(mockForecasts); | |||||
expect(component.forecasts).toEqual(mockForecasts); | |||||
}); | |||||
}); |
@ -0,0 +1,37 @@ | |||||
import { HttpClient } from '@angular/common/http'; | |||||
import { Component, OnInit } from '@angular/core'; | |||||
interface WeatherForecast { | |||||
date: string; | |||||
temperatureC: number; | |||||
temperatureF: number; | |||||
summary: string; | |||||
} | |||||
@Component({ | |||||
selector: 'app-root', | |||||
templateUrl: './app.component.html', | |||||
styleUrl: './app.component.css' | |||||
}) | |||||
export class AppComponent implements OnInit { | |||||
public forecasts: WeatherForecast[] = []; | |||||
constructor(private http: HttpClient) {} | |||||
ngOnInit() { | |||||
this.getForecasts(); | |||||
} | |||||
getForecasts() { | |||||
this.http.get<WeatherForecast[]>('/weatherforecast').subscribe( | |||||
(result) => { | |||||
this.forecasts = result; | |||||
}, | |||||
(error) => { | |||||
console.error(error); | |||||
} | |||||
); | |||||
} | |||||
title = 'awesomemicroservices.client'; | |||||
} |
@ -0,0 +1,19 @@ | |||||
import { HttpClientModule } from '@angular/common/http'; | |||||
import { NgModule } from '@angular/core'; | |||||
import { BrowserModule } from '@angular/platform-browser'; | |||||
import { AppRoutingModule } from './app-routing.module'; | |||||
import { AppComponent } from './app.component'; | |||||
@NgModule({ | |||||
declarations: [ | |||||
AppComponent | |||||
], | |||||
imports: [ | |||||
BrowserModule, HttpClientModule, | |||||
AppRoutingModule | |||||
], | |||||
providers: [], | |||||
bootstrap: [AppComponent] | |||||
}) | |||||
export class AppModule { } |
@ -0,0 +1,13 @@ | |||||
<!doctype html> | |||||
<html lang="en"> | |||||
<head> | |||||
<meta charset="utf-8"> | |||||
<title>AwesomemicroservicesClient</title> | |||||
<base href="/"> | |||||
<meta name="viewport" content="width=device-width, initial-scale=1"> | |||||
<link rel="icon" type="image/x-icon" href="favicon.ico"> | |||||
</head> | |||||
<body> | |||||
<app-root></app-root> | |||||
</body> | |||||
</html> |
@ -0,0 +1,8 @@ | |||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; | |||||
import { AppModule } from './app/app.module'; | |||||
platformBrowserDynamic().bootstrapModule(AppModule, { | |||||
ngZoneEventCoalescing: true | |||||
}) | |||||
.catch(err => console.error(err)); |
@ -0,0 +1,16 @@ | |||||
const { env } = require('process'); | |||||
const target = env.ASPNETCORE_HTTPS_PORT ? `https://localhost:${env.ASPNETCORE_HTTPS_PORT}` : | |||||
env.ASPNETCORE_URLS ? env.ASPNETCORE_URLS.split(';')[0] : 'https://localhost:7223'; | |||||
const PROXY_CONFIG = [ | |||||
{ | |||||
context: [ | |||||
"/weatherforecast", | |||||
], | |||||
target, | |||||
secure: false | |||||
} | |||||
] | |||||
module.exports = PROXY_CONFIG; |
@ -0,0 +1 @@ | |||||
/* You can add global styles to this file, and also import other style files */ |
@ -0,0 +1,15 @@ | |||||
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ | |||||
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ | |||||
{ | |||||
"extends": "./tsconfig.json", | |||||
"compilerOptions": { | |||||
"outDir": "./out-tsc/app", | |||||
"types": [] | |||||
}, | |||||
"files": [ | |||||
"src/main.ts" | |||||
], | |||||
"include": [ | |||||
"src/**/*.d.ts" | |||||
] | |||||
} |
@ -0,0 +1,33 @@ | |||||
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ | |||||
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ | |||||
{ | |||||
"compileOnSave": false, | |||||
"compilerOptions": { | |||||
"outDir": "./dist/out-tsc", | |||||
"strict": true, | |||||
"noImplicitOverride": true, | |||||
"noPropertyAccessFromIndexSignature": true, | |||||
"noImplicitReturns": true, | |||||
"noFallthroughCasesInSwitch": true, | |||||
"skipLibCheck": true, | |||||
"isolatedModules": true, | |||||
"esModuleInterop": true, | |||||
"sourceMap": true, | |||||
"declaration": false, | |||||
"experimentalDecorators": true, | |||||
"moduleResolution": "bundler", | |||||
"importHelpers": true, | |||||
"target": "ES2022", | |||||
"module": "ES2022", | |||||
"lib": [ | |||||
"ES2022", | |||||
"dom" | |||||
] | |||||
}, | |||||
"angularCompilerOptions": { | |||||
"enableI18nLegacyMessageIdFormat": false, | |||||
"strictInjectionParameters": true, | |||||
"strictInputAccessModifiers": true, | |||||
"strictTemplates": true | |||||
} | |||||
} |
@ -0,0 +1,15 @@ | |||||
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ | |||||
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ | |||||
{ | |||||
"extends": "./tsconfig.json", | |||||
"compilerOptions": { | |||||
"outDir": "./out-tsc/spec", | |||||
"types": [ | |||||
"jasmine" | |||||
] | |||||
}, | |||||
"include": [ | |||||
"src/**/*.spec.ts", | |||||
"src/**/*.d.ts" | |||||
] | |||||
} |
@ -0,0 +1,30 @@ | |||||
| |||||
Microsoft Visual Studio Solution File, Format Version 12.00 | |||||
# Visual Studio Version 17 | |||||
VisualStudioVersion = 17.12.35527.113 d17.12 | |||||
MinimumVisualStudioVersion = 10.0.40219.1 | |||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AwesomeMicroservices.Server", "AwesomeMicroservices\AwesomeMicroservices.Server\AwesomeMicroservices.Server.csproj", "{758C914B-C1D9-46E2-95F6-CDE1E282E283}" | |||||
EndProject | |||||
Project("{54A90642-561A-4BB1-A94E-469ADEE60C69}") = "awesomemicroservices.client", "AwesomeMicroservices\awesomemicroservices.client\awesomemicroservices.client.esproj", "{32A7249B-E416-4273-85AB-E8411FE0C8CA}" | |||||
EndProject | |||||
Global | |||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||||
Debug|Any CPU = Debug|Any CPU | |||||
Release|Any CPU = Release|Any CPU | |||||
EndGlobalSection | |||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | |||||
{758C914B-C1D9-46E2-95F6-CDE1E282E283}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
{758C914B-C1D9-46E2-95F6-CDE1E282E283}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
{758C914B-C1D9-46E2-95F6-CDE1E282E283}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
{758C914B-C1D9-46E2-95F6-CDE1E282E283}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
{32A7249B-E416-4273-85AB-E8411FE0C8CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
{32A7249B-E416-4273-85AB-E8411FE0C8CA}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
{32A7249B-E416-4273-85AB-E8411FE0C8CA}.Debug|Any CPU.Deploy.0 = Debug|Any CPU | |||||
{32A7249B-E416-4273-85AB-E8411FE0C8CA}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
{32A7249B-E416-4273-85AB-E8411FE0C8CA}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
{32A7249B-E416-4273-85AB-E8411FE0C8CA}.Release|Any CPU.Deploy.0 = Release|Any CPU | |||||
EndGlobalSection | |||||
GlobalSection(SolutionProperties) = preSolution | |||||
HideSolutionNode = FALSE | |||||
EndGlobalSection | |||||
EndGlobal |
@ -0,0 +1 @@ | |||||
# AwesomeMicroservicesSolution |