├── .gitignore ├── ApiGateways └── Ocelot.ApiGateway │ ├── Dockerfile │ ├── Ocelot.ApiGateway.csproj │ ├── Ocelot.ApiGateway.http │ ├── Program.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ └── ocelot.Development.json ├── Deployments ├── helm │ ├── basket │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── configmap.yaml │ │ │ ├── deployment.yaml │ │ │ ├── hpa.yaml │ │ │ ├── service.yaml │ │ │ └── tests │ │ │ │ └── test-connection.yaml │ │ └── values.yaml │ ├── basketdb │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── deployment.yaml │ │ │ ├── service.yaml │ │ │ └── tests │ │ │ │ └── test-connection.yaml │ │ └── values.yaml │ ├── catalog │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── configmap.yaml │ │ │ ├── deployment.yaml │ │ │ ├── hpa.yaml │ │ │ ├── service.yaml │ │ │ └── tests │ │ │ │ └── test-connection.yaml │ │ └── values.yaml │ ├── catalogdb │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── deployment.yaml │ │ │ ├── service.yaml │ │ │ └── tests │ │ │ │ └── test-connection.yaml │ │ └── values.yaml │ ├── discount │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── configmap.yaml │ │ │ ├── deployment.yaml │ │ │ ├── hpa.yaml │ │ │ ├── service.yaml │ │ │ └── tests │ │ │ │ └── test-connection.yaml │ │ └── values.yaml │ ├── discountdb │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── deployment.yaml │ │ │ ├── service.yaml │ │ │ └── tests │ │ │ │ └── test-connection.yaml │ │ └── values.yaml │ ├── elasticsearch │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── deployment.yaml │ │ │ ├── service.yaml │ │ │ └── tests │ │ │ │ └── test-connection.yaml │ │ └── values.yaml │ ├── install-helm.ps1 │ ├── kibana │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── deployment.yaml │ │ │ ├── service.yaml │ │ │ └── tests │ │ │ │ └── test-connection.yaml │ │ └── values.yaml │ ├── ocelotapigw │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── configmap.yaml │ │ │ ├── deployment.yaml │ │ │ ├── service.yaml │ │ │ └── tests │ │ │ │ └── test-connection.yaml │ │ └── values.yaml │ ├── orderdb │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── deployment.yaml │ │ │ ├── service.yaml │ │ │ └── tests │ │ │ │ └── test-connection.yaml │ │ └── values.yaml │ ├── ordering │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── configmap.yaml │ │ │ ├── deployment.yaml │ │ │ ├── hpa.yaml │ │ │ ├── service.yaml │ │ │ └── tests │ │ │ │ └── test-connection.yaml │ │ └── values.yaml │ ├── rabbitmq │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── templates │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── deployment.yaml │ │ │ ├── service.yaml │ │ │ └── tests │ │ │ │ └── test-connection.yaml │ │ └── values.yaml │ └── uninstall-helm.ps1 ├── istio │ ├── istio-init.yaml │ ├── istio-minikube.yaml │ └── kiali-secret.yaml └── k8s │ ├── catalog │ ├── catalog-api │ │ └── catalog-api.yaml │ └── catalog-db │ │ ├── catalog-db.yaml │ │ ├── mongo-configmap.yaml │ │ └── mongo-secret.yaml │ └── ingress │ └── ingress.yaml ├── Ecommerce.sln ├── Infrastructure ├── Common.Logging │ ├── Common.Logging.csproj │ └── Logging.cs └── EventBus.Messages │ ├── Common │ └── EventBusConstant.cs │ ├── EventBus.Messages.csproj │ └── Events │ ├── BaseIntegrationEvent.cs │ ├── BasketCheckoutEvent.cs │ └── BasketCheckoutEventV2.cs ├── Services ├── Basket │ ├── Basket.API │ │ ├── Basket.API.csproj │ │ ├── Basket.API.http │ │ ├── Controllers │ │ │ ├── ApiController.cs │ │ │ ├── BasketController.cs │ │ │ └── V2 │ │ │ │ └── BasketController.cs │ │ ├── Dockerfile │ │ ├── Program.cs │ │ ├── appsettings.Development.json │ │ └── appsettings.json │ ├── Basket.Application │ │ ├── Basket.Application.csproj │ │ ├── Commands │ │ │ ├── CreateShoppingCartCommand.cs │ │ │ └── DeleteBasketByUserNameCommand.cs │ │ ├── GrpcService │ │ │ └── DiscountGrpcService.cs │ │ ├── Handlers │ │ │ ├── CreateShoppingCartCommandHandler.cs │ │ │ ├── DeleteBasketByUserNameHandler.cs │ │ │ └── GetBasketByUserNameHandler.cs │ │ ├── Mappers │ │ │ ├── BasketMapper.cs │ │ │ └── BasketMappingProfile.cs │ │ ├── Queries │ │ │ └── GetBasketByUserNameQuery.cs │ │ └── Responses │ │ │ ├── ShoppingCartItemResponse.cs │ │ │ └── ShoppingCartResponse.cs │ ├── Basket.Core │ │ ├── Basket.Core.csproj │ │ ├── Entities │ │ │ ├── BasketCheckout.cs │ │ │ ├── BasketCheckoutV2.cs │ │ │ ├── ShoppingCart.cs │ │ │ └── ShoppingCartItem.cs │ │ └── Repositories │ │ │ └── IBasketRepository.cs │ └── Basket.Infrastructure │ │ ├── Basket.Infrastructure.csproj │ │ └── Repositories │ │ └── BasketRepository.cs ├── Catalog │ ├── Catalog.API │ │ ├── Catalog.API.csproj │ │ ├── Catalog.API.http │ │ ├── Controllers │ │ │ ├── ApiController.cs │ │ │ └── CatalogController.cs │ │ ├── Dockerfile │ │ ├── Program.cs │ │ ├── appsettings.Development.json │ │ └── appsettings.json │ ├── Catalog.Application │ │ ├── Catalog.Application.csproj │ │ ├── Commands │ │ │ ├── CreateProductCommand.cs │ │ │ ├── DeleteProductByIdCommand.cs │ │ │ └── UpdateProductCommand.cs │ │ ├── Handlers │ │ │ ├── CreateProductCommandHandler.cs │ │ │ ├── DeleteProductByIDCommandHandler.cs │ │ │ ├── GetAllBrandsHandler.cs │ │ │ ├── GetAllProductsHandler.cs │ │ │ ├── GetAllTypesHandler.cs │ │ │ ├── GetProductByBrandHandler.cs │ │ │ ├── GetProductByIdQueryHandler.cs │ │ │ ├── GetProductByNameQueryHandler.cs │ │ │ └── UpdateProductCommandHandler.cs │ │ ├── Mappers │ │ │ ├── ProductMapper.cs │ │ │ └── ProductMappingProfile.cs │ │ ├── Queries │ │ │ ├── GetAllBrandsQuery.cs │ │ │ ├── GetAllProductsQuery.cs │ │ │ ├── GetAllTypesQuery.cs │ │ │ ├── GetProductByBrandQuery.cs │ │ │ ├── GetProductByIdQuery.cs │ │ │ └── GetProductByNameQuery.cs │ │ └── Responses │ │ │ ├── BrandResponse.cs │ │ │ ├── ProductResponse.cs │ │ │ └── TypesResponse.cs │ ├── Catalog.Core │ │ ├── Catalog.Core.csproj │ │ ├── Entities │ │ │ ├── BaseEntity.cs │ │ │ ├── Product.cs │ │ │ ├── ProductBrand.cs │ │ │ └── ProductType.cs │ │ ├── Repositories │ │ │ ├── IBrandRepository.cs │ │ │ ├── IProductRepository.cs │ │ │ └── ITypesRepository.cs │ │ └── Specs │ │ │ ├── CatalogSpecParams.cs │ │ │ └── Pagination.cs │ └── Catalog.Infrastructure │ │ ├── Catalog.Infrastructure.csproj │ │ ├── Data │ │ ├── BrandContextSeed.cs │ │ ├── CatalogContext.cs │ │ ├── CatalogContextSeed.cs │ │ ├── ICatalogContext.cs │ │ ├── SeedData │ │ │ ├── brands.json │ │ │ ├── products.json │ │ │ └── types.json │ │ └── TypeContextSeed.cs │ │ └── Repositories │ │ └── ProductRepository.cs ├── Discount │ ├── Discount.API │ │ ├── Discount.API.csproj │ │ ├── Discount.API.http │ │ ├── Dockerfile │ │ ├── Program.cs │ │ ├── Services │ │ │ └── DiscountService.cs │ │ ├── appsettings.Development.json │ │ └── appsettings.json │ ├── Discount.Application │ │ ├── Commands │ │ │ ├── CreateDiscountCommand.cs │ │ │ ├── DeleteDiscountCommand.cs │ │ │ └── UpdateDiscountCommand.cs │ │ ├── Discount.Application.csproj │ │ ├── Handlers │ │ │ ├── CreateDiscountCommandHandler.cs │ │ │ ├── DeleteDiscountCommandHandler.cs │ │ │ ├── GetDiscountQueryHandler.cs │ │ │ └── UpdateDiscountCommandHandler.cs │ │ ├── Mapper │ │ │ └── DiscountProfile.cs │ │ ├── Protos │ │ │ └── discount.proto │ │ └── Queries │ │ │ └── GetDiscountQuery.cs │ ├── Discount.Core │ │ ├── Discount.Core.csproj │ │ ├── Entities │ │ │ └── Coupon.cs │ │ └── Repositories │ │ │ └── IDiscountRepository.cs │ └── Discount.Infrastructure │ │ ├── Discount.Infrastructure.csproj │ │ ├── Extensions │ │ └── DbExtension.cs │ │ └── Repositories │ │ └── DiscountRepository.cs └── Ordering │ ├── Ordering.API │ ├── Controllers │ │ ├── ApiController.cs │ │ └── OrderController.cs │ ├── Dockerfile │ ├── EventBusConsumer │ │ ├── BasketOrderingConsumer.cs │ │ └── BasketOrderingConsumerV2.cs │ ├── Extensions │ │ └── DbExtension.cs │ ├── Ordering.API.csproj │ ├── Ordering.API.http │ ├── Program.cs │ ├── appsettings.Development.json │ └── appsettings.json │ ├── Ordering.Application │ ├── Behaviour │ │ ├── UnhandledExceptionBehaviour.cs │ │ └── ValidationBehaviour.cs │ ├── Commands │ │ ├── CheckoutOrderCommand.cs │ │ ├── CheckoutOrderCommandV2.cs │ │ ├── DeleteOrderCommand.cs │ │ └── UpdateOrderCommand.cs │ ├── Exceptions │ │ ├── OrderNotFoundException.cs │ │ └── ValidationException.cs │ ├── Extensions │ │ └── ServiceRegistration.cs │ ├── Handlers │ │ ├── CheckoutOrderCommandHandler.cs │ │ ├── CheckoutOrderCommandV2Handler.cs │ │ ├── DeleteOrderCommandHandler.cs │ │ ├── GetOrderListQueryHandler.cs │ │ └── UpdateOrderCommandHandler.cs │ ├── Mappers │ │ └── OrderMappingProfile.cs │ ├── Ordering.Application.csproj │ ├── Queries │ │ └── GetOrderListQuery.cs │ ├── Responses │ │ └── OrderResponse.cs │ └── Validators │ │ ├── CheckoutOrderCommandValidator.cs │ │ ├── CheckoutOrderCommandValidatorV2.cs │ │ └── UpdateOrderCommandValidator.cs │ ├── Ordering.Core │ ├── Common │ │ └── EntityBase.cs │ ├── Entities │ │ └── Order.cs │ ├── Ordering.Core.csproj │ └── Repositories │ │ ├── IAsyncRepository.cs │ │ └── IOrderRepository.cs │ └── Ordering.Infrastructure │ ├── Data │ ├── OrderContext.cs │ ├── OrderContextFactory.cs │ └── OrderContextSeed.cs │ ├── Extensions │ └── InfraServices.cs │ ├── Migrations │ ├── 20240725154011_InitialCreate.Designer.cs │ ├── 20240725154011_InitialCreate.cs │ └── OrderContextModelSnapshot.cs │ ├── Ordering.Infrastructure.csproj │ └── Repositories │ ├── OrderRepository.cs │ └── RepositoryBase.cs ├── client ├── .editorconfig ├── .gitignore ├── .vscode │ ├── extensions.json │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── README.md ├── angular.json ├── package-lock.json ├── package.json ├── src │ ├── app │ │ ├── account │ │ │ ├── account.module.ts │ │ │ ├── acnt.service.ts │ │ │ ├── base.service.ts │ │ │ └── constants.ts │ │ ├── app-routing.module.ts │ │ ├── app.component.html │ │ ├── app.component.scss │ │ ├── app.component.spec.ts │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── basket │ │ │ ├── basket-routing.module.ts │ │ │ ├── basket.component.html │ │ │ ├── basket.component.scss │ │ │ ├── basket.component.ts │ │ │ ├── basket.module.ts │ │ │ └── basket.service.ts │ │ ├── checkout │ │ │ ├── checkout-routing.module.ts │ │ │ ├── checkout.component.html │ │ │ ├── checkout.component.scss │ │ │ ├── checkout.component.ts │ │ │ ├── checkout.module.ts │ │ │ └── checkout.service.ts │ │ ├── core │ │ │ ├── core.module.ts │ │ │ ├── guards │ │ │ │ ├── auth.guard.ts │ │ │ │ └── sample.guard.ts │ │ │ ├── header │ │ │ │ ├── header.component.html │ │ │ │ ├── header.component.scss │ │ │ │ └── header.component.ts │ │ │ ├── interceptors │ │ │ │ ├── error.interceptor.ts │ │ │ │ └── loading.interceptor.ts │ │ │ ├── navbar │ │ │ │ ├── navbar.component.html │ │ │ │ ├── navbar.component.scss │ │ │ │ └── navbar.component.ts │ │ │ ├── not-found │ │ │ │ ├── not-found.component.html │ │ │ │ ├── not-found.component.scss │ │ │ │ └── not-found.component.ts │ │ │ ├── server-error │ │ │ │ ├── server-error.component.html │ │ │ │ ├── server-error.component.scss │ │ │ │ └── server-error.component.ts │ │ │ ├── services │ │ │ │ └── loading.service.ts │ │ │ └── un-authenticated │ │ │ │ ├── un-authenticated.component.html │ │ │ │ ├── un-authenticated.component.scss │ │ │ │ └── un-authenticated.component.ts │ │ ├── home │ │ │ ├── home.component.html │ │ │ ├── home.component.scss │ │ │ ├── home.component.ts │ │ │ └── home.module.ts │ │ ├── shared │ │ │ ├── models │ │ │ │ ├── basket.ts │ │ │ │ ├── brand.ts │ │ │ │ ├── pagination.ts │ │ │ │ ├── product.ts │ │ │ │ ├── storeParams.ts │ │ │ │ └── type.ts │ │ │ ├── order-summary │ │ │ │ ├── order-summary.component.html │ │ │ │ ├── order-summary.component.scss │ │ │ │ └── order-summary.component.ts │ │ │ └── shared.module.ts │ │ └── store │ │ │ ├── product-details │ │ │ ├── product-details.component.html │ │ │ ├── product-details.component.scss │ │ │ └── product-details.component.ts │ │ │ ├── product-items │ │ │ ├── product-items.component.html │ │ │ ├── product-items.component.scss │ │ │ └── product-items.component.ts │ │ │ ├── store-routing.module.ts │ │ │ ├── store.component.html │ │ │ ├── store.component.scss │ │ │ ├── store.component.ts │ │ │ ├── store.module.ts │ │ │ └── store.service.ts │ ├── assets │ │ ├── .gitkeep │ │ ├── images │ │ │ ├── bslide1.jpg │ │ │ ├── bslide2.jpg │ │ │ ├── bslide3.jpg │ │ │ ├── hero1.jpg │ │ │ ├── hero2.jpg │ │ │ ├── hero3.jpg │ │ │ ├── hero4.jpg │ │ │ ├── hero5.jpg │ │ │ ├── hero6.jpg │ │ │ ├── logo.png │ │ │ ├── logo_old.png │ │ │ └── open-identity.png │ │ ├── js │ │ │ └── oidc-client.min.js │ │ └── silent-callback.html │ ├── favicon.ico │ ├── images │ │ └── products │ │ │ ├── Nike-Football-1.png │ │ │ ├── Nike-Football-2.png │ │ │ ├── Nike-Football-3.png │ │ │ ├── adidas_football-1.png │ │ │ ├── adidas_football-2.png │ │ │ ├── adidas_football-3.png │ │ │ ├── adidas_shoe-1.png │ │ │ ├── adidas_shoe-2.png │ │ │ ├── adidas_shoe-3.png │ │ │ ├── asics_shoe-1.png │ │ │ ├── asics_shoe-2.png │ │ │ ├── asics_shoe-3.png │ │ │ ├── babolat-kitback-1.png │ │ │ ├── babolat-kitback-2.png │ │ │ ├── babolat-kitback-3.png │ │ │ ├── babolat-racket-1.png │ │ │ ├── babolat-racket-2.png │ │ │ ├── babolat-racket-3.png │ │ │ ├── babolat.png │ │ │ ├── babolat_shoe-1.png │ │ │ ├── babolat_shoe-2.png │ │ │ ├── babolat_shoe-3.png │ │ │ ├── puma_shoe-1.png │ │ │ ├── puma_shoe-2.png │ │ │ ├── puma_shoe-3.png │ │ │ ├── victor-racket-1.png │ │ │ ├── victor-racket-2.png │ │ │ ├── victor-racket-3.png │ │ │ ├── victor_shoe-1.png │ │ │ ├── victor_shoe-2.png │ │ │ ├── yonex-badminton-1.png │ │ │ ├── yonex-badminton-2.png │ │ │ ├── yonex-badminton-3.png │ │ │ ├── yonex-kitback-1.png │ │ │ ├── yonex-kitback-2.png │ │ │ ├── yonex-kitback-3.png │ │ │ ├── yonex-racket-1.png │ │ │ ├── yonex-racket-2.png │ │ │ ├── yonex-racket-3.png │ │ │ ├── yonex_shoe-1.png │ │ │ ├── yonex_shoe-2.png │ │ │ └── yonex_shoe-3.png │ ├── index.html │ ├── main.ts │ ├── polyfills.ts │ └── styles.scss ├── target │ └── npmlist.json ├── tsconfig.app.json ├── tsconfig.json └── tsconfig.spec.json ├── docker-compose.dcproj ├── docker-compose.override.yml ├── docker-compose.yml ├── launchSettings.json └── readme.md /ApiGateways/Ocelot.ApiGateway/Dockerfile: -------------------------------------------------------------------------------- 1 | #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. 2 | 3 | FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base 4 | USER app 5 | WORKDIR /app 6 | EXPOSE 8080 7 | 8 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build 9 | ARG BUILD_CONFIGURATION=Release 10 | WORKDIR /src 11 | COPY ["ApiGateways/Ocelot.ApiGateway/Ocelot.ApiGateway.csproj", "ApiGateways/Ocelot.ApiGateway/"] 12 | RUN dotnet restore "./ApiGateways/Ocelot.ApiGateway/Ocelot.ApiGateway.csproj" 13 | COPY . . 14 | WORKDIR "/src/ApiGateways/Ocelot.ApiGateway" 15 | RUN dotnet build "./Ocelot.ApiGateway.csproj" -c $BUILD_CONFIGURATION -o /app/build 16 | 17 | FROM build AS publish 18 | ARG BUILD_CONFIGURATION=Release 19 | RUN dotnet publish "./Ocelot.ApiGateway.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false 20 | 21 | FROM base AS final 22 | WORKDIR /app 23 | COPY --from=publish /app/publish . 24 | ENTRYPOINT ["dotnet", "Ocelot.ApiGateway.dll"] -------------------------------------------------------------------------------- /ApiGateways/Ocelot.ApiGateway/Ocelot.ApiGateway.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | Linux 8 | ..\.. 9 | ..\..\docker-compose.dcproj 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ApiGateways/Ocelot.ApiGateway/Ocelot.ApiGateway.http: -------------------------------------------------------------------------------- 1 | @Ocelot.ApiGateway_HostAddress = http://localhost:5210 2 | 3 | GET {{Ocelot.ApiGateway_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /ApiGateways/Ocelot.ApiGateway/Program.cs: -------------------------------------------------------------------------------- 1 | using Ocelot.DependencyInjection; 2 | using Ocelot.Middleware; 3 | 4 | var builder = WebApplication.CreateBuilder(args); 5 | 6 | // Add services to the container. 7 | builder.Services.AddCors(options => 8 | { 9 | options.AddPolicy("CorsPolicy", policy => 10 | { 11 | policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin(); 12 | }); 13 | }); 14 | //ocelot configuration 15 | builder.Host.ConfigureAppConfiguration((env, config) => 16 | { 17 | config.AddJsonFile($"ocelot.{env.HostingEnvironment.EnvironmentName}.json", true, true); 18 | }); 19 | builder.Services.AddControllers(); 20 | // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle 21 | builder.Services.AddEndpointsApiExplorer(); 22 | builder.Services.AddSwaggerGen(); 23 | builder.Services.AddOcelot(); 24 | 25 | var app = builder.Build(); 26 | 27 | // Configure the HTTP request pipeline. 28 | if (app.Environment.IsDevelopment()) 29 | { 30 | app.UseSwagger(); 31 | app.UseSwaggerUI(); 32 | } 33 | app.UseRouting(); 34 | app.UseCors("CorsPolicy"); 35 | app.UseAuthorization(); 36 | 37 | app.MapControllers(); 38 | 39 | app.UseEndpoints(endpoints => 40 | { 41 | endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Hello Ocelot"); }); 42 | }); 43 | 44 | await app.UseOcelot(); 45 | await app.RunAsync(); 46 | -------------------------------------------------------------------------------- /ApiGateways/Ocelot.ApiGateway/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /ApiGateways/Ocelot.ApiGateway/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /Deployments/helm/basket/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /Deployments/helm/basket/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: basket 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /Deployments/helm/basket/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- $name := include "basket.fullname" . -}} 2 | 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: "cfg-{{ $name }}" 7 | labels: 8 | app: {{ template "basket.name" . }} 9 | chart: {{ template "basket.chart" .}} 10 | release: {{ .Release.Name }} 11 | heritage: {{ .Release.Service }} 12 | data: 13 | EventBusSettings__HostAddress: amqp://guest:guest@rabbitmq:5672 14 | CacheSettings__ConnectionString: basketdb:6379 15 | GrpcSettings__DiscountUrl: http://discountapi 16 | ElasticConfiguration__Uri: http://elasticsearch:9200 -------------------------------------------------------------------------------- /Deployments/helm/basket/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "basket.fullname" . }} 6 | labels: 7 | {{- include "basket.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "basket.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | target: 21 | type: Utilization 22 | averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 23 | {{- end }} 24 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 25 | - type: Resource 26 | resource: 27 | name: memory 28 | target: 29 | type: Utilization 30 | averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 31 | {{- end }} 32 | {{- end }} 33 | -------------------------------------------------------------------------------- /Deployments/helm/basket/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "basket.fullname" . }} 5 | labels: 6 | {{- include "basket.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "basket.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /Deployments/helm/basket/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "basket.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "basket.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "basket.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /Deployments/helm/basketdb/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /Deployments/helm/basketdb/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: basketdb 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /Deployments/helm/basketdb/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "basketdb.fullname" . }} 5 | labels: 6 | {{- include "basketdb.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "basketdb.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /Deployments/helm/basketdb/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "basketdb.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "basketdb.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "basketdb.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /Deployments/helm/catalog/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /Deployments/helm/catalog/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: catalog 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /Deployments/helm/catalog/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- $name := include "catalog.fullname" . -}} 2 | 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: "cfg-{{ $name }}" 7 | labels: 8 | app: {{ template "catalog.name" . }} 9 | chart: {{ template "catalog.chart" .}} 10 | release: {{ .Release.Name }} 11 | heritage: {{ .Release.Service }} 12 | data: 13 | DatabaseSettings__ConnectionString: mongodb://catalogdb:27017 14 | DatabaseSettings__DatabaseName: CatalogDb 15 | DatabaseSettings__CollectionName: Products 16 | DatabaseSettings__BrandsCollection: Brands 17 | DatabaseSettings__TypesCollection: Types 18 | ElasticConfiguration__Uri: http://elasticsearch:9200 -------------------------------------------------------------------------------- /Deployments/helm/catalog/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "catalog.fullname" . }} 6 | labels: 7 | {{- include "catalog.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "catalog.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | target: 21 | type: Utilization 22 | averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 23 | {{- end }} 24 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 25 | - type: Resource 26 | resource: 27 | name: memory 28 | target: 29 | type: Utilization 30 | averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 31 | {{- end }} 32 | {{- end }} 33 | -------------------------------------------------------------------------------- /Deployments/helm/catalog/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "catalog.fullname" . }} 5 | labels: 6 | {{- include "catalog.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "catalog.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /Deployments/helm/catalog/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "catalog.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "catalog.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "catalog.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /Deployments/helm/catalogdb/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /Deployments/helm/catalogdb/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: catalogdb 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /Deployments/helm/catalogdb/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "catalogdb.fullname" . }} 5 | labels: 6 | {{- include "catalogdb.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "catalogdb.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /Deployments/helm/catalogdb/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "catalogdb.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "catalogdb.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "catalogdb.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /Deployments/helm/discount/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /Deployments/helm/discount/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: discount-grpc 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /Deployments/helm/discount/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- $name := include "discount-grpc.fullname" . -}} 2 | 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: "cfg-{{ $name }}" 7 | labels: 8 | app: {{ template "discount-grpc.name" . }} 9 | chart: {{ template "discount-grpc.chart" .}} 10 | release: {{ .Release.Name }} 11 | heritage: {{ .Release.Service }} 12 | data: 13 | DatabaseSettings__ConnectionString: Server=discountdb;Port=5432;Database=DiscountDb;User Id=admin;Password=Password@1; 14 | ElasticConfiguration__Uri: http://elasticsearch:9200 -------------------------------------------------------------------------------- /Deployments/helm/discount/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "discount-grpc.fullname" . }} 6 | labels: 7 | {{- include "discount-grpc.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "discount-grpc.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | target: 21 | type: Utilization 22 | averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 23 | {{- end }} 24 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 25 | - type: Resource 26 | resource: 27 | name: memory 28 | target: 29 | type: Utilization 30 | averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 31 | {{- end }} 32 | {{- end }} 33 | -------------------------------------------------------------------------------- /Deployments/helm/discount/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "discount-grpc.fullname" . }} 5 | labels: 6 | {{- include "discount-grpc.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "discount-grpc.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /Deployments/helm/discount/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "discount-grpc.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "discount-grpc.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "discount-grpc.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /Deployments/helm/discountdb/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /Deployments/helm/discountdb/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: discountdb 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /Deployments/helm/discountdb/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "discountdb.fullname" . }} 5 | labels: 6 | {{- include "discountdb.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "discountdb.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /Deployments/helm/discountdb/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "discountdb.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "discountdb.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "discountdb.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /Deployments/helm/elasticsearch/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /Deployments/helm/elasticsearch/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: elasticsearch 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /Deployments/helm/elasticsearch/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "elasticsearch.fullname" . }} 5 | labels: 6 | {{- include "elasticsearch.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "elasticsearch.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /Deployments/helm/elasticsearch/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "elasticsearch.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "elasticsearch.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "elasticsearch.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /Deployments/helm/install-helm.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [parameter(Mandatory=$false)][string]$appName="eshopping" 3 | ) 4 | 5 | function Install-Chart { 6 | Param([string]$chart, [string]$initialOptions) 7 | $options=$initialOptions 8 | 9 | $cmd = "helm install $appName-$chart $chart $options" 10 | Write-Host "Helm Command: $cmd" -ForegroundColor Gray 11 | Invoke-Expression $cmd 12 | } 13 | 14 | 15 | Write-Host "Installation using Helm started" -ForegroundColor Green 16 | 17 | $infras = ("basketdb", "catalogdb", "discountdb", "elasticsearch", "kibana", "orderdb", "rabbitmq") 18 | $apis = ("basket","catalog", "ordering", "discount") 19 | # $gateways = ("ocelotapigw") 20 | 21 | 22 | foreach ($infra in $infras) { 23 | Write-Host "Installing: $infra" -ForegroundColor Green 24 | Write-Host "$infra" 25 | Install-Chart $infra 26 | } 27 | 28 | foreach ($api in $apis) { 29 | Write-Host "Installing: $api" -ForegroundColor Green 30 | Install-Chart $api 31 | } 32 | 33 | # foreach ($gateway in $gateways) { 34 | # Write-Host "Installing: $gateway" -ForegroundColor Green 35 | # Install-Chart $gateway 36 | # } 37 | 38 | Write-Host "helm charts installed." -ForegroundColor Green -------------------------------------------------------------------------------- /Deployments/helm/kibana/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /Deployments/helm/kibana/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: kibana 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /Deployments/helm/kibana/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "kibana.fullname" . }} 5 | labels: 6 | {{- include "kibana.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "kibana.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /Deployments/helm/kibana/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "kibana.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "kibana.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "kibana.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /Deployments/helm/ocelotapigw/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /Deployments/helm/ocelotapigw/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: ocelotapigw 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /Deployments/helm/ocelotapigw/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- $name := include "ocelotapigw.fullname" . -}} 2 | 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: "cfg-{{ $name }}" 7 | labels: 8 | app: {{ template "ocelotapigw.name" . }} 9 | chart: {{ template "ocelotapigw.chart" .}} 10 | release: {{ .Release.Name }} 11 | heritage: {{ .Release.Service }} 12 | data: 13 | ElasticConfiguration: Uri=http://elasticsearch:9200 -------------------------------------------------------------------------------- /Deployments/helm/ocelotapigw/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "ocelotapigw.fullname" . }} 5 | labels: 6 | {{- include "ocelotapigw.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "ocelotapigw.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /Deployments/helm/ocelotapigw/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "ocelotapigw.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "ocelotapigw.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "ocelotapigw.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /Deployments/helm/orderdb/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /Deployments/helm/orderdb/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: orderdb 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /Deployments/helm/orderdb/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "orderdb.fullname" . }} 5 | labels: 6 | {{- include "orderdb.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "orderdb.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /Deployments/helm/orderdb/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "orderdb.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "orderdb.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "orderdb.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /Deployments/helm/ordering/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /Deployments/helm/ordering/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: ordering 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /Deployments/helm/ordering/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- $name := include "ordering.fullname" . -}} 2 | 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: "cfg-{{ $name }}" 7 | labels: 8 | app: {{ template "ordering.name" . }} 9 | chart: {{ template "ordering.chart" .}} 10 | release: {{ .Release.Name }} 11 | heritage: {{ .Release.Service }} 12 | data: 13 | ConnectionStrings__OrderingConnectionString: Server=orderdb;Database=OrderDb;User Id=sa;Password=Rahul1234567 14 | ElasticConfiguration__Uri: http://elasticsearch:9200 15 | EventBusSettings__HostAddress: amqp://guest:guest@rabbitmq:5672 -------------------------------------------------------------------------------- /Deployments/helm/ordering/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "ordering.fullname" . }} 6 | labels: 7 | {{- include "ordering.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "ordering.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | target: 21 | type: Utilization 22 | averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 23 | {{- end }} 24 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 25 | - type: Resource 26 | resource: 27 | name: memory 28 | target: 29 | type: Utilization 30 | averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 31 | {{- end }} 32 | {{- end }} 33 | -------------------------------------------------------------------------------- /Deployments/helm/ordering/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "ordering.fullname" . }} 5 | labels: 6 | {{- include "ordering.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "ordering.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /Deployments/helm/ordering/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "ordering.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "ordering.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "ordering.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /Deployments/helm/rabbitmq/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /Deployments/helm/rabbitmq/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: rabbitmq 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /Deployments/helm/rabbitmq/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "rabbitmq.fullname" . }} 5 | labels: 6 | {{- include "rabbitmq.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "rabbitmq.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /Deployments/helm/rabbitmq/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "rabbitmq.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "rabbitmq.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "rabbitmq.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /Deployments/helm/uninstall-helm.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [parameter(Mandatory=$false)][string]$appName="eshopping" 3 | ) 4 | 5 | Write-Host "Starting Helm Uninstallation" -ForegroundColor Green 6 | 7 | # Uninstallation Process 8 | 9 | $listOfComponents=$(helm ls --filter $appName -q) 10 | if ([string]::IsNullOrEmpty($listOfComponents)) { 11 | Write-Host "No previous installation found!!!" -ForegroundColor Green 12 | }else{ 13 | Write-Host "Found previous releases!!!" -ForegroundColor Green 14 | Write-Host "Removing previous helm releases..." -ForegroundColor Green 15 | helm uninstall $listOfComponents 16 | 17 | Write-Host "Removed previous releases" -ForegroundColor Green 18 | } 19 | 20 | 21 | -------------------------------------------------------------------------------- /Deployments/istio/kiali-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | type: Opaque 4 | metadata: 5 | name: kiali 6 | namespace: istio-system 7 | labels: 8 | app: kiali 9 | data: 10 | username: YWRtaW4= 11 | passphrase: YWRtaW4= 12 | -------------------------------------------------------------------------------- /Deployments/k8s/catalog/catalog-db/catalog-db.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: mongo-deployment 5 | labels: 6 | app: mongodb 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: mongodb 12 | template: 13 | metadata: 14 | labels: 15 | app: mongodb 16 | spec: 17 | containers: 18 | - name: mongodb 19 | image: mongo 20 | ports: 21 | - containerPort: 27017 22 | resources: 23 | requests: 24 | memory: "2Gi" 25 | cpu: "500m" 26 | limits: 27 | memory: "2Gi" 28 | cpu: "500m" 29 | env: 30 | - name: MONGO_INITDB_ROOT_USERNAME 31 | valueFrom: 32 | secretKeyRef: 33 | name: mongo-secret 34 | key: mongo-root-username 35 | - name: MONGO_INITDB_ROOT_PASSWORD 36 | valueFrom: 37 | secretKeyRef: 38 | name: mongo-secret 39 | key: mongo-root-password 40 | --- 41 | apiVersion: v1 42 | kind: Service 43 | metadata: 44 | name: mongo-service 45 | spec: 46 | selector: 47 | app: mongodb 48 | ports: 49 | - protocol: TCP 50 | port: 27017 51 | targetPort: 27017 -------------------------------------------------------------------------------- /Deployments/k8s/catalog/catalog-db/mongo-configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: mongo-configmap 5 | data: 6 | connection_string: mongodb://username:password@mongo-service:27017 7 | DatabaseName: CatalogDb 8 | CollectionName: Products 9 | BrandsCollection: Brands 10 | TypesCollection: Types -------------------------------------------------------------------------------- /Deployments/k8s/catalog/catalog-db/mongo-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: mongo-secret 5 | type: Opaque 6 | data: 7 | mongo-root-username: dXNlcm5hbWU= 8 | mongo-root-password: cGFzc3dvcmQ= -------------------------------------------------------------------------------- /Deployments/k8s/ingress/ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | name: eshopping-ingress 5 | annotations: 6 | nginx.ingress.kubernetes.io/rewrite-target: / 7 | spec: 8 | rules: 9 | - host: api-local.eshopping.com 10 | http: 11 | paths: 12 | - path: / 13 | pathType: Prefix 14 | backend: 15 | service: 16 | name: ocelotapigw 17 | port: 18 | number: 80 -------------------------------------------------------------------------------- /Infrastructure/Common.Logging/Common.Logging.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Infrastructure/EventBus.Messages/Common/EventBusConstant.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus.Messages.Common 2 | { 3 | public class EventBusConstant 4 | { 5 | public const string BasketCheckoutQueue = "basketcheckout-queue"; 6 | public const string BasketCheckoutQueueV2 = "basketcheckout-queue-v2"; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Infrastructure/EventBus.Messages/EventBus.Messages.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Infrastructure/EventBus.Messages/Events/BaseIntegrationEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus.Messages.Common 2 | { 3 | public class BaseIntegrationEvent 4 | { 5 | public string CorrelationId { get; set; } 6 | public DateTime CreationDate { get; private set; } 7 | public BaseIntegrationEvent() 8 | { 9 | CorrelationId = Guid.NewGuid().ToString(); 10 | CreationDate = DateTime.UtcNow; 11 | } 12 | public BaseIntegrationEvent(Guid corelationId, DateTime creationDate) 13 | { 14 | CorrelationId = corelationId.ToString(); 15 | CreationDate = creationDate; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Infrastructure/EventBus.Messages/Events/BasketCheckoutEvent.cs: -------------------------------------------------------------------------------- 1 | namespace EventBus.Messages.Common 2 | { 3 | public class BasketCheckoutEvent : BaseIntegrationEvent 4 | { 5 | public string? UserName { get; set; } 6 | public decimal? TotalPrice { get; set; } 7 | 8 | public string? FirstName { get; set; } 9 | public string? LastName { get; set; } 10 | public string? EmailAddress { get; set; } 11 | public string? AddressLine { get; set; } 12 | public string? Country { get; set; } 13 | public string? State { get; set; } 14 | public string? ZipCode { get; set; } 15 | 16 | public string? CardName { get; set; } 17 | public string? CardNumber { get; set; } 18 | public string? Expiration { get; set; } 19 | public string? Cvv { get; set; } 20 | public int? PaymentMethod { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Infrastructure/EventBus.Messages/Events/BasketCheckoutEventV2.cs: -------------------------------------------------------------------------------- 1 | using EventBus.Messages.Common; 2 | 3 | namespace EventBus.Messages.Events 4 | { 5 | public class BasketCheckoutEventV2 : BaseIntegrationEvent 6 | { 7 | public string? UserName { get; set; } 8 | public decimal? TotalPrice { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Services/Basket/Basket.API/Basket.API.http: -------------------------------------------------------------------------------- 1 | @Basket.API_HostAddress = http://localhost:5286 2 | 3 | GET {{Basket.API_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /Services/Basket/Basket.API/Controllers/ApiController.cs: -------------------------------------------------------------------------------- 1 | using Asp.Versioning; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace Basket.API.Controllers 5 | { 6 | [Route("api/v{version:apiVersion}/[controller]")] 7 | [ApiController] 8 | public class ApiController : ControllerBase 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Services/Basket/Basket.API/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Services/Basket/Basket.API/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "CacheSettings": { 3 | "ConnectionString": "localhost:6379" 4 | }, 5 | "GrpcSettings": { 6 | "DiscountUrl": "http://localhost:8002" 7 | }, 8 | "EventBusSettings": { 9 | "HostAddress": "amqp://guest:guest@localhost:5672" 10 | }, 11 | "ElasticConfiguration": { 12 | "Uri": "http://localhost:9200" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Application/Basket.Application.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Protos\discount.proto 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Application/Commands/CreateShoppingCartCommand.cs: -------------------------------------------------------------------------------- 1 | using Basket.Application.Responses; 2 | using Basket.Core.Entities; 3 | using MediatR; 4 | 5 | namespace Basket.Application.Commands 6 | { 7 | public class CreateShoppingCartCommand : IRequest 8 | { 9 | public string UserName { get; set; } 10 | public List Items { get; set; } 11 | public CreateShoppingCartCommand(string username, List items) 12 | { 13 | UserName = username; 14 | Items = items; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Application/Commands/DeleteBasketByUserNameCommand.cs: -------------------------------------------------------------------------------- 1 | using MediatR; 2 | 3 | namespace Basket.Application.Commands 4 | { 5 | public class DeleteBasketByUserNameCommand : IRequest 6 | { 7 | public string UserName { get; set; } 8 | public DeleteBasketByUserNameCommand(string userName) 9 | { 10 | UserName = userName; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Application/GrpcService/DiscountGrpcService.cs: -------------------------------------------------------------------------------- 1 | using Discount.Grpc.Protos; 2 | 3 | namespace Basket.Application.GrpcService 4 | { 5 | public class DiscountGrpcService 6 | { 7 | private readonly DiscountProtoService.DiscountProtoServiceClient _discountProtoServiceClient; 8 | 9 | public DiscountGrpcService(DiscountProtoService.DiscountProtoServiceClient discountProtoServiceClient) 10 | { 11 | _discountProtoServiceClient = discountProtoServiceClient; 12 | } 13 | 14 | public async Task GetDiscount(string productName) 15 | { 16 | var discountRequest = new GetDiscountRequest { ProductName = productName }; 17 | return await _discountProtoServiceClient.GetDiscountAsync(discountRequest); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Application/Handlers/DeleteBasketByUserNameHandler.cs: -------------------------------------------------------------------------------- 1 | using Basket.Application.Commands; 2 | using Basket.Core.Repositories; 3 | using MediatR; 4 | 5 | namespace Basket.Application.Handlers 6 | { 7 | public class DeleteBasketByUserNameHandler : IRequestHandler 8 | { 9 | private readonly IBasketRepository _basketRepository; 10 | 11 | public DeleteBasketByUserNameHandler(IBasketRepository basketRepository) 12 | { 13 | _basketRepository = basketRepository; 14 | } 15 | public async Task Handle(DeleteBasketByUserNameCommand request, CancellationToken cancellationToken) 16 | { 17 | await _basketRepository.DeleteBasket(request.UserName); 18 | return Unit.Value; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Application/Handlers/GetBasketByUserNameHandler.cs: -------------------------------------------------------------------------------- 1 | using Basket.Application.Mappers; 2 | using Basket.Application.Queries; 3 | using Basket.Application.Responses; 4 | using Basket.Core.Repositories; 5 | using MediatR; 6 | 7 | namespace Basket.Application.Handlers 8 | { 9 | public class GetBasketByUserNameHandler : IRequestHandler 10 | { 11 | private readonly IBasketRepository _basketRepository; 12 | 13 | public GetBasketByUserNameHandler(IBasketRepository basketRepository) 14 | { 15 | _basketRepository = basketRepository; 16 | } 17 | public async Task Handle(GetBasketByUserNameQuery request, CancellationToken cancellationToken) 18 | { 19 | var shoppingCart = await _basketRepository.GetBasket(request.UserName); 20 | var shoppingCartResponse = BasketMapper.Mapper.Map(shoppingCart); 21 | return shoppingCartResponse; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Application/Mappers/BasketMapper.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | 3 | namespace Basket.Application.Mappers 4 | { 5 | public static class BasketMapper 6 | { 7 | private static readonly Lazy Lazy = new Lazy(() => 8 | { 9 | var config = new MapperConfiguration(cfg => 10 | { 11 | cfg.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly; 12 | cfg.AddProfile(); 13 | }); 14 | var mapper = config.CreateMapper(); 15 | return mapper; 16 | }); 17 | public static IMapper Mapper => Lazy.Value; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Application/Mappers/BasketMappingProfile.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Basket.Application.Responses; 3 | using Basket.Core.Entities; 4 | using EventBus.Messages.Common; 5 | using EventBus.Messages.Events; 6 | 7 | namespace Basket.Application.Mappers 8 | { 9 | public class BasketMappingProfile : Profile 10 | { 11 | public BasketMappingProfile() 12 | { 13 | CreateMap().ReverseMap(); 14 | CreateMap().ReverseMap(); 15 | CreateMap().ReverseMap(); 16 | CreateMap().ReverseMap(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Application/Queries/GetBasketByUserNameQuery.cs: -------------------------------------------------------------------------------- 1 | using Basket.Application.Responses; 2 | using MediatR; 3 | 4 | namespace Basket.Application.Queries 5 | { 6 | public class GetBasketByUserNameQuery : IRequest 7 | { 8 | public string UserName { get; set; } 9 | public GetBasketByUserNameQuery(string userName) 10 | { 11 | UserName = userName; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Application/Responses/ShoppingCartItemResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Basket.Application.Responses 2 | { 3 | public class ShoppingCartItemResponse 4 | { 5 | public int Quantity { get; set; } 6 | public string ImageFile { get; set; } 7 | public decimal Price { get; set; } 8 | public string ProductId { get; set; } 9 | public string ProductName { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Application/Responses/ShoppingCartResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Basket.Application.Responses 2 | { 3 | public class ShoppingCartResponse 4 | { 5 | public string UserName { get; set; } 6 | public List Items { get; set; } 7 | public ShoppingCartResponse() 8 | { 9 | 10 | } 11 | public ShoppingCartResponse(string username) 12 | { 13 | UserName = username; 14 | } 15 | public decimal TotalPrice 16 | { 17 | get 18 | { 19 | decimal totalPrice = 0; 20 | foreach (var item in Items) 21 | { 22 | totalPrice += item.Price * item.Quantity; 23 | } 24 | return totalPrice; 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Core/Basket.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Core/Entities/BasketCheckout.cs: -------------------------------------------------------------------------------- 1 | namespace Basket.Core.Entities 2 | { 3 | public class BasketCheckout 4 | { 5 | public string UserName { get; set; } 6 | public decimal TotalPrice { get; set; } 7 | 8 | public string FirstName { get; set; } 9 | public string LastName { get; set; } 10 | public string EmailAddress { get; set; } 11 | public string AddressLine { get; set; } 12 | public string Country { get; set; } 13 | public string State { get; set; } 14 | public string ZipCode { get; set; } 15 | 16 | public string CardName { get; set; } 17 | public string CardNumber { get; set; } 18 | public string Expiration { get; set; } 19 | public string Cvv { get; set; } 20 | public int PaymentMethod { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Core/Entities/BasketCheckoutV2.cs: -------------------------------------------------------------------------------- 1 | namespace Basket.Core.Entities 2 | { 3 | public class BasketCheckoutV2 4 | { 5 | public string UserName { get; set; } 6 | public decimal TotalPrice { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Core/Entities/ShoppingCart.cs: -------------------------------------------------------------------------------- 1 | namespace Basket.Core.Entities 2 | { 3 | public class ShoppingCart 4 | { 5 | public string UserName { get; set; } 6 | public List Items { get; set; } = new List(); 7 | public ShoppingCart() 8 | { 9 | 10 | } 11 | public ShoppingCart(string userName) 12 | { 13 | UserName = userName; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Core/Entities/ShoppingCartItem.cs: -------------------------------------------------------------------------------- 1 | namespace Basket.Core.Entities 2 | { 3 | public class ShoppingCartItem 4 | { 5 | public int Quantity { get; set; } 6 | public decimal Price { get; set; } 7 | public string ProductId { get; set; } 8 | public string ImageFile { get; set; } 9 | public string ProductName { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Core/Repositories/IBasketRepository.cs: -------------------------------------------------------------------------------- 1 | using Basket.Core.Entities; 2 | 3 | namespace Basket.Core.Repositories 4 | { 5 | public interface IBasketRepository 6 | { 7 | Task GetBasket(string userName); 8 | Task UpdateBasket(ShoppingCart shoppingCart); 9 | Task DeleteBasket(string userName); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Infrastructure/Basket.Infrastructure.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Services/Basket/Basket.Infrastructure/Repositories/BasketRepository.cs: -------------------------------------------------------------------------------- 1 | using Basket.Core.Entities; 2 | using Basket.Core.Repositories; 3 | using Microsoft.Extensions.Caching.Distributed; 4 | using Newtonsoft.Json; 5 | 6 | namespace Basket.Infrastructure.Repositories 7 | { 8 | public class BasketRepository : IBasketRepository 9 | { 10 | private readonly IDistributedCache _redisCache; 11 | 12 | public BasketRepository(IDistributedCache redisCache) 13 | { 14 | _redisCache = redisCache; 15 | } 16 | public async Task GetBasket(string userName) 17 | { 18 | var basket = await _redisCache.GetStringAsync(userName); 19 | if (string.IsNullOrEmpty(basket)) 20 | { 21 | return null; 22 | } 23 | return JsonConvert.DeserializeObject(basket); 24 | } 25 | 26 | public async Task UpdateBasket(ShoppingCart shoppingCart) 27 | { 28 | await _redisCache.SetStringAsync(shoppingCart.UserName, JsonConvert.SerializeObject(shoppingCart)); 29 | return await GetBasket(shoppingCart.UserName); 30 | } 31 | public async Task DeleteBasket(string userName) 32 | { 33 | await _redisCache.RemoveAsync(userName); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.API/Catalog.API.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | Linux 8 | ..\..\.. 9 | ..\..\..\docker-compose.dcproj 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.API/Catalog.API.http: -------------------------------------------------------------------------------- 1 | @Catalog.API_HostAddress = http://localhost:5032 2 | 3 | GET {{Catalog.API_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.API/Controllers/ApiController.cs: -------------------------------------------------------------------------------- 1 | using Asp.Versioning; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace Catalog.API.Controllers 5 | { 6 | [ApiVersion("1")] 7 | [Route("api/v{version:apiVersion}/[controller]")] 8 | [ApiController] 9 | public class ApiController : ControllerBase 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.API/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base 2 | USER app 3 | WORKDIR /app 4 | EXPOSE 8080 5 | EXPOSE 443 6 | 7 | FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build 8 | ARG BUILD_CONFIGURATION=Release 9 | WORKDIR /src 10 | COPY ["Services/Catalog/Catalog.API/Catalog.API.csproj", "Services/Catalog/Catalog.API/"] 11 | COPY ["Services/Catalog/Catalog.Application/Catalog.Application.csproj", "Services/Catalog/Catalog.Application/"] 12 | COPY ["Services/Catalog/Catalog.Core/Catalog.Core.csproj", "Services/Catalog/Catalog.Core/"] 13 | COPY ["Services/Catalog/Catalog.Infrastructure/Catalog.Infrastructure.csproj", "Services/Catalog/Catalog.Infrastructure/"] 14 | COPY ["Infrastructure/Common.Logging/Common.Logging.csproj", "Infrastructure/Common.Logging/"] 15 | RUN dotnet restore "./Services/Catalog/Catalog.API/Catalog.API.csproj" 16 | COPY . . 17 | WORKDIR "/src/Services/Catalog/Catalog.API" 18 | RUN dotnet build "./Catalog.API.csproj" -c $BUILD_CONFIGURATION -o /app/build 19 | 20 | FROM build AS publish 21 | ARG BUILD_CONFIGURATION=Release 22 | RUN dotnet publish "./Catalog.API.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false 23 | 24 | FROM base AS final 25 | WORKDIR /app 26 | COPY --from=publish /app/publish . 27 | ENTRYPOINT ["dotnet", "Catalog.API.dll"] 28 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.API/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.API/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "DatabaseSettings": { 3 | "ConnectionString": "mongodb://127.0.0.1:27017?readPreference=primary&ssl=false", 4 | "DatabaseName": "CatalogDb", 5 | "CollectionName": "Products", 6 | "BrandsCollection": "Brands", 7 | "TypesCollection": "Types" 8 | }, 9 | "ElasticConfiguration": { 10 | "Uri": "http://localhost:9200" 11 | } 12 | } -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Catalog.Application.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Commands/CreateProductCommand.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Application.Responses; 2 | using Catalog.Core.Entities; 3 | using MediatR; 4 | 5 | namespace Catalog.Application.Commands 6 | { 7 | public class CreateProductCommand : IRequest 8 | { 9 | public string Name { get; set; } 10 | public string Summary { get; set; } 11 | public string Description { get; set; } 12 | public string ImageFile { get; set; } 13 | public decimal Price { get; set; } 14 | public ProductBrand Brands { get; set; } 15 | public ProductType Types { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Commands/DeleteProductByIdCommand.cs: -------------------------------------------------------------------------------- 1 | using MediatR; 2 | 3 | namespace Catalog.Application.Commands 4 | { 5 | public class DeleteProductByIdCommand : IRequest 6 | { 7 | public string Id { get; set; } 8 | 9 | public DeleteProductByIdCommand(string id) 10 | { 11 | Id = id; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Commands/UpdateProductCommand.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Core.Entities; 2 | using MediatR; 3 | using MongoDB.Bson.Serialization.Attributes; 4 | using MongoDB.Bson; 5 | 6 | namespace Catalog.Application.Commands 7 | { 8 | public class UpdateProductCommand : IRequest 9 | { 10 | [BsonId] 11 | [BsonRepresentation(BsonType.ObjectId)] 12 | public string Id { get; set; } 13 | [BsonElement("Name")] 14 | public string Name { get; set; } 15 | public string Summary { get; set; } 16 | public string Description { get; set; } 17 | public string ImageFile { get; set; } 18 | public decimal Price { get; set; } 19 | public ProductBrand Brands { get; set; } 20 | public ProductType Types { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Handlers/CreateProductCommandHandler.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Application.Commands; 2 | using Catalog.Application.Mappers; 3 | using Catalog.Application.Responses; 4 | using Catalog.Core.Entities; 5 | using Catalog.Core.Repositories; 6 | using MediatR; 7 | 8 | namespace Catalog.Application.Handlers 9 | { 10 | public class CreateProductCommandHandler : IRequestHandler 11 | { 12 | private readonly IProductRepository _productRepository; 13 | 14 | public CreateProductCommandHandler(IProductRepository productRepository) 15 | { 16 | _productRepository = productRepository; 17 | } 18 | public async Task Handle(CreateProductCommand request, CancellationToken cancellationToken) 19 | { 20 | var productEntity = ProductMapper.Mapper.Map(request); 21 | if (productEntity is null) 22 | { 23 | throw new ApplicationException("There is an issue with mapping while creating new product"); 24 | } 25 | var newProduct = await _productRepository.CreateProduct(productEntity); 26 | var productResponse = ProductMapper.Mapper.Map(newProduct); 27 | return productResponse; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Handlers/DeleteProductByIDCommandHandler.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Application.Commands; 2 | using Catalog.Core.Repositories; 3 | using MediatR; 4 | 5 | namespace Catalog.Application.Handlers 6 | { 7 | public class DeleteProductByIDCommandHandler : IRequestHandler 8 | { 9 | private readonly IProductRepository _productRepository; 10 | 11 | public DeleteProductByIDCommandHandler(IProductRepository productRepository) 12 | { 13 | _productRepository = productRepository; 14 | } 15 | public async Task Handle(DeleteProductByIdCommand request, CancellationToken cancellationToken) 16 | { 17 | return await _productRepository.DeleteProduct(request.Id); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Handlers/GetAllBrandsHandler.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Catalog.Application.Mappers; 3 | using Catalog.Application.Queries; 4 | using Catalog.Application.Responses; 5 | using Catalog.Core.Entities; 6 | using Catalog.Core.Repositories; 7 | using MediatR; 8 | 9 | namespace Catalog.Application.Handlers 10 | { 11 | public class GetAllBrandsHandler : IRequestHandler> 12 | { 13 | private readonly IBrandRepository _brandRepository; 14 | 15 | public GetAllBrandsHandler(IBrandRepository brandRepository) 16 | { 17 | _brandRepository = brandRepository; 18 | } 19 | public async Task> Handle(GetAllBrandsQuery request, CancellationToken cancellationToken) 20 | { 21 | var brandList = await _brandRepository.GetAllBrands(); 22 | var brandResponseList = ProductMapper.Mapper.Map,IList>(brandList.ToList()); 23 | return brandResponseList; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Handlers/GetAllProductsHandler.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Application.Mappers; 2 | using Catalog.Application.Queries; 3 | using Catalog.Application.Responses; 4 | using Catalog.Core.Repositories; 5 | using Catalog.Core.Specs; 6 | using MediatR; 7 | 8 | namespace Catalog.Application.Handlers 9 | { 10 | public class GetAllProductsHandler : IRequestHandler> 11 | { 12 | private readonly IProductRepository _productRepository; 13 | 14 | public GetAllProductsHandler(IProductRepository productRepository) 15 | { 16 | _productRepository = productRepository; 17 | } 18 | public async Task> Handle(GetAllProductsQuery request, CancellationToken cancellationToken) 19 | { 20 | var productList = await _productRepository.GetProducts(request.CatalogSpecParams); 21 | var productResposeList = ProductMapper.Mapper.Map>(productList); 22 | return productResposeList; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Handlers/GetAllTypesHandler.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Application.Mappers; 2 | using Catalog.Application.Queries; 3 | using Catalog.Application.Responses; 4 | using Catalog.Core.Repositories; 5 | using MediatR; 6 | 7 | namespace Catalog.Application.Handlers 8 | { 9 | public class GetAllTypesHandler : IRequestHandler> 10 | { 11 | private readonly ITypesRepository _typesRepository; 12 | 13 | public GetAllTypesHandler(ITypesRepository typesRepository) 14 | { 15 | _typesRepository = typesRepository; 16 | } 17 | public async Task> Handle(GetAllTypesQuery request, CancellationToken cancellationToken) 18 | { 19 | var typesList = await _typesRepository.GetAllTypes(); 20 | var typesResponseList = ProductMapper.Mapper.Map>(typesList); 21 | return typesResponseList; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Handlers/GetProductByBrandHandler.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Application.Mappers; 2 | using Catalog.Application.Queries; 3 | using Catalog.Application.Responses; 4 | using Catalog.Core.Repositories; 5 | using MediatR; 6 | 7 | namespace Catalog.Application.Handlers 8 | { 9 | public class GetProductByBrandHandler : IRequestHandler> 10 | { 11 | private readonly IProductRepository _productRepository; 12 | 13 | public GetProductByBrandHandler(IProductRepository productRepository) 14 | { 15 | _productRepository = productRepository; 16 | } 17 | public async Task> Handle(GetProductByBrandQuery request, CancellationToken cancellationToken) 18 | { 19 | var productList = await _productRepository.GetProductsByBrand(request.BrandName); 20 | var productResponseList = ProductMapper.Mapper.Map>(productList); 21 | return productResponseList; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Handlers/GetProductByIdQueryHandler.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Application.Mappers; 2 | using Catalog.Application.Queries; 3 | using Catalog.Application.Responses; 4 | using Catalog.Core.Repositories; 5 | using MediatR; 6 | 7 | namespace Catalog.Application.Handlers 8 | { 9 | public class GetProductByIdQueryHandler : IRequestHandler 10 | { 11 | private readonly IProductRepository _productRepository; 12 | 13 | public GetProductByIdQueryHandler(IProductRepository productRepository) 14 | { 15 | _productRepository = productRepository; 16 | } 17 | public async Task Handle(GetProductByIdQuery request, CancellationToken cancellationToken) 18 | { 19 | var product = await _productRepository.GetProduct(request.Id); 20 | var productRespose = ProductMapper.Mapper.Map(product); 21 | return productRespose; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Handlers/GetProductByNameQueryHandler.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Application.Mappers; 2 | using Catalog.Application.Queries; 3 | using Catalog.Application.Responses; 4 | using Catalog.Core.Repositories; 5 | using MediatR; 6 | 7 | namespace Catalog.Application.Handlers 8 | { 9 | public class GetProductByNameQueryHandler : IRequestHandler> 10 | { 11 | private readonly IProductRepository _productRepository; 12 | 13 | public GetProductByNameQueryHandler(IProductRepository productRepository) 14 | { 15 | _productRepository = productRepository; 16 | } 17 | public async Task> Handle(GetProductByNameQuery request, CancellationToken cancellationToken) 18 | { 19 | var productList = await _productRepository.GetProductsByName(request.Name); 20 | var productResponseList = ProductMapper.Mapper.Map>(productList); 21 | return productResponseList; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Handlers/UpdateProductCommandHandler.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Application.Commands; 2 | using Catalog.Core.Entities; 3 | using Catalog.Core.Repositories; 4 | using MediatR; 5 | 6 | namespace Catalog.Application.Handlers 7 | { 8 | public class UpdateProductCommandHandler : IRequestHandler 9 | { 10 | private readonly IProductRepository _productRepository; 11 | 12 | public UpdateProductCommandHandler(IProductRepository productRepository) 13 | { 14 | _productRepository = productRepository; 15 | } 16 | public async Task Handle(UpdateProductCommand request, CancellationToken cancellationToken) 17 | { 18 | var productEntity = await _productRepository.UpdateProduct(new Product 19 | { 20 | Id = request.Id, 21 | Description = request.Description, 22 | ImageFile = request.ImageFile, 23 | Name = request.Name, 24 | Price = request.Price, 25 | Summary = request.Summary, 26 | Brands = request.Brands, 27 | Types = request.Types 28 | }); 29 | return true; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Mappers/ProductMapper.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | 3 | namespace Catalog.Application.Mappers 4 | { 5 | public static class ProductMapper 6 | { 7 | private static readonly Lazy Lazy = new Lazy(() => 8 | { 9 | var config = new MapperConfiguration(cfg => 10 | { 11 | cfg.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly; 12 | cfg.AddProfile(); 13 | }); 14 | var mapper = config.CreateMapper(); 15 | return mapper; 16 | }); 17 | 18 | public static IMapper Mapper => Lazy.Value; 19 | } 20 | } -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Mappers/ProductMappingProfile.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Catalog.Application.Commands; 3 | using Catalog.Application.Responses; 4 | using Catalog.Core.Entities; 5 | using Catalog.Core.Specs; 6 | 7 | namespace Catalog.Application.Mappers 8 | { 9 | public class ProductMappingProfile : Profile 10 | { 11 | public ProductMappingProfile() 12 | { 13 | CreateMap().ReverseMap(); 14 | CreateMap().ReverseMap(); 15 | CreateMap().ReverseMap(); 16 | CreateMap().ReverseMap(); 17 | CreateMap, Pagination>().ReverseMap(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Queries/GetAllBrandsQuery.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Application.Responses; 2 | using MediatR; 3 | 4 | namespace Catalog.Application.Queries 5 | { 6 | public class GetAllBrandsQuery : IRequest> 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Queries/GetAllProductsQuery.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Application.Responses; 2 | using Catalog.Core.Specs; 3 | using MediatR; 4 | 5 | namespace Catalog.Application.Queries 6 | { 7 | public class GetAllProductsQuery : IRequest> 8 | { 9 | public CatalogSpecParams CatalogSpecParams { get; set; } 10 | public GetAllProductsQuery(CatalogSpecParams catalogSpecParams) 11 | { 12 | CatalogSpecParams = catalogSpecParams; 13 | } 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Queries/GetAllTypesQuery.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Application.Responses; 2 | using MediatR; 3 | 4 | namespace Catalog.Application.Queries 5 | { 6 | public class GetAllTypesQuery : IRequest> 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Queries/GetProductByBrandQuery.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Application.Responses; 2 | using MediatR; 3 | 4 | namespace Catalog.Application.Queries 5 | { 6 | public class GetProductByBrandQuery : IRequest> 7 | { 8 | public string BrandName { get; set; } 9 | 10 | public GetProductByBrandQuery(string brandName) 11 | { 12 | BrandName = brandName; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Queries/GetProductByIdQuery.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Application.Responses; 2 | using MediatR; 3 | 4 | namespace Catalog.Application.Queries 5 | { 6 | public class GetProductByIdQuery : IRequest 7 | { 8 | public string Id { get; set; } 9 | public GetProductByIdQuery(string id) 10 | { 11 | Id = id; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Queries/GetProductByNameQuery.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Application.Responses; 2 | using MediatR; 3 | 4 | namespace Catalog.Application.Queries 5 | { 6 | public class GetProductByNameQuery : IRequest> 7 | { 8 | public string Name { get; set; } 9 | public GetProductByNameQuery(string name) 10 | { 11 | Name = name; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Responses/BrandResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Catalog.Application.Responses 2 | { 3 | public class BrandResponse 4 | { 5 | public string Id { get; set; } 6 | public string Name { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Responses/ProductResponse.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Core.Entities; 2 | using MongoDB.Bson.Serialization.Attributes; 3 | 4 | namespace Catalog.Application.Responses 5 | { 6 | public class ProductResponse 7 | { 8 | [BsonId] 9 | [BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)] 10 | public string Id { get; set; } 11 | [BsonElement("Name")] 12 | public string Name { get; set; } 13 | public string Summary { get; set; } 14 | public string Description { get; set; } 15 | public string ImageFile { get; set; } 16 | public ProductBrand Brands { get; set; } 17 | public ProductType Types { get; set; } 18 | [BsonRepresentation(MongoDB.Bson.BsonType.Decimal128)] 19 | public decimal Price { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Application/Responses/TypesResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Catalog.Application.Responses 2 | { 3 | public class TypesResponse 4 | { 5 | public string Id { get; set; } 6 | public string Name { get; set; } 7 | 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Core/Catalog.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Core/Entities/BaseEntity.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Bson.Serialization.Attributes; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Catalog.Core.Entities 9 | { 10 | public class BaseEntity 11 | { 12 | [BsonId] 13 | [BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)] 14 | public string Id { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Core/Entities/Product.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Bson.Serialization.Attributes; 2 | 3 | 4 | namespace Catalog.Core.Entities 5 | { 6 | public class Product : BaseEntity 7 | { 8 | [BsonElement("Name")] 9 | public string Name { get; set; } 10 | public string Summary { get; set; } 11 | public string Description { get; set; } 12 | public string ImageFile { get; set; } 13 | public ProductBrand Brands { get; set; } 14 | public ProductType Types { get; set; } 15 | [BsonRepresentation(MongoDB.Bson.BsonType.Decimal128)] 16 | public decimal Price { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Core/Entities/ProductBrand.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Bson.Serialization.Attributes; 2 | 3 | namespace Catalog.Core.Entities 4 | { 5 | public class ProductBrand : BaseEntity 6 | { 7 | [BsonElement("Name")] 8 | public string Name { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Core/Entities/ProductType.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Bson.Serialization.Attributes; 2 | 3 | namespace Catalog.Core.Entities 4 | { 5 | public class ProductType : BaseEntity 6 | { 7 | [BsonElement("Name")] 8 | public string Name { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Core/Repositories/IBrandRepository.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Core.Entities; 2 | 3 | namespace Catalog.Core.Repositories 4 | { 5 | public interface IBrandRepository 6 | { 7 | Task> GetAllBrands(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Core/Repositories/IProductRepository.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Core.Entities; 2 | using Catalog.Core.Specs; 3 | 4 | namespace Catalog.Core.Repositories 5 | { 6 | public interface IProductRepository 7 | { 8 | Task> GetProducts(CatalogSpecParams catalogSpecParams); 9 | Task GetProduct(string id); 10 | Task> GetProductsByName(string name); 11 | Task> GetProductsByBrand(string brandName); 12 | Task CreateProduct(Product product); 13 | Task UpdateProduct(Product product); 14 | Task DeleteProduct(string id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Core/Repositories/ITypesRepository.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Core.Entities; 2 | 3 | namespace Catalog.Core.Repositories 4 | { 5 | public interface ITypesRepository 6 | { 7 | Task> GetAllTypes(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Core/Specs/CatalogSpecParams.cs: -------------------------------------------------------------------------------- 1 | namespace Catalog.Core.Specs 2 | { 3 | public class CatalogSpecParams 4 | { 5 | private const int MaxPageSize = 70; 6 | private int _pageSize = 10; 7 | 8 | public int PageIndex { get; set; } = 1; 9 | public int PageSize 10 | { 11 | get => _pageSize; 12 | set => _pageSize = (value > MaxPageSize) ? MaxPageSize:value; 13 | } 14 | public string? BrandId { get; set; } 15 | public string? TypeId { get; set; } 16 | public string? Sort { get; set; } 17 | public string? Search { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Core/Specs/Pagination.cs: -------------------------------------------------------------------------------- 1 | namespace Catalog.Core.Specs 2 | { 3 | public class Pagination where T : class 4 | { 5 | public Pagination() 6 | { 7 | 8 | } 9 | public Pagination(int pageIndex, int pageSize, int count, IReadOnlyList data) 10 | { 11 | PageIndex = pageIndex; 12 | PageSize = pageSize; 13 | Count = count; 14 | Data = data; 15 | } 16 | public int PageIndex { get; set; } 17 | public int PageSize { get; set; } 18 | public int Count { get; set; } 19 | public IReadOnlyList Data { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Infrastructure/Catalog.Infrastructure.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Always 20 | 21 | 22 | Always 23 | 24 | 25 | Always 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Infrastructure/Data/BrandContextSeed.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Core.Entities; 2 | using MongoDB.Driver; 3 | using System.Text.Json; 4 | 5 | namespace Catalog.Infrastructure.Data 6 | { 7 | public static class BrandContextSeed 8 | { 9 | public static void SeedData(IMongoCollection brandCollection) 10 | { 11 | bool checkBrands = brandCollection.Find(b => true).Any(); 12 | string path = Path.Combine("Data", "SeedData", "brands.json"); 13 | if (!checkBrands) { 14 | var brandsData = File.ReadAllText(path); 15 | //var brandsData = File.ReadAllText("../Catalog.Infrastructure/Data/SeedData/brands.json"); 16 | var brands = JsonSerializer.Deserialize>(brandsData); 17 | if (brands != null) 18 | { 19 | foreach(var item in brands) 20 | { 21 | brandCollection.InsertOneAsync(item); 22 | } 23 | } 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Infrastructure/Data/CatalogContext.cs: -------------------------------------------------------------------------------- 1 |  2 | using Catalog.Core.Entities; 3 | using Microsoft.Extensions.Configuration; 4 | 5 | using MongoDB.Driver; 6 | 7 | namespace Catalog.Infrastructure.Data 8 | { 9 | public class CatalogContext : ICatalogContext 10 | { 11 | public IMongoCollection Products { get; } 12 | 13 | public IMongoCollection Brands { get; } 14 | 15 | public IMongoCollection Types { get; } 16 | 17 | public CatalogContext(IConfiguration configuration) 18 | { 19 | var client = new MongoClient(configuration.GetValue("DatabaseSettings:ConnectionString")); 20 | var database = client.GetDatabase(configuration.GetValue("DatabaseSettings:DatabaseName")); 21 | Brands = database.GetCollection(configuration.GetValue("DatabaseSettings:BrandsCollection")); 22 | Types = database.GetCollection(configuration.GetValue("DatabaseSettings:TypesCollection")); 23 | Products = database.GetCollection(configuration.GetValue("DatabaseSettings:CollectionName")); 24 | BrandContextSeed.SeedData(Brands); 25 | TypeContextSeed.SeedData(Types); 26 | CatalogContextSeed.SeedData(Products); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Infrastructure/Data/CatalogContextSeed.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Core.Entities; 2 | using MongoDB.Driver; 3 | using System.Text.Json; 4 | 5 | 6 | namespace Catalog.Infrastructure.Data 7 | { 8 | public static class CatalogContextSeed 9 | { 10 | public static void SeedData(IMongoCollection productCollection) 11 | { 12 | bool checkProducts = productCollection.Find(b => true).Any(); 13 | string path = Path.Combine("Data", "SeedData", "products.json"); 14 | if (!checkProducts) 15 | { 16 | var productsData = File.ReadAllText(path); 17 | //var productsData = File.ReadAllText("../Catalog.Infrastructure/Data/SeedData/products.json"); 18 | var products = JsonSerializer.Deserialize>(productsData); 19 | if (products != null) 20 | { 21 | foreach (var item in products) 22 | { 23 | productCollection.InsertOneAsync(item); 24 | } 25 | } 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Infrastructure/Data/ICatalogContext.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Core.Entities; 2 | using MongoDB.Driver; 3 | 4 | 5 | namespace Catalog.Infrastructure.Data 6 | { 7 | public interface ICatalogContext 8 | { 9 | IMongoCollection Products { get; } 10 | IMongoCollection Brands { get; } 11 | IMongoCollection Types { get; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Infrastructure/Data/SeedData/brands.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "63ca5e40e0aa3968b549af53", 4 | "Name": "Adidas" 5 | }, 6 | { 7 | "Id": "63ca5e4c455900b990b43bc1", 8 | "Name": "ASICS" 9 | }, 10 | { 11 | "Id": "63ca5e59065163c16451bd73", 12 | "Name": "Victor" 13 | }, 14 | { 15 | "Id": "63ca5e655ec1fdc49bd9327d", 16 | "Name": "Yonex" 17 | }, 18 | { 19 | "Id": "63ca5e728c4cff9708ada2a6", 20 | "Name": "Puma" 21 | }, 22 | { 23 | "Id": "63ca5e7ec90ff5c8f44d5ac8", 24 | "Name": "Nike" 25 | }, 26 | { 27 | "Id": "63ca5e8d6110a9c56ee7dc48", 28 | "Name": "Babolat" 29 | } 30 | ] -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Infrastructure/Data/SeedData/types.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "63ca5d4bc3a8a58f47299f97", 4 | "Name": "Shoes" 5 | }, 6 | { 7 | "Id": "63ca5d6d958e43ee1cd375fe", 8 | "Name": "Rackets" 9 | }, 10 | { 11 | "Id": "63ca5d7d380402dce7f06ebc", 12 | "Name": "Football" 13 | }, 14 | { 15 | "Id": "63ca5d8849bc19321b8be5f1", 16 | "Name": "Kit Bags" 17 | } 18 | ] -------------------------------------------------------------------------------- /Services/Catalog/Catalog.Infrastructure/Data/TypeContextSeed.cs: -------------------------------------------------------------------------------- 1 | using Catalog.Core.Entities; 2 | using MongoDB.Driver; 3 | using System.Text.Json; 4 | 5 | namespace Catalog.Infrastructure.Data 6 | { 7 | public static class TypeContextSeed 8 | { 9 | public static void SeedData(IMongoCollection typeCollection) 10 | { 11 | bool checkTypes = typeCollection.Find(b => true).Any(); 12 | string path = Path.Combine("Data", "SeedData", "types.json"); 13 | if (!checkTypes) 14 | { 15 | var typesData = File.ReadAllText(path); 16 | //var typesData = File.ReadAllText("../Catalog.Infrastructure/Data/SeedData/types.json"); 17 | var types = JsonSerializer.Deserialize>(typesData); 18 | if (types != null) 19 | { 20 | foreach (var item in types) 21 | { 22 | typeCollection.InsertOneAsync(item); 23 | } 24 | } 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Services/Discount/Discount.API/Discount.API.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | Linux 8 | ..\..\.. 9 | ..\..\..\docker-compose.dcproj 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Services/Discount/Discount.API/Discount.API.http: -------------------------------------------------------------------------------- 1 | @Discount.API_HostAddress = http://localhost:5057 2 | 3 | GET {{Discount.API_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /Services/Discount/Discount.API/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Services/Discount/Discount.API/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "DatabaseSettings": { 3 | "ConnectionString": "Server=localhost;Port=5432;Database=DiscountDb;User Id=admin;Password=Password@1;" 4 | }, 5 | "AllowedHosts": "*", 6 | "Kestrel": { 7 | "EndpointDefaults": { 8 | "Protocols": "Http2" 9 | } 10 | }, 11 | "ElasticConfiguration": { 12 | "Uri": "http://localhost:9200" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Services/Discount/Discount.Application/Commands/CreateDiscountCommand.cs: -------------------------------------------------------------------------------- 1 | using Discount.Grpc.Protos; 2 | using MediatR; 3 | 4 | namespace Discount.Application.Commands 5 | { 6 | public class CreateDiscountCommand : IRequest 7 | { 8 | public string ProductName { get; set; } 9 | public string Description { get; set; } 10 | public int Amount { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Services/Discount/Discount.Application/Commands/DeleteDiscountCommand.cs: -------------------------------------------------------------------------------- 1 | using MediatR; 2 | 3 | namespace Discount.Application.Commands 4 | { 5 | public class DeleteDiscountCommand : IRequest 6 | { 7 | public string ProductName { get; set; } 8 | public DeleteDiscountCommand(string productName) 9 | { 10 | ProductName = productName; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Services/Discount/Discount.Application/Commands/UpdateDiscountCommand.cs: -------------------------------------------------------------------------------- 1 | using Discount.Grpc.Protos; 2 | using MediatR; 3 | 4 | namespace Discount.Application.Commands 5 | { 6 | public class UpdateDiscountCommand : IRequest 7 | { 8 | public int Id { get; set; } 9 | public string ProductName { get; set; } 10 | public string Description { get; set; } 11 | public int Amount { get; set; } 12 | 13 | } 14 | } -------------------------------------------------------------------------------- /Services/Discount/Discount.Application/Discount.Application.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Services/Discount/Discount.Application/Handlers/CreateDiscountCommandHandler.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Discount.Application.Commands; 3 | using Discount.Core.Entities; 4 | using Discount.Core.Repositories; 5 | using Discount.Grpc.Protos; 6 | using MediatR; 7 | 8 | namespace Discount.Application.Handlers 9 | { 10 | public class CreateDiscountCommandHandler : IRequestHandler 11 | { 12 | private readonly IDiscountRepository _discountRepository; 13 | private readonly IMapper _mapper; 14 | 15 | public CreateDiscountCommandHandler(IDiscountRepository discountRepository, IMapper mapper) 16 | { 17 | _discountRepository = discountRepository; 18 | _mapper = mapper; 19 | } 20 | public async Task Handle(CreateDiscountCommand request, CancellationToken cancellationToken) 21 | { 22 | var coupon = _mapper.Map(request); 23 | await _discountRepository.CreateDiscount(coupon); 24 | var couponModel = _mapper.Map(coupon); 25 | return couponModel; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Services/Discount/Discount.Application/Handlers/DeleteDiscountCommandHandler.cs: -------------------------------------------------------------------------------- 1 | using Discount.Application.Commands; 2 | using Discount.Core.Repositories; 3 | using MediatR; 4 | 5 | namespace Discount.Application.Handlers 6 | { 7 | public class DeleteDiscountCommandHandler : IRequestHandler 8 | { 9 | private readonly IDiscountRepository _discountRepository; 10 | 11 | public DeleteDiscountCommandHandler(IDiscountRepository discountRepository) 12 | { 13 | _discountRepository = discountRepository; 14 | } 15 | public async Task Handle(DeleteDiscountCommand request, CancellationToken cancellationToken) 16 | { 17 | var deleted = await _discountRepository.DeleteDiscount(request.ProductName); 18 | return deleted; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Services/Discount/Discount.Application/Handlers/UpdateDiscountCommandHandler.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Discount.Application.Commands; 3 | using Discount.Core.Entities; 4 | using Discount.Core.Repositories; 5 | using Discount.Grpc.Protos; 6 | using MediatR; 7 | 8 | namespace Discount.Application.Handlers 9 | { 10 | public class UpdateDiscountCommandHandler : IRequestHandler 11 | { 12 | private readonly IDiscountRepository _discountRepository; 13 | private readonly IMapper _mapper; 14 | public UpdateDiscountCommandHandler(IDiscountRepository discountRepository, IMapper mapper) 15 | { 16 | _discountRepository = discountRepository; 17 | _mapper = mapper; 18 | } 19 | public async Task Handle(UpdateDiscountCommand request, CancellationToken cancellationToken) 20 | { 21 | var coupon = _mapper.Map(request); 22 | await _discountRepository.UpdateDiscount(coupon); 23 | var couponModel = _mapper.Map(coupon); 24 | return couponModel; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Services/Discount/Discount.Application/Mapper/DiscountProfile.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Discount.Core.Entities; 3 | using Discount.Grpc.Protos; 4 | 5 | namespace Discount.Application.Mapper 6 | { 7 | public class DiscountProfile : Profile 8 | { 9 | public DiscountProfile() 10 | { 11 | CreateMap().ReverseMap(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Services/Discount/Discount.Application/Protos/discount.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option csharp_namespace = "Discount.Grpc.Protos"; 4 | 5 | service DiscountProtoService { 6 | rpc GetDiscount(GetDiscountRequest) returns (CouponModel); 7 | rpc CreateDiscount(CreateDiscountRequest) returns (CouponModel); 8 | rpc UpdateDiscount(UpdateDiscountRequest) returns (CouponModel); 9 | rpc DeleteDiscount(DeleteDiscountRequest) returns (DeleteDiscountResponse); 10 | } 11 | 12 | message GetDiscountRequest { 13 | string productName = 1; 14 | } 15 | 16 | message CouponModel { 17 | int32 id = 1; 18 | string productName = 2; 19 | string description = 3; 20 | int32 amount = 4; 21 | } 22 | 23 | message CreateDiscountRequest { 24 | CouponModel coupon = 1; 25 | } 26 | message UpdateDiscountRequest { 27 | CouponModel coupon = 1; 28 | } 29 | 30 | message DeleteDiscountRequest { 31 | string productName = 1; 32 | } 33 | 34 | message DeleteDiscountResponse { 35 | bool success = 1; 36 | } -------------------------------------------------------------------------------- /Services/Discount/Discount.Application/Queries/GetDiscountQuery.cs: -------------------------------------------------------------------------------- 1 | using Discount.Grpc.Protos; 2 | using MediatR; 3 | 4 | namespace Discount.Application.Queries 5 | { 6 | public class GetDiscountQuery : IRequest 7 | { 8 | public string ProductName { get; set; } 9 | public GetDiscountQuery(string productName) 10 | { 11 | ProductName = productName; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Services/Discount/Discount.Core/Discount.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Services/Discount/Discount.Core/Entities/Coupon.cs: -------------------------------------------------------------------------------- 1 | namespace Discount.Core.Entities 2 | { 3 | public class Coupon 4 | { 5 | public int Id { get; set; } 6 | public string ProductName { get; set; } 7 | public string Description { get; set; } 8 | public int Amount { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Services/Discount/Discount.Core/Repositories/IDiscountRepository.cs: -------------------------------------------------------------------------------- 1 | using Discount.Core.Entities; 2 | 3 | namespace Discount.Core.Repositories 4 | { 5 | public interface IDiscountRepository 6 | { 7 | Task GetDiscount(string productName); 8 | Task CreateDiscount(Coupon coupon); 9 | Task UpdateDiscount(Coupon coupon); 10 | Task DeleteDiscount(string productName); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Services/Discount/Discount.Infrastructure/Discount.Infrastructure.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.API/Controllers/ApiController.cs: -------------------------------------------------------------------------------- 1 | using Asp.Versioning; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace Ordering.API.Controllers 5 | { 6 | [ApiVersion("1")] 7 | [Route("api/v{version:apiVersion}/[controller]")] 8 | [ApiController] 9 | public class ApiController : ControllerBase 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.API/EventBusConsumer/BasketOrderingConsumer.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using EventBus.Messages.Common; 3 | using MassTransit; 4 | using MediatR; 5 | using Ordering.Application.Commands; 6 | 7 | 8 | namespace Ordering.API.EventBusConsumer 9 | { 10 | public class BasketOrderingConsumer : IConsumer 11 | { 12 | private readonly IMediator _mediator; 13 | private readonly IMapper _mapper; 14 | private readonly ILogger _logger; 15 | 16 | public BasketOrderingConsumer(IMediator mediator, IMapper mapper, ILogger logger) 17 | { 18 | _mediator = mediator; 19 | _mapper = mapper; 20 | _logger = logger; 21 | } 22 | 23 | public async Task Consume(ConsumeContext context) 24 | { 25 | using var scope = _logger.BeginScope("Consuming Basket Checkout Event for {correlationId}", context.Message.CorrelationId); 26 | var cmd = _mapper.Map(context.Message); 27 | var result = await _mediator.Send(cmd); 28 | _logger.LogInformation("Basket Checkout Event completed!!!"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.API/EventBusConsumer/BasketOrderingConsumerV2.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using EventBus.Messages.Events; 3 | using MassTransit; 4 | using MediatR; 5 | using Ordering.Application.Commands; 6 | 7 | namespace Ordering.API.EventBusConsumer 8 | { 9 | public class BasketOrderingConsumerV2 : IConsumer 10 | { 11 | private readonly IMediator _mediator; 12 | private readonly IMapper _mapper; 13 | private readonly ILogger _logger; 14 | 15 | public BasketOrderingConsumerV2(IMediator mediator, IMapper mapper, ILogger logger) 16 | { 17 | _mediator = mediator; 18 | _mapper = mapper; 19 | _logger = logger; 20 | } 21 | public async Task Consume(ConsumeContext context) 22 | { 23 | using var scope = _logger.BeginScope("Consuming Basket Checkout Event for {correlationId} with version 2", context.Message.CorrelationId); 24 | var cmd = _mapper.Map(context.Message); 25 | var result = await _mediator.Send(cmd); 26 | _logger.LogInformation("Basket Checkout Event completed with version 2!!!"); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.API/Ordering.API.http: -------------------------------------------------------------------------------- 1 | @Ordering.API_HostAddress = http://localhost:5224 2 | 3 | GET {{Ordering.API_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.API/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.API/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "OrderingConnectionString": "Server=localhost;Database=OrderDb;User Id=sa;Password=Rahul1234567;TrustServerCertificate=True;" 4 | }, 5 | "EventBusSettings": { 6 | "HostAddress": "amqp://guest:guest@localhost:5672" 7 | }, 8 | "ElasticConfiguration": { 9 | "Uri": "http://localhost:9200" 10 | }, 11 | "AllowedHosts": "*" 12 | } 13 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Behaviour/UnhandledExceptionBehaviour.cs: -------------------------------------------------------------------------------- 1 | using MediatR; 2 | using Microsoft.Extensions.Logging; 3 | 4 | namespace Ordering.Application.Behaviour 5 | { 6 | public class UnhandledExceptionBehaviour : IPipelineBehavior where TRequest : IRequest 7 | { 8 | private readonly ILogger _logger; 9 | 10 | public UnhandledExceptionBehaviour(ILogger logger) 11 | { 12 | _logger = logger; 13 | } 14 | public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) 15 | { 16 | try 17 | { 18 | return await next(); 19 | } 20 | catch (Exception ex) 21 | { 22 | var requestName = typeof(TRequest).Name; 23 | _logger.LogError(ex, $"Unhandled exception occurred with Request Name: {requestName}, {request}"); 24 | throw; 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Commands/CheckoutOrderCommand.cs: -------------------------------------------------------------------------------- 1 | using MediatR; 2 | 3 | namespace Ordering.Application.Commands 4 | { 5 | public class CheckoutOrderCommand : IRequest 6 | { 7 | public string? UserName { get; set; } 8 | public decimal? TotalPrice { get; set; } 9 | public string? FirstName { get; set; } 10 | public string? LastName { get; set; } 11 | public string? EmailAddress { get; set; } 12 | public string? AddressLine { get; set; } 13 | public string? Country { get; set; } 14 | public string? State { get; set; } 15 | public string? ZipCode { get; set; } 16 | public string? CardName { get; set; } 17 | public string? CardNumber { get; set; } 18 | public string? Expiration { get; set; } 19 | public string? Cvv { get; set; } 20 | public int? PaymentMethod { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Commands/CheckoutOrderCommandV2.cs: -------------------------------------------------------------------------------- 1 | using MediatR; 2 | 3 | namespace Ordering.Application.Commands 4 | { 5 | public class CheckoutOrderCommandV2 : IRequest 6 | { 7 | public string? UserName { get; set; } 8 | public decimal? TotalPrice { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Commands/DeleteOrderCommand.cs: -------------------------------------------------------------------------------- 1 | using MediatR; 2 | 3 | namespace Ordering.Application.Commands 4 | { 5 | public class DeleteOrderCommand : IRequest 6 | { 7 | public int Id { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Commands/UpdateOrderCommand.cs: -------------------------------------------------------------------------------- 1 | using MediatR; 2 | 3 | namespace Ordering.Application.Commands 4 | { 5 | public class UpdateOrderCommand : IRequest 6 | { 7 | public int Id { get; set; } 8 | public string? UserName { get; set; } 9 | public decimal? TotalPrice { get; set; } 10 | public string? FirstName { get; set; } 11 | public string? LastName { get; set; } 12 | public string? EmailAddress { get; set; } 13 | public string? AddressLine { get; set; } 14 | public string? Country { get; set; } 15 | public string? State { get; set; } 16 | public string? ZipCode { get; set; } 17 | public string? CardName { get; set; } 18 | public string? CardNumber { get; set; } 19 | public string? Expiration { get; set; } 20 | public string? Cvv { get; set; } 21 | public int? PaymentMethod { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Exceptions/OrderNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace Ordering.Application.Exceptions 2 | { 3 | public class OrderNotFoundException : ApplicationException 4 | { 5 | public OrderNotFoundException(string name, Object key):base($"Entity {name} - {key} is not found.") 6 | { 7 | 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Exceptions/ValidationException.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation.Results; 2 | using System.ComponentModel; 3 | 4 | namespace Ordering.Application.Exceptions 5 | { 6 | public class ValidationException : ApplicationException 7 | { 8 | public Dictionary Errors { get; } 9 | public ValidationException() : base("One or more validation error(s) occurred.") 10 | { 11 | Errors = new Dictionary(); 12 | } 13 | 14 | public ValidationException(IEnumerable failures): this() 15 | { 16 | Errors = failures 17 | .GroupBy(e => e.PropertyName, e => e.ErrorMessage) 18 | .ToDictionary(failure => failure.Key, failure => failure.ToArray()); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Extensions/ServiceRegistration.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | using MediatR; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Ordering.Application.Behaviour; 5 | using System.Reflection; 6 | 7 | namespace Ordering.Application.Extensions 8 | { 9 | public static class ServiceRegistration 10 | { 11 | public static IServiceCollection AddApplicationServices(this IServiceCollection services) 12 | { 13 | services.AddAutoMapper(Assembly.GetExecutingAssembly()); 14 | services.AddMediatR(cfg=>cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly())); 15 | services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly()); 16 | services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehaviour<,>)); 17 | services.AddTransient(typeof(IPipelineBehavior<,>), typeof(UnhandledExceptionBehaviour<,>)); 18 | return services; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Handlers/CheckoutOrderCommandHandler.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using MediatR; 3 | using Microsoft.Extensions.Logging; 4 | using Ordering.Application.Commands; 5 | using Ordering.Core.Entities; 6 | using Ordering.Core.Repositories; 7 | 8 | namespace Ordering.Application.Handlers 9 | { 10 | public class CheckoutOrderCommandHandler : IRequestHandler 11 | { 12 | private readonly IOrderRepository _orderRepository; 13 | private readonly IMapper _mapper; 14 | private readonly ILogger _logger; 15 | 16 | public CheckoutOrderCommandHandler(IOrderRepository orderRepository, IMapper mapper, ILogger logger) 17 | { 18 | _orderRepository = orderRepository; 19 | _mapper = mapper; 20 | _logger = logger; 21 | } 22 | public async Task Handle(CheckoutOrderCommand request, CancellationToken cancellationToken) 23 | { 24 | var orderEntity = _mapper.Map(request); 25 | var generatedOrder = await _orderRepository.AddAsync(orderEntity); 26 | _logger.LogInformation($"Order with Id {generatedOrder.Id} successfully created"); 27 | return generatedOrder.Id; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Handlers/CheckoutOrderCommandV2Handler.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using MediatR; 3 | using Microsoft.Extensions.Logging; 4 | using Ordering.Application.Commands; 5 | using Ordering.Core.Entities; 6 | using Ordering.Core.Repositories; 7 | 8 | namespace Ordering.Application.Handlers 9 | { 10 | public class CheckoutOrderCommandV2Handler : IRequestHandler 11 | { 12 | private readonly IOrderRepository _orderRepository; 13 | private readonly IMapper _mapper; 14 | private readonly ILogger _logger; 15 | 16 | public CheckoutOrderCommandV2Handler(IOrderRepository orderRepository, IMapper mapper, ILogger logger) 17 | { 18 | _orderRepository = orderRepository; 19 | _mapper = mapper; 20 | _logger = logger; 21 | } 22 | public async Task Handle(CheckoutOrderCommandV2 request, CancellationToken cancellationToken) 23 | { 24 | var orderEntity = _mapper.Map(request); 25 | var generatedOrder = await _orderRepository.AddAsync(orderEntity); 26 | _logger.LogInformation($"Order with Id {generatedOrder.Id} successfully created with V2 Handler"); 27 | return generatedOrder.Id; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Handlers/GetOrderListQueryHandler.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using MediatR; 3 | using Ordering.Application.Queries; 4 | using Ordering.Application.Responses; 5 | using Ordering.Core.Repositories; 6 | 7 | namespace Ordering.Application.Handlers 8 | { 9 | public class GetOrderListQueryHandler : IRequestHandler> 10 | { 11 | private readonly IOrderRepository _orderRepository; 12 | private readonly IMapper _mapper; 13 | 14 | public GetOrderListQueryHandler(IOrderRepository orderRepository, IMapper mapper) 15 | { 16 | _orderRepository = orderRepository; 17 | _mapper = mapper; 18 | } 19 | public async Task> Handle(GetOrderListQuery request, CancellationToken cancellationToken) 20 | { 21 | var orderList = await _orderRepository.GetOrdersByUserName(request.UserName); 22 | return _mapper.Map>(orderList); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Mappers/OrderMappingProfile.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using EventBus.Messages.Common; 3 | using EventBus.Messages.Events; 4 | using Ordering.Application.Commands; 5 | using Ordering.Application.Responses; 6 | using Ordering.Core.Entities; 7 | 8 | namespace Ordering.Application.Mappers 9 | { 10 | public class OrderMappingProfile : Profile 11 | { 12 | public OrderMappingProfile() 13 | { 14 | CreateMap().ReverseMap(); 15 | CreateMap().ReverseMap(); 16 | CreateMap().ReverseMap(); 17 | CreateMap().ReverseMap(); 18 | CreateMap().ReverseMap(); 19 | CreateMap().ReverseMap(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Ordering.Application.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Queries/GetOrderListQuery.cs: -------------------------------------------------------------------------------- 1 | using MediatR; 2 | using Ordering.Application.Responses; 3 | 4 | namespace Ordering.Application.Queries 5 | { 6 | public class GetOrderListQuery : IRequest> 7 | { 8 | public string UserName { get; set; } 9 | public GetOrderListQuery(string userName) 10 | { 11 | UserName = userName; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Responses/OrderResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Ordering.Application.Responses 2 | { 3 | public class OrderResponse 4 | { 5 | public int Id { get; set; } 6 | public string? UserName { get; set; } 7 | public decimal? TotalPrice { get; set; } 8 | public string? FirstName { get; set; } 9 | public string? LastName { get; set; } 10 | public string? EmailAddress { get; set; } 11 | public string? AddressLine { get; set; } 12 | public string? Country { get; set; } 13 | public string? State { get; set; } 14 | public string? ZipCode { get; set; } 15 | public string? CardName { get; set; } 16 | public string? CardNumber { get; set; } 17 | public string? Expiration { get; set; } 18 | public string? Cvv { get; set; } 19 | public int? PaymentMethod { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Validators/CheckoutOrderCommandValidator.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | using Ordering.Application.Commands; 3 | 4 | namespace Ordering.Application.Validators 5 | { 6 | public class CheckoutOrderCommandValidator : AbstractValidator 7 | { 8 | public CheckoutOrderCommandValidator() 9 | { 10 | RuleFor(o => o.UserName) 11 | .NotEmpty() 12 | .WithMessage("{UserName} is required.") 13 | .NotNull() 14 | .MaximumLength(70) 15 | .WithMessage("{UserName} must not exceed 70 characters."); 16 | RuleFor(o => o.TotalPrice) 17 | .NotEmpty() 18 | .WithMessage("{TotalPrice} is required.") 19 | .GreaterThan(-1) 20 | .WithMessage("{TotalPrice} should not be -ve"); 21 | RuleFor(o => o.EmailAddress) 22 | .NotEmpty() 23 | .WithMessage("{EmailAddress} is required"); 24 | RuleFor(o => o.FirstName) 25 | .NotEmpty() 26 | .NotNull() 27 | .WithMessage("{FirstName} is required"); 28 | RuleFor(o => o.LastName) 29 | .NotEmpty() 30 | .NotNull() 31 | .WithMessage("{LastName} is required"); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Application/Validators/CheckoutOrderCommandValidatorV2.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | using Ordering.Application.Commands; 3 | 4 | namespace Ordering.Application.Validators 5 | { 6 | public class CheckoutOrderCommandValidatorV2 : AbstractValidator 7 | { 8 | public CheckoutOrderCommandValidatorV2() 9 | { 10 | RuleFor(o => o.UserName) 11 | .NotEmpty() 12 | .WithMessage("{UserName} is required.") 13 | .NotNull() 14 | .MaximumLength(70) 15 | .WithMessage("{UserName} must not exceed 70 characters."); 16 | RuleFor(o => o.TotalPrice) 17 | .NotEmpty() 18 | .WithMessage("{TotalPrice} is required.") 19 | .GreaterThan(-1) 20 | .WithMessage("{TotalPrice} should not be -ve"); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Core/Common/EntityBase.cs: -------------------------------------------------------------------------------- 1 | namespace Ordering.Core.Common 2 | { 3 | public abstract class EntityBase 4 | { 5 | //Protected set is made to use in the derived classes 6 | public int Id { get; protected set; } 7 | //Below Properties are Audit properties 8 | public string? CreatedBy { get; set; } 9 | public DateTime? CreatedDate { get; set; } 10 | public string? LastModifiedBy { get; set; } 11 | public DateTime? LastModifiedDate { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Core/Entities/Order.cs: -------------------------------------------------------------------------------- 1 | using Ordering.Core.Common; 2 | 3 | namespace Ordering.Core.Entities 4 | { 5 | public class Order : EntityBase 6 | { 7 | public string? UserName { get; set; } 8 | public decimal? TotalPrice { get; set; } 9 | public string? FirstName { get; set; } 10 | public string? LastName { get; set; } 11 | public string? EmailAddress { get; set; } 12 | public string? AddressLine { get; set; } 13 | public string? Country { get; set; } 14 | public string? State { get; set; } 15 | public string? ZipCode { get; set; } 16 | public string? CardName { get; set; } 17 | public string? CardNumber { get; set; } 18 | public string? Expiration { get; set; } 19 | public string? Cvv { get; set; } 20 | public int? PaymentMethod { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Core/Ordering.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Core/Repositories/IAsyncRepository.cs: -------------------------------------------------------------------------------- 1 | using Ordering.Core.Common; 2 | using System.Linq.Expressions; 3 | 4 | namespace Ordering.Core.Repositories 5 | { 6 | public interface IAsyncRepository where T : EntityBase 7 | { 8 | Task> GetAllAsync(); 9 | Task> GetAllAsync(Expression> predicate); 10 | Task GetByIdAsync(int id); 11 | Task AddAsync(T entity); 12 | Task UpdateAsync(T entity); 13 | Task DeleteAsync(T entity); 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Core/Repositories/IOrderRepository.cs: -------------------------------------------------------------------------------- 1 | using Ordering.Core.Entities; 2 | 3 | namespace Ordering.Core.Repositories 4 | { 5 | public interface IOrderRepository : IAsyncRepository 6 | { 7 | Task> GetOrdersByUserName(string userName); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Infrastructure/Data/OrderContextFactory.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Design; 3 | 4 | namespace Ordering.Infrastructure.Data 5 | { 6 | public class OrderContextFactory : IDesignTimeDbContextFactory 7 | { 8 | public OrderContext CreateDbContext(string[] args) 9 | { 10 | var optionsBuilder = new DbContextOptionsBuilder(); 11 | optionsBuilder.UseSqlServer("Data Source=OrderDb"); 12 | return new OrderContext(optionsBuilder.Options); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Infrastructure/Extensions/InfraServices.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Ordering.Core.Repositories; 5 | using Ordering.Infrastructure.Data; 6 | using Ordering.Infrastructure.Repositories; 7 | 8 | namespace Ordering.Infrastructure.Extensions 9 | { 10 | public static class InfraServices 11 | { 12 | public static IServiceCollection AddInfraServices(this IServiceCollection serviceCollection, IConfiguration configuration) 13 | { 14 | serviceCollection.AddDbContext(options => options.UseSqlServer( 15 | configuration.GetConnectionString("OrderingConnectionString"), 16 | sqlServerOptions => sqlServerOptions.EnableRetryOnFailure())); 17 | serviceCollection.AddScoped(typeof(IAsyncRepository<>), typeof(RepositoryBase<>)); 18 | serviceCollection.AddScoped(); 19 | return serviceCollection; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | all 13 | runtime; build; native; contentfiles; analyzers; buildtransitive 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Services/Ordering/Ordering.Infrastructure/Repositories/OrderRepository.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Ordering.Core.Entities; 3 | using Ordering.Core.Repositories; 4 | using Ordering.Infrastructure.Data; 5 | 6 | namespace Ordering.Infrastructure.Repositories 7 | { 8 | public class OrderRepository : RepositoryBase, IOrderRepository 9 | { 10 | public OrderRepository(OrderContext dbContext): base(dbContext) 11 | { 12 | 13 | } 14 | public async Task> GetOrdersByUserName(string userName) 15 | { 16 | var orderList = await _dbContext.Orders 17 | .Where(o => o.UserName == userName) 18 | .ToListAsync(); 19 | return orderList; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /client/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # Compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /bazel-out 8 | 9 | # Node 10 | /node_modules 11 | npm-debug.log 12 | yarn-error.log 13 | 14 | # IDEs and editors 15 | .idea/ 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # Visual Studio Code 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | .history/* 30 | 31 | # Miscellaneous 32 | /.angular/cache 33 | .sass-cache/ 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | testem.log 38 | /typings 39 | 40 | # System files 41 | .DS_Store 42 | Thumbs.db 43 | -------------------------------------------------------------------------------- /client/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 3 | "recommendations": ["angular.ng-template"] 4 | } 5 | -------------------------------------------------------------------------------- /client/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "name": "ng serve", 7 | "type": "pwa-chrome", 8 | "request": "launch", 9 | "preLaunchTask": "npm: start", 10 | "url": "http://localhost:4200/" 11 | }, 12 | { 13 | "name": "ng test", 14 | "type": "chrome", 15 | "request": "launch", 16 | "preLaunchTask": "npm: test", 17 | "url": "http://localhost:9876/debug.html" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /client/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | } 3 | -------------------------------------------------------------------------------- /client/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 3 | "version": "2.0.0", 4 | "tasks": [ 5 | { 6 | "type": "npm", 7 | "script": "start", 8 | "isBackground": true, 9 | "problemMatcher": { 10 | "owner": "typescript", 11 | "pattern": "$tsc", 12 | "background": { 13 | "activeOnStart": true, 14 | "beginsPattern": { 15 | "regexp": "(.*?)" 16 | }, 17 | "endsPattern": { 18 | "regexp": "bundle generation complete" 19 | } 20 | } 21 | } 22 | }, 23 | { 24 | "type": "npm", 25 | "script": "test", 26 | "isBackground": true, 27 | "problemMatcher": { 28 | "owner": "typescript", 29 | "pattern": "$tsc", 30 | "background": { 31 | "activeOnStart": true, 32 | "beginsPattern": { 33 | "regexp": "(.*?)" 34 | }, 35 | "endsPattern": { 36 | "regexp": "bundle generation complete" 37 | } 38 | } 39 | } 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /client/README.md: -------------------------------------------------------------------------------- 1 | # Client 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 15.0.5. 4 | 5 | ## Development server 6 | 7 | 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. 8 | 9 | ## Code scaffolding 10 | 11 | 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`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | 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. 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 28 | -------------------------------------------------------------------------------- /client/src/app/account/account.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { LoginComponent } from './login/login.component'; 4 | import { RegisterComponent } from './register/register.component'; 5 | import { AccountRoutingModule } from './account-routing.module'; 6 | import { MsalModule } from '@azure/msal-angular'; 7 | 8 | 9 | @NgModule({ 10 | declarations: [ 11 | LoginComponent, 12 | RegisterComponent 13 | ], 14 | imports: [ 15 | CommonModule, 16 | AccountRoutingModule, 17 | MsalModule 18 | ] 19 | }) 20 | export class AccountModule { } 21 | -------------------------------------------------------------------------------- /client/src/app/account/base.service.ts: -------------------------------------------------------------------------------- 1 | import { throwError } from 'rxjs'; 2 | 3 | export abstract class BaseService { 4 | 5 | constructor() { } 6 | 7 | protected handleError(error: any) { 8 | 9 | var applicationError = error.headers.get('Application-Error'); 10 | 11 | 12 | if (applicationError) { 13 | return throwError(applicationError); 14 | } 15 | 16 | var modelStateErrors: string = ''; 17 | 18 | for (var key in error.error) { 19 | if (error.error[key]) modelStateErrors += error.error[key].description + '\n'; 20 | } 21 | //return; 22 | modelStateErrors = modelStateErrors = '' ? null : modelStateErrors; 23 | return throwError(modelStateErrors || 'Server error'); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /client/src/app/account/constants.ts: -------------------------------------------------------------------------------- 1 | export class Constants { 2 | public static apiRoot = "https://localhost:8000"; 3 | public static clientRoot = "http://localhost:4200"; 4 | public static idpAuthority = "https://localhost:9009" 5 | public static clientId = "angular-client"; 6 | } 7 | -------------------------------------------------------------------------------- /client/src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { NotFoundComponent } from './core/not-found/not-found.component'; 4 | import { ServerErrorComponent } from './core/server-error/server-error.component'; 5 | import { UnAuthenticatedComponent } from './core/un-authenticated/un-authenticated.component'; 6 | import { HomeComponent } from './home/home.component'; 7 | 8 | const routes: Routes = [ 9 | {path: '', component:HomeComponent, data:{breadcrumb:'Home'}}, 10 | {path: 'not-found', component: NotFoundComponent}, 11 | {path: 'un-authenticated', component: UnAuthenticatedComponent}, 12 | {path:'server-error', component: ServerErrorComponent}, 13 | {path: 'store', loadChildren:()=>import('./store/store.module').then(mod=>mod.StoreModule), data:{breadcrumb:'Store'}}, 14 | {path: 'basket', loadChildren:()=>import('./basket/basket.module').then(mod=>mod.BasketModule), data:{breadcrumb:'Basket'}}, 15 | {path: 'checkout', loadChildren:()=>import('./checkout/checkout.module').then(mod=>mod.CheckoutModule), data:{breadcrumb:'Checkout'}}, 16 | {path: '**', redirectTo: '', pathMatch: 'full'}, 17 | ]; 18 | 19 | @NgModule({ 20 | imports: [RouterModule.forRoot(routes)], 21 | exports: [RouterModule] 22 | }) 23 | export class AppRoutingModule { } 24 | -------------------------------------------------------------------------------- /client/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 |

Fetching results...

3 |
4 | 5 | 6 |
7 | 8 | 9 |
10 | 11 | -------------------------------------------------------------------------------- /client/src/app/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/app/app.component.scss -------------------------------------------------------------------------------- /client/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AppComponent } from './app.component'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async () => { 7 | await TestBed.configureTestingModule({ 8 | imports: [ 9 | RouterTestingModule 10 | ], 11 | declarations: [ 12 | AppComponent 13 | ], 14 | }).compileComponents(); 15 | }); 16 | 17 | it('should create the app', () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.componentInstance; 20 | expect(app).toBeTruthy(); 21 | }); 22 | 23 | it(`should have as title 'client'`, () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | const app = fixture.componentInstance; 26 | expect(app.title).toEqual('client'); 27 | }); 28 | 29 | it('should render title', () => { 30 | const fixture = TestBed.createComponent(AppComponent); 31 | fixture.detectChanges(); 32 | const compiled = fixture.nativeElement as HTMLElement; 33 | expect(compiled.querySelector('.content span')?.textContent).toContain('client app is running!'); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /client/src/app/basket/basket-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { RouterModule, Routes } from '@angular/router'; 4 | import { BasketComponent } from './basket.component'; 5 | 6 | const routes: Routes = [ 7 | {path:'', component:BasketComponent} 8 | ] 9 | 10 | @NgModule({ 11 | declarations: [], 12 | imports: [ 13 | CommonModule, 14 | RouterModule.forChild(routes) 15 | ], 16 | exports:[ 17 | RouterModule 18 | ] 19 | }) 20 | export class BasketRoutingModule { } 21 | -------------------------------------------------------------------------------- /client/src/app/basket/basket.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/app/basket/basket.component.scss -------------------------------------------------------------------------------- /client/src/app/basket/basket.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { IBasketItem } from '../shared/models/basket'; 3 | import { BasketService } from './basket.service'; 4 | 5 | @Component({ 6 | selector: 'app-basket', 7 | templateUrl: './basket.component.html', 8 | styleUrls: ['./basket.component.scss'] 9 | }) 10 | export class BasketComponent { 11 | constructor(public basketService: BasketService){} 12 | 13 | removeBasketItem(item: IBasketItem){ 14 | this.basketService.removeItemFromBasket(item); 15 | } 16 | 17 | incrementItem(item: IBasketItem){ 18 | this.basketService.incrementItemQuantity(item); 19 | } 20 | 21 | decrementItem(item: IBasketItem){ 22 | this.basketService.decrementItemQuantity(item); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /client/src/app/basket/basket.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { BasketComponent } from './basket.component'; 4 | import { BasketRoutingModule } from './basket-routing.module'; 5 | import { SharedModule } from '../shared/shared.module'; 6 | 7 | 8 | 9 | @NgModule({ 10 | declarations: [ 11 | BasketComponent 12 | ], 13 | imports: [ 14 | CommonModule, 15 | BasketRoutingModule, 16 | SharedModule 17 | ] 18 | }) 19 | export class BasketModule { } 20 | -------------------------------------------------------------------------------- /client/src/app/checkout/checkout-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { CheckoutComponent } from './checkout.component'; 4 | 5 | const routes: Routes = [ 6 | {path: '', component: CheckoutComponent} 7 | ] 8 | 9 | @NgModule({ 10 | declarations: [], 11 | imports: [ 12 | RouterModule.forChild(routes) 13 | ], 14 | exports:[ 15 | RouterModule 16 | ] 17 | }) 18 | export class CheckoutRoutingModule { } 19 | -------------------------------------------------------------------------------- /client/src/app/checkout/checkout.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/app/checkout/checkout.component.scss -------------------------------------------------------------------------------- /client/src/app/checkout/checkout.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { CheckoutComponent } from './checkout.component'; 4 | import { CheckoutRoutingModule } from './checkout-routing.module'; 5 | import { SharedModule } from '../shared/shared.module'; 6 | 7 | 8 | @NgModule({ 9 | declarations: [ 10 | CheckoutComponent 11 | ], 12 | imports: [ 13 | CommonModule, 14 | CheckoutRoutingModule, 15 | SharedModule 16 | ] 17 | }) 18 | export class CheckoutModule { } 19 | -------------------------------------------------------------------------------- /client/src/app/checkout/checkout.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root' 5 | }) 6 | export class CheckoutService { 7 | 8 | constructor() { } 9 | } 10 | -------------------------------------------------------------------------------- /client/src/app/core/core.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { NavbarComponent } from './navbar/navbar.component'; 4 | import { RouterModule } from '@angular/router'; 5 | import { NotFoundComponent } from './not-found/not-found.component'; 6 | import { UnAuthenticatedComponent } from './un-authenticated/un-authenticated.component'; 7 | import { ServerErrorComponent } from './server-error/server-error.component'; 8 | import { HeaderComponent } from './header/header.component'; 9 | import { BreadcrumbModule } from 'xng-breadcrumb'; 10 | import { NgxSpinnerModule } from 'ngx-spinner'; 11 | 12 | 13 | 14 | @NgModule({ 15 | declarations: [ 16 | NavbarComponent, 17 | NotFoundComponent, 18 | UnAuthenticatedComponent, 19 | ServerErrorComponent, 20 | HeaderComponent 21 | ], 22 | imports: [ 23 | CommonModule, 24 | RouterModule, 25 | BreadcrumbModule, 26 | NgxSpinnerModule 27 | ], 28 | exports:[ 29 | NavbarComponent, 30 | HeaderComponent, 31 | NgxSpinnerModule 32 | ] 33 | }) 34 | export class CoreModule { } 35 | -------------------------------------------------------------------------------- /client/src/app/core/guards/auth.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; 3 | import { map } from 'rxjs'; 4 | import { Observable } from 'rxjs'; 5 | import { AcntService } from 'src/app/account/acnt.service'; 6 | 7 | @Injectable({ 8 | providedIn: 'root' 9 | }) 10 | export class AuthGuard implements CanActivate { 11 | constructor(private router: Router,private acntService: AcntService) { } 12 | canActivate( 13 | route: ActivatedRouteSnapshot, 14 | state: RouterStateSnapshot): Observable { 15 | return this.acntService.currentUser$.pipe( 16 | map(auth =>{ 17 | if(auth) return true; 18 | else{ 19 | this.router.navigate(['/account/login'], {queryParams: {returnUrl: state.url}, replaceUrl: true }); 20 | return false; 21 | } 22 | }) 23 | ) 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /client/src/app/core/guards/sample.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, UrlTree } from '@angular/router'; 3 | import { Observable } from 'rxjs'; 4 | 5 | @Injectable({ 6 | providedIn: 'root' 7 | }) 8 | export class SampleGuard implements CanActivate { 9 | canActivate( 10 | route: ActivatedRouteSnapshot, 11 | state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { 12 | return true; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /client/src/app/core/header/header.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 |

eCommerce!!!

7 | 8 |
9 |
10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 |
18 | 19 | -------------------------------------------------------------------------------- /client/src/app/core/header/header.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/app/core/header/header.component.scss -------------------------------------------------------------------------------- /client/src/app/core/header/header.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { BreadcrumbService } from 'xng-breadcrumb'; 3 | 4 | @Component({ 5 | selector: 'app-header', 6 | templateUrl: './header.component.html', 7 | styleUrls: ['./header.component.scss'] 8 | }) 9 | export class HeaderComponent { 10 | constructor(public bcService: BreadcrumbService){} 11 | 12 | } 13 | -------------------------------------------------------------------------------- /client/src/app/core/interceptors/error.interceptor.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { 3 | HttpRequest, 4 | HttpHandler, 5 | HttpEvent, 6 | HttpInterceptor 7 | } from '@angular/common/http'; 8 | import { catchError, Observable, throwError } from 'rxjs'; 9 | import { Router } from '@angular/router'; 10 | 11 | @Injectable() 12 | export class ErrorInterceptor implements HttpInterceptor { 13 | 14 | constructor(private router: Router) {} 15 | 16 | intercept(request: HttpRequest, next: HttpHandler): Observable> { 17 | return next.handle(request).pipe( 18 | catchError((error)=>{ 19 | if(error){ 20 | if(error.status === 404){ 21 | this.router.navigateByUrl('/not-found'); 22 | } 23 | if(error.status === 401){ 24 | this.router.navigateByUrl('/un-authenticated'); 25 | } 26 | if(error.status === 500){ 27 | this.router.navigateByUrl('/server-error'); 28 | } 29 | } 30 | return throwError(()=> new Error(error)); 31 | }) 32 | ) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /client/src/app/core/interceptors/loading.interceptor.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { 3 | HttpRequest, 4 | HttpHandler, 5 | HttpEvent, 6 | HttpInterceptor 7 | } from '@angular/common/http'; 8 | import { delay, finalize, Observable } from 'rxjs'; 9 | import { LoadingService } from '../services/loading.service'; 10 | 11 | @Injectable() 12 | export class LoadingInterceptor implements HttpInterceptor { 13 | 14 | constructor(private loadingService: LoadingService) {} 15 | 16 | intercept(request: HttpRequest, next: HttpHandler): Observable> { 17 | this.loadingService.loading(); 18 | return next.handle(request).pipe( 19 | //delay(1000), 20 | finalize(()=>{ 21 | this.loadingService.idle(); 22 | }) 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /client/src/app/core/navbar/navbar.component.scss: -------------------------------------------------------------------------------- 1 | .cart-no { 2 | position: absolute; 3 | min-height: 25px; 4 | min-width: 25px; 5 | border-radius: 50%; 6 | font-size: 1em; 7 | background: purple; 8 | color: white; 9 | text-align: center; 10 | top: -12px; 11 | right: 32px; 12 | } 13 | 14 | a { 15 | text-decoration: none; 16 | color: #343a40; 17 | &.active { 18 | color: orange; 19 | } 20 | } 21 | 22 | .logo{ 23 | cursor: pointer; 24 | &:focus{ 25 | outline: none; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /client/src/app/core/navbar/navbar.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { AcntService } from 'src/app/account/acnt.service'; 3 | import { BasketService } from 'src/app/basket/basket.service'; 4 | import { IBasketItem } from 'src/app/shared/models/basket'; 5 | 6 | @Component({ 7 | selector: 'app-navbar', 8 | templateUrl: './navbar.component.html', 9 | styleUrls: ['./navbar.component.scss'] 10 | }) 11 | export class NavbarComponent implements OnInit { 12 | public isUserAuthenticated: boolean = false; 13 | 14 | constructor(public basketService: BasketService, private acntService: AcntService) {} 15 | 16 | ngOnInit(): void { 17 | this.acntService.currentUser$.subscribe({ 18 | next: (user) => { 19 | this.isUserAuthenticated = !!user; // true if user is logged in, false otherwise 20 | console.log(`User authenticated: ${this.isUserAuthenticated}`); 21 | }, 22 | error: (err) => { 23 | console.log(`An error occurred while setting isUserAuthenticated flag: ${err}`); 24 | } 25 | }); 26 | } 27 | 28 | getBasketCount(items: IBasketItem[]): number { 29 | return items.reduce((sum, item) => sum + item.quantity, 0); 30 | } 31 | 32 | public login(): void { 33 | this.acntService.login(); 34 | } 35 | 36 | public logout(): void { 37 | this.acntService.logout(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /client/src/app/core/not-found/not-found.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |

404 Not Found

7 |

Oops! 404 Not Found!!!

8 | Go to homepage 9 |
10 |
11 |
12 |
13 |
14 | -------------------------------------------------------------------------------- /client/src/app/core/not-found/not-found.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/app/core/not-found/not-found.component.scss -------------------------------------------------------------------------------- /client/src/app/core/not-found/not-found.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-not-found', 5 | templateUrl: './not-found.component.html', 6 | styleUrls: ['./not-found.component.scss'] 7 | }) 8 | export class NotFoundComponent { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /client/src/app/core/server-error/server-error.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |

500 Server Error

7 |

Oops! Server Error happened!!!

8 |

Please refer Elastic Logs for more details...

9 | Go to homepage 10 |
11 |
12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /client/src/app/core/server-error/server-error.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/app/core/server-error/server-error.component.scss -------------------------------------------------------------------------------- /client/src/app/core/server-error/server-error.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-server-error', 5 | templateUrl: './server-error.component.html', 6 | styleUrls: ['./server-error.component.scss'] 7 | }) 8 | export class ServerErrorComponent { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /client/src/app/core/services/loading.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { NgxSpinnerService } from 'ngx-spinner'; 3 | 4 | @Injectable({ 5 | providedIn: 'root' 6 | }) 7 | export class LoadingService { 8 | loadingReqCount = 0; 9 | 10 | constructor(private spinnerService: NgxSpinnerService) {} 11 | 12 | loading() { 13 | this.loadingReqCount++; 14 | this.spinnerService.show(undefined, { 15 | type: 'ball-pulse-sync', 16 | bdColor: 'rgba(255,255,255,0.7)', 17 | color: '#333333' 18 | }); 19 | } 20 | 21 | idle() { 22 | this.loadingReqCount--; 23 | if (this.loadingReqCount <= 0) { 24 | this.loadingReqCount = 0; 25 | this.spinnerService.hide(); 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /client/src/app/core/un-authenticated/un-authenticated.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |

401 Server Error

7 |

Oops! Authentication Failed!!!

8 |

Please refer Elastic Logs for more details...

9 | Go to homepage 10 |
11 |
12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /client/src/app/core/un-authenticated/un-authenticated.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/app/core/un-authenticated/un-authenticated.component.scss -------------------------------------------------------------------------------- /client/src/app/core/un-authenticated/un-authenticated.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-un-authenticated', 5 | templateUrl: './un-authenticated.component.html', 6 | styleUrls: ['./un-authenticated.component.scss'] 7 | }) 8 | export class UnAuthenticatedComponent { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /client/src/app/home/home.component.scss: -------------------------------------------------------------------------------- 1 | .featured { 2 | height: 200px; 3 | } 4 | 5 | img { 6 | object-fit: cover; 7 | height: 600px; 8 | width: 100%; 9 | } 10 | -------------------------------------------------------------------------------- /client/src/app/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-home', 5 | templateUrl: './home.component.html', 6 | styleUrls: ['./home.component.scss'] 7 | }) 8 | export class HomeComponent { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /client/src/app/home/home.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { HomeComponent } from './home.component'; 4 | import { SharedModule } from '../shared/shared.module'; 5 | 6 | 7 | 8 | @NgModule({ 9 | declarations: [ 10 | HomeComponent 11 | ], 12 | imports: [ 13 | CommonModule, 14 | SharedModule 15 | ], 16 | exports:[ 17 | HomeComponent, 18 | SharedModule 19 | ] 20 | }) 21 | export class HomeModule { } 22 | -------------------------------------------------------------------------------- /client/src/app/shared/models/basket.ts: -------------------------------------------------------------------------------- 1 | export interface IBasketItem { 2 | quantity: number; 3 | imageFile: string; 4 | price: number; 5 | productId: string; 6 | productName: string; 7 | } 8 | 9 | export interface IBasket { 10 | userName: string; 11 | items: IBasketItem[]; 12 | totalPrice: number; 13 | } 14 | 15 | export class Basket implements IBasket { 16 | userName: string = 'rahul'; 17 | totalPrice: number = 0; 18 | items: IBasketItem[] = []; 19 | } 20 | 21 | export interface IBasketTotal{ 22 | total: number; 23 | } 24 | -------------------------------------------------------------------------------- /client/src/app/shared/models/brand.ts: -------------------------------------------------------------------------------- 1 | export interface IBrand { 2 | id: string; 3 | name: string; 4 | } 5 | -------------------------------------------------------------------------------- /client/src/app/shared/models/pagination.ts: -------------------------------------------------------------------------------- 1 | export interface IPagination { 2 | pageIndex: number; 3 | pageSize: number; 4 | count: number; 5 | data: T; 6 | } 7 | -------------------------------------------------------------------------------- /client/src/app/shared/models/product.ts: -------------------------------------------------------------------------------- 1 | export interface IProduct { 2 | id: string; 3 | name: string; 4 | description: string; 5 | imageFile: string; 6 | price: number; 7 | productType: string; 8 | productBrand: string; 9 | } 10 | -------------------------------------------------------------------------------- /client/src/app/shared/models/storeParams.ts: -------------------------------------------------------------------------------- 1 | export class StoreParams { 2 | brandId = ''; 3 | typeId = ''; 4 | sort = ''; 5 | pageNumber = 1; 6 | pageSize = 10; 7 | search?: string; 8 | } 9 | -------------------------------------------------------------------------------- /client/src/app/shared/models/type.ts: -------------------------------------------------------------------------------- 1 | export interface IType { 2 | id: string; 3 | name: string; 4 | } 5 | -------------------------------------------------------------------------------- /client/src/app/shared/order-summary/order-summary.component.html: -------------------------------------------------------------------------------- 1 |
2 | Order Details 3 |
4 |
5 |
    6 |
  • 7 | Total: 8 | {{total.total | currency: 'INR'}} 9 |
  • 10 |
11 |
12 | -------------------------------------------------------------------------------- /client/src/app/shared/order-summary/order-summary.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/app/shared/order-summary/order-summary.component.scss -------------------------------------------------------------------------------- /client/src/app/shared/order-summary/order-summary.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { BasketService } from 'src/app/basket/basket.service'; 3 | 4 | @Component({ 5 | selector: 'app-order-summary', 6 | templateUrl: './order-summary.component.html', 7 | styleUrls: ['./order-summary.component.scss'] 8 | }) 9 | export class OrderSummaryComponent { 10 | constructor(public basketService: BasketService){} 11 | } 12 | -------------------------------------------------------------------------------- /client/src/app/shared/shared.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { PaginationModule } from 'ngx-bootstrap/pagination'; 4 | import { CarouselModule } from 'ngx-bootstrap/carousel'; 5 | import { OrderSummaryComponent } from './order-summary/order-summary.component'; 6 | 7 | @NgModule({ 8 | declarations: [ 9 | OrderSummaryComponent 10 | ], 11 | imports: [ 12 | CommonModule, 13 | PaginationModule.forRoot(), 14 | CarouselModule.forRoot(), 15 | ], 16 | exports:[ 17 | PaginationModule, 18 | CarouselModule, 19 | OrderSummaryComponent 20 | ] 21 | }) 22 | export class SharedModule { } 23 | -------------------------------------------------------------------------------- /client/src/app/store/product-details/product-details.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | {{product.name}} 5 |

{{ product.name }}

6 |
7 |
8 |

{{ product.name }}

9 |

{{ product.price | currency: "INR"}}

10 |
11 | 12 | {{quantity}} 13 | 14 | 15 |
16 |
17 |
18 |
19 |

Description

20 |

{{product.description}}

21 |
22 |
23 |
24 |
25 | 26 | -------------------------------------------------------------------------------- /client/src/app/store/product-details/product-details.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/app/store/product-details/product-details.component.scss -------------------------------------------------------------------------------- /client/src/app/store/product-items/product-items.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | {{ product.name }} 4 |
5 | 6 | 7 |
8 |
9 | 10 |
11 | 12 |
{{ product.name }}
13 |
14 | {{ product.price | currency: "INR" }} 15 |
16 |
17 | -------------------------------------------------------------------------------- /client/src/app/store/product-items/product-items.component.scss: -------------------------------------------------------------------------------- 1 | .btn { 2 | width: 30%; 3 | height: 40px; 4 | } 5 | 6 | .image :hover { 7 | opacity: 1; 8 | & button { 9 | transform: none; 10 | opacity: 1; 11 | } 12 | } 13 | 14 | .hover-overlay { 15 | position: absolute; 16 | width: 100%; 17 | height: 100%; 18 | top: 0; 19 | left: 0; 20 | background: rgba(255, 255, 255, 0.5); 21 | opacity: 0; 22 | transition: all 0.5s; 23 | 24 | & button { 25 | z-index: 1000; 26 | transition: all 0.5s; 27 | } 28 | 29 | & button:first-of-type { 30 | transform: translateX(-20px); 31 | } 32 | 33 | & button:last-of-type { 34 | transform: translateX(20px); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /client/src/app/store/product-items/product-items.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core'; 2 | import { BasketService } from 'src/app/basket/basket.service'; 3 | import { IProduct } from 'src/app/shared/models/product'; 4 | 5 | @Component({ 6 | selector: 'app-product-items', 7 | templateUrl: './product-items.component.html', 8 | styleUrls: ['./product-items.component.scss'] 9 | }) 10 | export class ProductItemsComponent { 11 | @Input() product?: IProduct; 12 | 13 | constructor(private basketService: BasketService){} 14 | 15 | addItemToBasket(){ 16 | this.product && this.basketService.addItemToBasket(this.product); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /client/src/app/store/store-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { StoreComponent } from './store.component'; 4 | import { ProductDetailsComponent } from './product-details/product-details.component'; 5 | 6 | const routes:Routes = [ 7 | {path:'', component: StoreComponent}, 8 | {path:':id', component: ProductDetailsComponent, data:{breadcrumb:{alias:'productDetails'}}} 9 | ] 10 | 11 | @NgModule({ 12 | declarations: [], 13 | imports: [ 14 | RouterModule.forChild(routes) 15 | ], 16 | exports:[ 17 | RouterModule 18 | ] 19 | }) 20 | export class StoreRoutingModule { } 21 | -------------------------------------------------------------------------------- /client/src/app/store/store.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/app/store/store.component.scss -------------------------------------------------------------------------------- /client/src/app/store/store.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { StoreComponent } from './store.component'; 4 | import { ProductItemsComponent } from './product-items/product-items.component'; 5 | import { SharedModule } from '../shared/shared.module'; 6 | import { ProductDetailsComponent } from './product-details/product-details.component'; 7 | import { StoreRoutingModule } from './store-routing.module'; 8 | 9 | 10 | @NgModule({ 11 | declarations: [ 12 | StoreComponent, 13 | ProductItemsComponent, 14 | ProductDetailsComponent 15 | ], 16 | imports: [ 17 | CommonModule, 18 | SharedModule, 19 | StoreRoutingModule 20 | ] 21 | }) 22 | export class StoreModule { } 23 | -------------------------------------------------------------------------------- /client/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/assets/.gitkeep -------------------------------------------------------------------------------- /client/src/assets/images/bslide1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/assets/images/bslide1.jpg -------------------------------------------------------------------------------- /client/src/assets/images/bslide2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/assets/images/bslide2.jpg -------------------------------------------------------------------------------- /client/src/assets/images/bslide3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/assets/images/bslide3.jpg -------------------------------------------------------------------------------- /client/src/assets/images/hero1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/assets/images/hero1.jpg -------------------------------------------------------------------------------- /client/src/assets/images/hero2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/assets/images/hero2.jpg -------------------------------------------------------------------------------- /client/src/assets/images/hero3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/assets/images/hero3.jpg -------------------------------------------------------------------------------- /client/src/assets/images/hero4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/assets/images/hero4.jpg -------------------------------------------------------------------------------- /client/src/assets/images/hero5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/assets/images/hero5.jpg -------------------------------------------------------------------------------- /client/src/assets/images/hero6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/assets/images/hero6.jpg -------------------------------------------------------------------------------- /client/src/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/assets/images/logo.png -------------------------------------------------------------------------------- /client/src/assets/images/logo_old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/assets/images/logo_old.png -------------------------------------------------------------------------------- /client/src/assets/images/open-identity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/assets/images/open-identity.png -------------------------------------------------------------------------------- /client/src/assets/silent-callback.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Silent-Callback 10 | 11 | 12 | 13 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /client/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/favicon.ico -------------------------------------------------------------------------------- /client/src/images/products/Nike-Football-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/Nike-Football-1.png -------------------------------------------------------------------------------- /client/src/images/products/Nike-Football-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/Nike-Football-2.png -------------------------------------------------------------------------------- /client/src/images/products/Nike-Football-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/Nike-Football-3.png -------------------------------------------------------------------------------- /client/src/images/products/adidas_football-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/adidas_football-1.png -------------------------------------------------------------------------------- /client/src/images/products/adidas_football-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/adidas_football-2.png -------------------------------------------------------------------------------- /client/src/images/products/adidas_football-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/adidas_football-3.png -------------------------------------------------------------------------------- /client/src/images/products/adidas_shoe-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/adidas_shoe-1.png -------------------------------------------------------------------------------- /client/src/images/products/adidas_shoe-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/adidas_shoe-2.png -------------------------------------------------------------------------------- /client/src/images/products/adidas_shoe-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/adidas_shoe-3.png -------------------------------------------------------------------------------- /client/src/images/products/asics_shoe-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/asics_shoe-1.png -------------------------------------------------------------------------------- /client/src/images/products/asics_shoe-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/asics_shoe-2.png -------------------------------------------------------------------------------- /client/src/images/products/asics_shoe-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/asics_shoe-3.png -------------------------------------------------------------------------------- /client/src/images/products/babolat-kitback-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/babolat-kitback-1.png -------------------------------------------------------------------------------- /client/src/images/products/babolat-kitback-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/babolat-kitback-2.png -------------------------------------------------------------------------------- /client/src/images/products/babolat-kitback-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/babolat-kitback-3.png -------------------------------------------------------------------------------- /client/src/images/products/babolat-racket-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/babolat-racket-1.png -------------------------------------------------------------------------------- /client/src/images/products/babolat-racket-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/babolat-racket-2.png -------------------------------------------------------------------------------- /client/src/images/products/babolat-racket-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/babolat-racket-3.png -------------------------------------------------------------------------------- /client/src/images/products/babolat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/babolat.png -------------------------------------------------------------------------------- /client/src/images/products/babolat_shoe-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/babolat_shoe-1.png -------------------------------------------------------------------------------- /client/src/images/products/babolat_shoe-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/babolat_shoe-2.png -------------------------------------------------------------------------------- /client/src/images/products/babolat_shoe-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/babolat_shoe-3.png -------------------------------------------------------------------------------- /client/src/images/products/puma_shoe-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/puma_shoe-1.png -------------------------------------------------------------------------------- /client/src/images/products/puma_shoe-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/puma_shoe-2.png -------------------------------------------------------------------------------- /client/src/images/products/puma_shoe-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/puma_shoe-3.png -------------------------------------------------------------------------------- /client/src/images/products/victor-racket-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/victor-racket-1.png -------------------------------------------------------------------------------- /client/src/images/products/victor-racket-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/victor-racket-2.png -------------------------------------------------------------------------------- /client/src/images/products/victor-racket-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/victor-racket-3.png -------------------------------------------------------------------------------- /client/src/images/products/victor_shoe-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/victor_shoe-1.png -------------------------------------------------------------------------------- /client/src/images/products/victor_shoe-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/victor_shoe-2.png -------------------------------------------------------------------------------- /client/src/images/products/yonex-badminton-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/yonex-badminton-1.png -------------------------------------------------------------------------------- /client/src/images/products/yonex-badminton-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/yonex-badminton-2.png -------------------------------------------------------------------------------- /client/src/images/products/yonex-badminton-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/yonex-badminton-3.png -------------------------------------------------------------------------------- /client/src/images/products/yonex-kitback-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/yonex-kitback-1.png -------------------------------------------------------------------------------- /client/src/images/products/yonex-kitback-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/yonex-kitback-2.png -------------------------------------------------------------------------------- /client/src/images/products/yonex-kitback-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/yonex-kitback-3.png -------------------------------------------------------------------------------- /client/src/images/products/yonex-racket-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/yonex-racket-1.png -------------------------------------------------------------------------------- /client/src/images/products/yonex-racket-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/yonex-racket-2.png -------------------------------------------------------------------------------- /client/src/images/products/yonex-racket-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/yonex-racket-3.png -------------------------------------------------------------------------------- /client/src/images/products/yonex_shoe-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/yonex_shoe-1.png -------------------------------------------------------------------------------- /client/src/images/products/yonex_shoe-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/yonex_shoe-2.png -------------------------------------------------------------------------------- /client/src/images/products/yonex_shoe-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rahulsahay19/dot-net-core-microservices-8/7416628fa067d080a7653afc49ab51a0cdcd7324/client/src/images/products/yonex_shoe-3.png -------------------------------------------------------------------------------- /client/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Client 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /client/src/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | 3 | import { AppModule } from './app/app.module'; 4 | 5 | 6 | platformBrowserDynamic().bootstrapModule(AppModule) 7 | .catch(err => console.error(err)); 8 | -------------------------------------------------------------------------------- /client/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | .xng-breadcrumb-root { 3 | padding: 8px 16px; 4 | display: inline; 5 | border-radius: 0; 6 | } 7 | 8 | label.xng-breadcrumb-trail { 9 | margin-bottom: 0; 10 | color: blue; 11 | } 12 | 13 | .xng-breadcrumb-separator { 14 | padding: 0 0; 15 | } 16 | -------------------------------------------------------------------------------- /client/target/npmlist.json: -------------------------------------------------------------------------------- 1 | {"version":"0.0.0","name":"client","dependencies":{"@angular/animations":{"version":"14.2.12"},"@angular/common":{"version":"14.2.12"},"@angular/compiler":{"version":"14.2.12"},"@angular/core":{"version":"14.2.12"},"@angular/forms":{"version":"14.2.12"},"@angular/platform-browser-dynamic":{"version":"14.2.12"},"@angular/platform-browser":{"version":"14.2.12"},"@angular/router":{"version":"14.2.12"},"bootstrap":{"version":"5.2.3"},"font-awesome":{"version":"4.7.0"},"ngx-bootstrap":{"version":"6.2.0"},"ngx-spinner":{"version":"14.0.0"},"oidc-client":{"version":"1.11.5"},"rxjs":{"version":"7.5.7"},"tslib":{"version":"2.5.0"},"xng-breadcrumb":{"version":"9.0.0"},"zone.js":{"version":"0.12.0"}}} -------------------------------------------------------------------------------- /client/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts", 10 | "src/polyfills.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /client/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "strictNullChecks":false, 10 | "noImplicitOverride": true, 11 | "noPropertyAccessFromIndexSignature": true, 12 | "noImplicitReturns": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "sourceMap": true, 15 | "declaration": false, 16 | "downlevelIteration": true, 17 | "experimentalDecorators": true, 18 | "moduleResolution": "node", 19 | "importHelpers": true, 20 | "target": "ES2022", 21 | "module": "ES2022", 22 | "useDefineForClassFields": false, 23 | "lib": [ 24 | "ES2022", 25 | "dom" 26 | ] 27 | }, 28 | "angularCompilerOptions": { 29 | "enableI18nLegacyMessageIdFormat": false, 30 | "strictInjectionParameters": true, 31 | "strictInputAccessModifiers": true, 32 | "strictTemplates": true 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /client/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /docker-compose.dcproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2.1 5 | Linux 6 | False 7 | ace1ab99-c274-4066-9cd1-f9b996536801 8 | LaunchBrowser 9 | {Scheme}://localhost:{ServicePort}/swagger 10 | catalog.api 11 | 12 | 13 | 14 | docker-compose.yml 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Docker Compose": { 4 | "commandName": "DockerCompose", 5 | "commandVersion": "1.0", 6 | "serviceActions": { 7 | "catalog.api": "StartDebugging", 8 | "basket.api": "StartDebugging", 9 | "discount.api": "StartDebugging", 10 | "ordering.api": "StartDebugging", 11 | "ocelot.apigateway": "StartDebugging" 12 | } 13 | } 14 | } 15 | } --------------------------------------------------------------------------------