├── .github └── workflows │ ├── deploy-auth.yml │ ├── deploy-client.yml │ ├── deploy-expiration.yml │ ├── deploy-manifests.yml │ ├── deploy-orders.yml │ ├── deploy-payments.yml │ ├── deploy-tickets.yml │ ├── tests-auth.yml │ ├── tests-orders.yml │ ├── tests-payments.yml │ └── tests-tickets.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── 02_A_Mini_Microservices_App.md ├── 02_A_Mini_Microservices_App └── app │ ├── client │ ├── .gitignore │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── manifest.json │ │ └── robots.txt │ └── src │ │ ├── App.js │ │ ├── CommentCreate.js │ │ ├── CommentList.js │ │ ├── PostCreate.js │ │ ├── PostList.js │ │ └── index.js │ ├── comments │ ├── index.js │ ├── package-lock.json │ └── package.json │ ├── event-bus │ ├── index.js │ ├── package-lock.json │ └── package.json │ ├── moderation │ ├── index.js │ ├── package-lock.json │ └── package.json │ ├── posts │ ├── index.js │ ├── package-lock.json │ └── package.json │ └── query │ ├── index.js │ ├── package-lock.json │ └── package.json ├── 04_Orchestrating_Collections_of_Services_with_Kubernetes.md ├── 04_Orchestrating_Collections_of_Services_with_Kubernetes ├── app │ ├── client │ │ ├── .dockerignore │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── public │ │ │ ├── favicon.ico │ │ │ ├── index.html │ │ │ ├── manifest.json │ │ │ └── robots.txt │ │ └── src │ │ │ ├── App.js │ │ │ ├── CommentCreate.js │ │ │ ├── CommentList.js │ │ │ ├── PostCreate.js │ │ │ ├── PostList.js │ │ │ └── index.js │ ├── comments │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── index.js │ │ ├── package-lock.json │ │ └── package.json │ ├── event-bus │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── index.js │ │ ├── package-lock.json │ │ └── package.json │ ├── moderation │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── index.js │ │ ├── package-lock.json │ │ └── package.json │ ├── posts │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── index.js │ │ ├── package-lock.json │ │ └── package.json │ └── query │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── index.js │ │ ├── package-lock.json │ │ └── package.json ├── k8s │ ├── client-depl.yaml │ ├── client-srv-ClusterIP.yaml │ ├── comments-depl.yaml │ ├── comments-srv-ClusterIP.yaml │ ├── event-bus-depl.yaml │ ├── event-bus-srv-ClusterIP.yaml │ ├── ingress-srv.yaml │ ├── moderation-depl.yaml │ ├── moderation-srv-ClusterIP.yaml │ ├── posts-depl.yaml │ ├── posts-srv-ClusterIP.yaml │ ├── query-depl.yaml │ └── query-srv-ClusterIP.yaml └── skaffold │ └── skaffold.yaml ├── 05_Architecture_of_Multi_Service_Apps.md ├── 05_Architecture_of_Multi_Service_Apps ├── app │ └── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ └── index.ts │ │ └── tsconfig.json ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ └── ingress-controller.yaml └── skaffold │ └── skaffold.yaml ├── 07_Response_Normalization_Strategies.md ├── 07_Response_Normalization_Strategies ├── app │ └── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── errors │ │ │ ├── custom-error.ts │ │ │ ├── database-connectionerror.ts │ │ │ ├── not-found-error.ts │ │ │ └── request-validation-error.ts │ │ ├── index.ts │ │ ├── middlewares │ │ │ └── error-handler.ts │ │ └── routes │ │ │ ├── current-user.ts │ │ │ ├── signin.ts │ │ │ ├── signout.ts │ │ │ └── signup.ts │ │ └── tsconfig.json ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ └── ingress-controller.yaml └── skaffold │ └── skaffold.yaml ├── 08_Database Management_and_Modeling ├── app │ └── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── errors │ │ │ ├── bad-request-error.ts │ │ │ ├── custom-error.ts │ │ │ ├── database-connectionerror.ts │ │ │ ├── not-found-error.ts │ │ │ └── request-validation-error.ts │ │ ├── index.ts │ │ ├── middlewares │ │ │ └── error-handler.ts │ │ ├── models │ │ │ └── User.ts │ │ ├── routes │ │ │ ├── current-user.ts │ │ │ ├── signin.ts │ │ │ ├── signout.ts │ │ │ └── signup.ts │ │ └── services │ │ │ └── password.ts │ │ └── tsconfig.json ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ ├── auth-mongo-clusterIP.yaml │ ├── auth-mongo-deployment.yaml │ └── ingress-controller.yaml └── skaffold │ └── skaffold.yaml ├── 08_Database_Management_and_Modeling.md ├── 09_Authentication_Strategies_and_Options.md ├── 09_Authentication_Strategies_and_Options ├── app │ └── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── errors │ │ │ ├── bad-request-error.ts │ │ │ ├── custom-error.ts │ │ │ ├── database-connectionerror.ts │ │ │ ├── not-authorized-error.ts │ │ │ ├── not-found-error.ts │ │ │ └── request-validation-error.ts │ │ ├── index.ts │ │ ├── middlewares │ │ │ ├── current-user.ts │ │ │ ├── error-handler.ts │ │ │ ├── require-auth.ts │ │ │ └── validate-request.ts │ │ ├── models │ │ │ └── User.ts │ │ ├── routes │ │ │ ├── current-user.ts │ │ │ ├── signin.ts │ │ │ ├── signout.ts │ │ │ └── signup.ts │ │ └── services │ │ │ └── password.ts │ │ └── tsconfig.json ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ ├── auth-mongo-clusterIP.yaml │ ├── auth-mongo-deployment.yaml │ └── ingress-controller.yaml └── skaffold │ └── skaffold.yaml ├── 10_Testing_Isolated_Microservices.md ├── 10_Testing_Isolated_Microservices ├── app │ └── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── app.ts │ │ ├── errors │ │ │ ├── bad-request-error.ts │ │ │ ├── custom-error.ts │ │ │ ├── database-connectionerror.ts │ │ │ ├── not-authorized-error.ts │ │ │ ├── not-found-error.ts │ │ │ └── request-validation-error.ts │ │ ├── index.ts │ │ ├── middlewares │ │ │ ├── current-user.ts │ │ │ ├── error-handler.ts │ │ │ ├── require-auth.ts │ │ │ └── validate-request.ts │ │ ├── models │ │ │ └── User.ts │ │ ├── routes │ │ │ ├── __test__ │ │ │ │ ├── current-user.test.ts │ │ │ │ ├── signin.test.ts │ │ │ │ ├── signout.test.ts │ │ │ │ └── signup.test.ts │ │ │ ├── current-user.ts │ │ │ ├── signin.ts │ │ │ ├── signout.ts │ │ │ └── signup.ts │ │ ├── services │ │ │ └── password.ts │ │ └── test │ │ │ └── setup.ts │ │ └── tsconfig.json ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ ├── auth-mongo-clusterIP.yaml │ ├── auth-mongo-deployment.yaml │ └── ingress-controller.yaml └── skaffold │ └── skaffold.yaml ├── 11_Integrating_a_Server_Side_Rendered_React_App.md ├── 11_Integrating_a_Server_Side_Rendered_React_App ├── app │ ├── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app.ts │ │ │ ├── errors │ │ │ │ ├── bad-request-error.ts │ │ │ │ ├── custom-error.ts │ │ │ │ ├── database-connectionerror.ts │ │ │ │ ├── not-authorized-error.ts │ │ │ │ ├── not-found-error.ts │ │ │ │ └── request-validation-error.ts │ │ │ ├── index.ts │ │ │ ├── middlewares │ │ │ │ ├── current-user.ts │ │ │ │ ├── error-handler.ts │ │ │ │ ├── require-auth.ts │ │ │ │ └── validate-request.ts │ │ │ ├── models │ │ │ │ └── User.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── current-user.test.ts │ │ │ │ │ ├── signin.test.ts │ │ │ │ │ ├── signout.test.ts │ │ │ │ │ └── signup.test.ts │ │ │ │ ├── current-user.ts │ │ │ │ ├── signin.ts │ │ │ │ ├── signout.ts │ │ │ │ └── signup.ts │ │ │ ├── services │ │ │ │ └── password.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ └── client │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── api │ │ └── build-client.js │ │ ├── components │ │ └── Header.js │ │ ├── hooks │ │ └── use-request.js │ │ ├── next.config.js │ │ ├── package-lock.json │ │ ├── package.json │ │ └── pages │ │ ├── _app.js │ │ ├── auth │ │ ├── signin.js │ │ ├── signout.js │ │ └── signup.js │ │ └── index.js ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ ├── auth-mongo-clusterIP.yaml │ ├── auth-mongo-deployment.yaml │ ├── client-clusterIP.yaml │ ├── client-deployment.yaml │ └── ingress-controller.yaml └── skaffold │ └── skaffold.yaml ├── 12_Code_Sharing_and_Reuse_Between_Services.md ├── 12_Code_Sharing_and_Reuse_Between_Services ├── app │ ├── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ └── User.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── current-user.test.ts │ │ │ │ │ ├── signin.test.ts │ │ │ │ │ ├── signout.test.ts │ │ │ │ │ └── signup.test.ts │ │ │ │ ├── current-user.ts │ │ │ │ ├── signin.ts │ │ │ │ ├── signout.ts │ │ │ │ └── signup.ts │ │ │ ├── services │ │ │ │ └── password.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ ├── client │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── api │ │ │ └── build-client.js │ │ ├── components │ │ │ └── Header.js │ │ ├── hooks │ │ │ └── use-request.js │ │ ├── next.config.js │ │ ├── package-lock.json │ │ ├── package.json │ │ └── pages │ │ │ ├── _app.js │ │ │ ├── auth │ │ │ ├── signin.js │ │ │ ├── signout.js │ │ │ └── signup.js │ │ │ └── index.js │ └── common │ │ ├── .gitignore │ │ ├── build │ │ ├── index.d.ts │ │ └── index.js │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── errors │ │ │ ├── bad-request-error.ts │ │ │ ├── custom-error.ts │ │ │ ├── database-connection-error.ts │ │ │ ├── not-authorized-error.ts │ │ │ ├── not-found-error.ts │ │ │ └── request-validation-error.ts │ │ ├── index.ts │ │ └── middlewares │ │ │ ├── current-user.ts │ │ │ ├── error-handler.ts │ │ │ ├── require-auth.ts │ │ │ └── validate-request.ts │ │ └── tsconfig.json ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ ├── auth-mongo-clusterIP.yaml │ ├── auth-mongo-deployment.yaml │ ├── client-clusterIP.yaml │ ├── client-deployment.yaml │ └── ingress-controller.yaml └── skaffold │ └── skaffold.yaml ├── 13_Create_Read_Update_Destroy_Server_Setup.md ├── 13_Create_Read_Update_Destroy_Server_Setup ├── app │ ├── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ └── User.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── current-user.test.ts │ │ │ │ │ ├── signin.test.ts │ │ │ │ │ ├── signout.test.ts │ │ │ │ │ └── signup.test.ts │ │ │ │ ├── current-user.ts │ │ │ │ ├── signin.ts │ │ │ │ ├── signout.ts │ │ │ │ └── signup.ts │ │ │ ├── services │ │ │ │ └── password.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ ├── client │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── api │ │ │ └── build-client.js │ │ ├── components │ │ │ └── Header.js │ │ ├── hooks │ │ │ └── use-request.js │ │ ├── next.config.js │ │ ├── package-lock.json │ │ ├── package.json │ │ └── pages │ │ │ ├── _app.js │ │ │ ├── auth │ │ │ ├── signin.js │ │ │ ├── signout.js │ │ │ └── signup.js │ │ │ └── index.js │ ├── common │ │ ├── .gitignore │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── errors │ │ │ │ ├── bad-request-error.ts │ │ │ │ ├── custom-error.ts │ │ │ │ ├── database-connection-error.ts │ │ │ │ ├── not-authorized-error.ts │ │ │ │ ├── not-found-error.ts │ │ │ │ └── request-validation-error.ts │ │ │ ├── index.ts │ │ │ └── middlewares │ │ │ │ ├── current-user.ts │ │ │ │ ├── error-handler.ts │ │ │ │ ├── require-auth.ts │ │ │ │ └── validate-request.ts │ │ └── tsconfig.json │ └── tickets │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── app.ts │ │ ├── index.ts │ │ ├── models │ │ │ └── Ticket.ts │ │ ├── routes │ │ │ ├── __test__ │ │ │ │ ├── index.test.ts │ │ │ │ ├── new.test.ts │ │ │ │ ├── show.test.ts │ │ │ │ └── update.test.ts │ │ │ ├── index.ts │ │ │ ├── new.ts │ │ │ ├── show.ts │ │ │ └── update.ts │ │ └── test │ │ │ └── setup.ts │ │ └── tsconfig.json ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ ├── auth-mongo-clusterIP.yaml │ ├── auth-mongo-deployment.yaml │ ├── client-clusterIP.yaml │ ├── client-deployment.yaml │ ├── ingress-controller.yaml │ ├── tickets-clusterIP.yaml │ ├── tickets-deployment.yaml │ ├── tickets-mongo-clusterIP.yaml │ └── tickets-mongo-deployment.yaml └── skaffold │ └── skaffold.yaml ├── 14_NATS_Streaming_Server_An_Event_Bus_Implementation.md ├── 14_NATS_Streaming_Server_An_Event_Bus_Implementation ├── app │ ├── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ └── User.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── current-user.test.ts │ │ │ │ │ ├── signin.test.ts │ │ │ │ │ ├── signout.test.ts │ │ │ │ │ └── signup.test.ts │ │ │ │ ├── current-user.ts │ │ │ │ ├── signin.ts │ │ │ │ ├── signout.ts │ │ │ │ └── signup.ts │ │ │ ├── services │ │ │ │ └── password.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ ├── client │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── api │ │ │ └── build-client.js │ │ ├── components │ │ │ └── Header.js │ │ ├── hooks │ │ │ └── use-request.js │ │ ├── next.config.js │ │ ├── package-lock.json │ │ ├── package.json │ │ └── pages │ │ │ ├── _app.js │ │ │ ├── auth │ │ │ ├── signin.js │ │ │ ├── signout.js │ │ │ └── signup.js │ │ │ └── index.js │ ├── common │ │ ├── .gitignore │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── errors │ │ │ │ ├── bad-request-error.ts │ │ │ │ ├── custom-error.ts │ │ │ │ ├── database-connection-error.ts │ │ │ │ ├── not-authorized-error.ts │ │ │ │ ├── not-found-error.ts │ │ │ │ └── request-validation-error.ts │ │ │ ├── index.ts │ │ │ └── middlewares │ │ │ │ ├── current-user.ts │ │ │ │ ├── error-handler.ts │ │ │ │ ├── require-auth.ts │ │ │ │ └── validate-request.ts │ │ └── tsconfig.json │ ├── nats-test │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── listener.ts │ │ │ └── publisher.ts │ │ └── tsconfig.json │ └── tickets │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── app.ts │ │ ├── index.ts │ │ ├── models │ │ │ └── Ticket.ts │ │ ├── routes │ │ │ ├── __test__ │ │ │ │ ├── index.test.ts │ │ │ │ ├── new.test.ts │ │ │ │ ├── show.test.ts │ │ │ │ └── update.test.ts │ │ │ ├── index.ts │ │ │ ├── new.ts │ │ │ ├── show.ts │ │ │ └── update.ts │ │ └── test │ │ │ └── setup.ts │ │ └── tsconfig.json ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ ├── auth-mongo-clusterIP.yaml │ ├── auth-mongo-deployment.yaml │ ├── client-clusterIP.yaml │ ├── client-deployment.yaml │ ├── ingress-controller.yaml │ ├── nats-clusterIP.yaml │ ├── nats-deployment.yaml │ ├── tickets-clusterIP.yaml │ ├── tickets-deployment.yaml │ ├── tickets-mongo-clusterIP.yaml │ └── tickets-mongo-deployment.yaml └── skaffold │ └── skaffold.yaml ├── 15_Connecting_to_NATS_in_a_Node_JS_World.md ├── 15_Connecting_to_NATS_in_a_Node_JS_World ├── app │ ├── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ └── User.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── current-user.test.ts │ │ │ │ │ ├── signin.test.ts │ │ │ │ │ ├── signout.test.ts │ │ │ │ │ └── signup.test.ts │ │ │ │ ├── current-user.ts │ │ │ │ ├── signin.ts │ │ │ │ ├── signout.ts │ │ │ │ └── signup.ts │ │ │ ├── services │ │ │ │ └── password.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ ├── client │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── api │ │ │ └── build-client.js │ │ ├── components │ │ │ └── Header.js │ │ ├── hooks │ │ │ └── use-request.js │ │ ├── next.config.js │ │ ├── package-lock.json │ │ ├── package.json │ │ └── pages │ │ │ ├── _app.js │ │ │ ├── auth │ │ │ ├── signin.js │ │ │ ├── signout.js │ │ │ └── signup.js │ │ │ └── index.js │ ├── common │ │ ├── .gitignore │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── errors │ │ │ │ ├── bad-request-error.ts │ │ │ │ ├── custom-error.ts │ │ │ │ ├── database-connection-error.ts │ │ │ │ ├── not-authorized-error.ts │ │ │ │ ├── not-found-error.ts │ │ │ │ └── request-validation-error.ts │ │ │ ├── events │ │ │ │ ├── ListenerAbstract.ts │ │ │ │ ├── PublisherAbstract.ts │ │ │ │ ├── SubjectsEnum.ts │ │ │ │ ├── TicketCreatedEventInterface.ts │ │ │ │ └── TicketUpdatedEventInterface.ts │ │ │ ├── index.ts │ │ │ └── middlewares │ │ │ │ ├── current-user.ts │ │ │ │ ├── error-handler.ts │ │ │ │ ├── require-auth.ts │ │ │ │ └── validate-request.ts │ │ └── tsconfig.json │ ├── nats-test │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── events │ │ │ │ ├── TicketCreatedListener.ts │ │ │ │ └── TicketCreatedPublisher.ts │ │ │ ├── listener.ts │ │ │ └── publisher.ts │ │ └── tsconfig.json │ └── tickets │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── app.ts │ │ ├── index.ts │ │ ├── models │ │ │ └── Ticket.ts │ │ ├── routes │ │ │ ├── __test__ │ │ │ │ ├── index.test.ts │ │ │ │ ├── new.test.ts │ │ │ │ ├── show.test.ts │ │ │ │ └── update.test.ts │ │ │ ├── index.ts │ │ │ ├── new.ts │ │ │ ├── show.ts │ │ │ └── update.ts │ │ └── test │ │ │ └── setup.ts │ │ └── tsconfig.json ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ ├── auth-mongo-clusterIP.yaml │ ├── auth-mongo-deployment.yaml │ ├── client-clusterIP.yaml │ ├── client-deployment.yaml │ ├── ingress-controller.yaml │ ├── nats-clusterIP.yaml │ ├── nats-deployment.yaml │ ├── tickets-clusterIP.yaml │ ├── tickets-deployment.yaml │ ├── tickets-mongo-clusterIP.yaml │ └── tickets-mongo-deployment.yaml └── skaffold │ └── skaffold.yaml ├── 16_Managing_a_NATS_Client.md ├── 16_Managing_a_NATS_Client ├── app │ ├── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ └── User.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── current-user.test.ts │ │ │ │ │ ├── signin.test.ts │ │ │ │ │ ├── signout.test.ts │ │ │ │ │ └── signup.test.ts │ │ │ │ ├── current-user.ts │ │ │ │ ├── signin.ts │ │ │ │ ├── signout.ts │ │ │ │ └── signup.ts │ │ │ ├── services │ │ │ │ └── password.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ ├── client │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── api │ │ │ └── build-client.js │ │ ├── components │ │ │ └── Header.js │ │ ├── hooks │ │ │ └── use-request.js │ │ ├── next.config.js │ │ ├── package-lock.json │ │ ├── package.json │ │ └── pages │ │ │ ├── _app.js │ │ │ ├── auth │ │ │ ├── signin.js │ │ │ ├── signout.js │ │ │ └── signup.js │ │ │ └── index.js │ ├── common │ │ ├── .gitignore │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── errors │ │ │ │ ├── bad-request-error.ts │ │ │ │ ├── custom-error.ts │ │ │ │ ├── database-connection-error.ts │ │ │ │ ├── not-authorized-error.ts │ │ │ │ ├── not-found-error.ts │ │ │ │ └── request-validation-error.ts │ │ │ ├── events │ │ │ │ ├── ListenerAbstract.ts │ │ │ │ ├── PublisherAbstract.ts │ │ │ │ ├── SubjectsEnum.ts │ │ │ │ ├── TicketCreatedEventInterface.ts │ │ │ │ └── TicketUpdatedEventInterface.ts │ │ │ ├── index.ts │ │ │ └── middlewares │ │ │ │ ├── current-user.ts │ │ │ │ ├── error-handler.ts │ │ │ │ ├── require-auth.ts │ │ │ │ └── validate-request.ts │ │ └── tsconfig.json │ ├── nats-test │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── events │ │ │ │ ├── TicketCreatedListener.ts │ │ │ │ └── TicketCreatedPublisher.ts │ │ │ ├── listener.ts │ │ │ └── publisher.ts │ │ └── tsconfig.json │ └── tickets │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── NatsWrapper.ts │ │ ├── __mocks__ │ │ │ └── NatsWrapper.ts │ │ ├── app.ts │ │ ├── events │ │ │ └── publishers │ │ │ │ ├── TicketCreatedPublisher.ts │ │ │ │ └── TicketUpdatedPublisher.ts │ │ ├── index.ts │ │ ├── models │ │ │ └── Ticket.ts │ │ ├── routes │ │ │ ├── __test__ │ │ │ │ ├── index.test.ts │ │ │ │ ├── new.test.ts │ │ │ │ ├── show.test.ts │ │ │ │ └── update.test.ts │ │ │ ├── index.ts │ │ │ ├── new.ts │ │ │ ├── show.ts │ │ │ └── update.ts │ │ └── test │ │ │ └── setup.ts │ │ └── tsconfig.json ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ ├── auth-mongo-clusterIP.yaml │ ├── auth-mongo-deployment.yaml │ ├── client-clusterIP.yaml │ ├── client-deployment.yaml │ ├── ingress-controller.yaml │ ├── nats-clusterIP.yaml │ ├── nats-deployment.yaml │ ├── tickets-clusterIP.yaml │ ├── tickets-deployment.yaml │ ├── tickets-mongo-clusterIP.yaml │ └── tickets-mongo-deployment.yaml └── skaffold │ └── skaffold.yaml ├── 17_Cross_Service_Data_Replication_In_Action.md ├── 17_Cross_Service_Data_Replication_In_Action ├── app │ ├── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ └── User.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── current-user.test.ts │ │ │ │ │ ├── signin.test.ts │ │ │ │ │ ├── signout.test.ts │ │ │ │ │ └── signup.test.ts │ │ │ │ ├── current-user.ts │ │ │ │ ├── signin.ts │ │ │ │ ├── signout.ts │ │ │ │ └── signup.ts │ │ │ ├── services │ │ │ │ └── password.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ ├── client │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── api │ │ │ └── build-client.js │ │ ├── components │ │ │ └── Header.js │ │ ├── hooks │ │ │ └── use-request.js │ │ ├── next.config.js │ │ ├── package-lock.json │ │ ├── package.json │ │ └── pages │ │ │ ├── _app.js │ │ │ ├── auth │ │ │ ├── signin.js │ │ │ ├── signout.js │ │ │ └── signup.js │ │ │ └── index.js │ ├── common │ │ ├── .gitignore │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── errors │ │ │ │ ├── bad-request-error.ts │ │ │ │ ├── custom-error.ts │ │ │ │ ├── database-connection-error.ts │ │ │ │ ├── not-authorized-error.ts │ │ │ │ ├── not-found-error.ts │ │ │ │ └── request-validation-error.ts │ │ │ ├── events │ │ │ │ ├── ListenerAbstract.ts │ │ │ │ ├── PublisherAbstract.ts │ │ │ │ ├── SubjectsEnum.ts │ │ │ │ ├── TicketCreatedEventInterface.ts │ │ │ │ ├── TicketUpdatedEventInterface.ts │ │ │ │ └── types │ │ │ │ │ └── OrderStatus.ts │ │ │ ├── index.ts │ │ │ └── middlewares │ │ │ │ ├── current-user.ts │ │ │ │ ├── error-handler.ts │ │ │ │ ├── require-auth.ts │ │ │ │ └── validate-request.ts │ │ └── tsconfig.json │ ├── nats-test │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── events │ │ │ │ ├── TicketCreatedListener.ts │ │ │ │ └── TicketCreatedPublisher.ts │ │ │ ├── listener.ts │ │ │ └── publisher.ts │ │ └── tsconfig.json │ ├── orders │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── NatsWrapper.ts │ │ │ ├── __mocks__ │ │ │ │ └── NatsWrapper.ts │ │ │ ├── app.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── Order.ts │ │ │ │ └── Ticket.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── delete.test.ts │ │ │ │ │ ├── index.test.ts │ │ │ │ │ ├── new.test.ts │ │ │ │ │ └── show.test.ts │ │ │ │ ├── delete.ts │ │ │ │ ├── index.ts │ │ │ │ ├── new.ts │ │ │ │ └── show.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ └── tickets │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── NatsWrapper.ts │ │ ├── __mocks__ │ │ │ └── NatsWrapper.ts │ │ ├── app.ts │ │ ├── events │ │ │ └── publishers │ │ │ │ ├── TicketCreatedPublisher.ts │ │ │ │ └── TicketUpdatedPublisher.ts │ │ ├── index.ts │ │ ├── models │ │ │ └── Ticket.ts │ │ ├── routes │ │ │ ├── __test__ │ │ │ │ ├── index.test.ts │ │ │ │ ├── new.test.ts │ │ │ │ ├── show.test.ts │ │ │ │ └── update.test.ts │ │ │ ├── index.ts │ │ │ ├── new.ts │ │ │ ├── show.ts │ │ │ └── update.ts │ │ └── test │ │ │ └── setup.ts │ │ └── tsconfig.json ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ ├── auth-mongo-clusterIP.yaml │ ├── auth-mongo-deployment.yaml │ ├── client-clusterIP.yaml │ ├── client-deployment.yaml │ ├── ingress-controller.yaml │ ├── nats-clusterIP.yaml │ ├── nats-deployment.yaml │ ├── orders-clusterIP.yaml │ ├── orders-deployment.yaml │ ├── orders-mongo-clusterIP.yaml │ ├── orders-mongo-deployment.yaml │ ├── tickets-clusterIP.yaml │ ├── tickets-deployment.yaml │ ├── tickets-mongo-clusterIP.yaml │ └── tickets-mongo-deployment.yaml └── skaffold │ └── skaffold.yaml ├── 18_Understanding_Event_Flow.md ├── 18_Understanding_Event_Flow ├── app │ ├── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ └── User.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── current-user.test.ts │ │ │ │ │ ├── signin.test.ts │ │ │ │ │ ├── signout.test.ts │ │ │ │ │ └── signup.test.ts │ │ │ │ ├── current-user.ts │ │ │ │ ├── signin.ts │ │ │ │ ├── signout.ts │ │ │ │ └── signup.ts │ │ │ ├── services │ │ │ │ └── password.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ ├── client │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── api │ │ │ └── build-client.js │ │ ├── components │ │ │ └── Header.js │ │ ├── hooks │ │ │ └── use-request.js │ │ ├── next.config.js │ │ ├── package-lock.json │ │ ├── package.json │ │ └── pages │ │ │ ├── _app.js │ │ │ ├── auth │ │ │ ├── signin.js │ │ │ ├── signout.js │ │ │ └── signup.js │ │ │ └── index.js │ ├── common │ │ ├── .gitignore │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── errors │ │ │ │ ├── bad-request-error.ts │ │ │ │ ├── custom-error.ts │ │ │ │ ├── database-connection-error.ts │ │ │ │ ├── not-authorized-error.ts │ │ │ │ ├── not-found-error.ts │ │ │ │ └── request-validation-error.ts │ │ │ ├── events │ │ │ │ ├── ListenerAbstract.ts │ │ │ │ ├── OrderCancelledEventInterface.ts │ │ │ │ ├── OrderCreatedEventInterface.ts │ │ │ │ ├── PublisherAbstract.ts │ │ │ │ ├── SubjectsEnum.ts │ │ │ │ ├── TicketCreatedEventInterface.ts │ │ │ │ ├── TicketUpdatedEventInterface.ts │ │ │ │ └── types │ │ │ │ │ └── OrderStatusEnum.ts │ │ │ ├── index.ts │ │ │ └── middlewares │ │ │ │ ├── current-user.ts │ │ │ │ ├── error-handler.ts │ │ │ │ ├── require-auth.ts │ │ │ │ └── validate-request.ts │ │ └── tsconfig.json │ ├── nats-test │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── events │ │ │ │ ├── TicketCreatedListener.ts │ │ │ │ └── TicketCreatedPublisher.ts │ │ │ ├── listener.ts │ │ │ └── publisher.ts │ │ └── tsconfig.json │ ├── orders │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── NatsWrapper.ts │ │ │ ├── __mocks__ │ │ │ │ └── NatsWrapper.ts │ │ │ ├── app.ts │ │ │ ├── events │ │ │ │ └── publishers │ │ │ │ │ ├── OrderCancelledPublisher.ts │ │ │ │ │ └── OrderCreatedPublisher.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── Order.ts │ │ │ │ └── Ticket.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── delete.test.ts │ │ │ │ │ ├── index.test.ts │ │ │ │ │ ├── new.test.ts │ │ │ │ │ └── show.test.ts │ │ │ │ ├── delete.ts │ │ │ │ ├── index.ts │ │ │ │ ├── new.ts │ │ │ │ └── show.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ └── tickets │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── NatsWrapper.ts │ │ ├── __mocks__ │ │ │ └── NatsWrapper.ts │ │ ├── app.ts │ │ ├── events │ │ │ └── publishers │ │ │ │ ├── TicketCreatedPublisher.ts │ │ │ │ └── TicketUpdatedPublisher.ts │ │ ├── index.ts │ │ ├── models │ │ │ └── Ticket.ts │ │ ├── routes │ │ │ ├── __test__ │ │ │ │ ├── index.test.ts │ │ │ │ ├── new.test.ts │ │ │ │ ├── show.test.ts │ │ │ │ └── update.test.ts │ │ │ ├── index.ts │ │ │ ├── new.ts │ │ │ ├── show.ts │ │ │ └── update.ts │ │ └── test │ │ │ └── setup.ts │ │ └── tsconfig.json ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ ├── auth-mongo-clusterIP.yaml │ ├── auth-mongo-deployment.yaml │ ├── client-clusterIP.yaml │ ├── client-deployment.yaml │ ├── ingress-controller.yaml │ ├── nats-clusterIP.yaml │ ├── nats-deployment.yaml │ ├── orders-clusterIP.yaml │ ├── orders-deployment.yaml │ ├── orders-mongo-clusterIP.yaml │ ├── orders-mongo-deployment.yaml │ ├── tickets-clusterIP.yaml │ ├── tickets-deployment.yaml │ ├── tickets-mongo-clusterIP.yaml │ └── tickets-mongo-deployment.yaml └── skaffold │ └── skaffold.yaml ├── 19_Listening_for_Events_and_Handling_Concurrency_Issues.md ├── 19_Listening_for_Events_and_Handling_Concurrency_Issues ├── app │ ├── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ └── User.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── current-user.test.ts │ │ │ │ │ ├── signin.test.ts │ │ │ │ │ ├── signout.test.ts │ │ │ │ │ └── signup.test.ts │ │ │ │ ├── current-user.ts │ │ │ │ ├── signin.ts │ │ │ │ ├── signout.ts │ │ │ │ └── signup.ts │ │ │ ├── services │ │ │ │ └── password.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ ├── client │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── api │ │ │ └── build-client.js │ │ ├── components │ │ │ └── Header.js │ │ ├── hooks │ │ │ └── use-request.js │ │ ├── next.config.js │ │ ├── package-lock.json │ │ ├── package.json │ │ └── pages │ │ │ ├── _app.js │ │ │ ├── auth │ │ │ ├── signin.js │ │ │ ├── signout.js │ │ │ └── signup.js │ │ │ └── index.js │ ├── common │ │ ├── .gitignore │ │ ├── package.json │ │ ├── src │ │ │ ├── errors │ │ │ │ ├── bad-request-error.ts │ │ │ │ ├── custom-error.ts │ │ │ │ ├── database-connection-error.ts │ │ │ │ ├── not-authorized-error.ts │ │ │ │ ├── not-found-error.ts │ │ │ │ └── request-validation-error.ts │ │ │ ├── events │ │ │ │ ├── ListenerAbstract.ts │ │ │ │ ├── OrderCancelledEventInterface.ts │ │ │ │ ├── OrderCreatedEventInterface.ts │ │ │ │ ├── PublisherAbstract.ts │ │ │ │ ├── SubjectsEnum.ts │ │ │ │ ├── TicketCreatedEventInterface.ts │ │ │ │ ├── TicketUpdatedEventInterface.ts │ │ │ │ └── types │ │ │ │ │ └── OrderStatusEnum.ts │ │ │ ├── index.ts │ │ │ └── middlewares │ │ │ │ ├── current-user.ts │ │ │ │ ├── error-handler.ts │ │ │ │ ├── require-auth.ts │ │ │ │ └── validate-request.ts │ │ └── tsconfig.json │ ├── nats-test │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── events │ │ │ │ ├── TicketCreatedListener.ts │ │ │ │ └── TicketCreatedPublisher.ts │ │ │ ├── listener.ts │ │ │ └── publisher.ts │ │ └── tsconfig.json │ ├── orders │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── NatsWrapper.ts │ │ │ ├── __mocks__ │ │ │ │ └── NatsWrapper.ts │ │ │ ├── app.ts │ │ │ ├── events │ │ │ │ ├── listeners │ │ │ │ │ ├── TicketCreatedListener.ts │ │ │ │ │ ├── TicketUpdatedListener.ts │ │ │ │ │ ├── __test__ │ │ │ │ │ │ ├── TicketCreatedListener.test.ts │ │ │ │ │ │ └── TicketUpdatedLister.test.ts │ │ │ │ │ └── queueGroupName.ts │ │ │ │ └── publishers │ │ │ │ │ ├── OrderCancelledPublisher.ts │ │ │ │ │ └── OrderCreatedPublisher.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── Order.ts │ │ │ │ └── Ticket.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── delete.test.ts │ │ │ │ │ ├── index.test.ts │ │ │ │ │ ├── new.test.ts │ │ │ │ │ └── show.test.ts │ │ │ │ ├── delete.ts │ │ │ │ ├── index.ts │ │ │ │ ├── new.ts │ │ │ │ └── show.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ └── tickets │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── NatsWrapper.ts │ │ ├── __mocks__ │ │ │ └── NatsWrapper.ts │ │ ├── app.ts │ │ ├── events │ │ │ ├── listeners │ │ │ │ ├── OrderCancelledListener.ts │ │ │ │ ├── OrderCreatedListener.ts │ │ │ │ ├── __test__ │ │ │ │ │ ├── OrderCancelledListener.test.ts │ │ │ │ │ └── OrderCreatedListener.test.ts │ │ │ │ └── queueGroupName.ts │ │ │ └── publishers │ │ │ │ ├── TicketCreatedPublisher.ts │ │ │ │ └── TicketUpdatedPublisher.ts │ │ ├── index.ts │ │ ├── models │ │ │ ├── Ticket.ts │ │ │ └── __test__ │ │ │ │ └── Ticket.test.ts │ │ ├── routes │ │ │ ├── __test__ │ │ │ │ ├── index.test.ts │ │ │ │ ├── new.test.ts │ │ │ │ ├── show.test.ts │ │ │ │ └── update.test.ts │ │ │ ├── index.ts │ │ │ ├── new.ts │ │ │ ├── show.ts │ │ │ └── update.ts │ │ └── test │ │ │ └── setup.ts │ │ └── tsconfig.json ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ ├── auth-mongo-clusterIP.yaml │ ├── auth-mongo-deployment.yaml │ ├── client-clusterIP.yaml │ ├── client-deployment.yaml │ ├── ingress-controller.yaml │ ├── nats-clusterIP.yaml │ ├── nats-deployment.yaml │ ├── orders-clusterIP.yaml │ ├── orders-deployment.yaml │ ├── orders-mongo-clusterIP.yaml │ ├── orders-mongo-deployment.yaml │ ├── tickets-clusterIP.yaml │ ├── tickets-deployment.yaml │ ├── tickets-mongo-clusterIP.yaml │ └── tickets-mongo-deployment.yaml └── skaffold │ └── skaffold.yaml ├── 20_Worker_Services.md ├── 20_Worker_Services ├── app │ ├── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ └── User.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── current-user.test.ts │ │ │ │ │ ├── signin.test.ts │ │ │ │ │ ├── signout.test.ts │ │ │ │ │ └── signup.test.ts │ │ │ │ ├── current-user.ts │ │ │ │ ├── signin.ts │ │ │ │ ├── signout.ts │ │ │ │ └── signup.ts │ │ │ ├── services │ │ │ │ └── password.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ ├── client │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── api │ │ │ └── build-client.js │ │ ├── components │ │ │ └── Header.js │ │ ├── hooks │ │ │ └── use-request.js │ │ ├── next.config.js │ │ ├── package-lock.json │ │ ├── package.json │ │ └── pages │ │ │ ├── _app.js │ │ │ ├── auth │ │ │ ├── signin.js │ │ │ ├── signout.js │ │ │ └── signup.js │ │ │ └── index.js │ ├── common │ │ ├── .gitignore │ │ ├── package.json │ │ ├── src │ │ │ ├── errors │ │ │ │ ├── bad-request-error.ts │ │ │ │ ├── custom-error.ts │ │ │ │ ├── database-connection-error.ts │ │ │ │ ├── not-authorized-error.ts │ │ │ │ ├── not-found-error.ts │ │ │ │ └── request-validation-error.ts │ │ │ ├── events │ │ │ │ ├── ExpirationCompleteEventInterface.ts │ │ │ │ ├── ListenerAbstract.ts │ │ │ │ ├── OrderCancelledEventInterface.ts │ │ │ │ ├── OrderCreatedEventInterface.ts │ │ │ │ ├── PublisherAbstract.ts │ │ │ │ ├── SubjectsEnum.ts │ │ │ │ ├── TicketCreatedEventInterface.ts │ │ │ │ ├── TicketUpdatedEventInterface.ts │ │ │ │ └── types │ │ │ │ │ └── OrderStatusEnum.ts │ │ │ ├── index.ts │ │ │ └── middlewares │ │ │ │ ├── current-user.ts │ │ │ │ ├── error-handler.ts │ │ │ │ ├── require-auth.ts │ │ │ │ └── validate-request.ts │ │ └── tsconfig.json │ ├── expiration │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── NatsWrapper.ts │ │ │ ├── __mocks__ │ │ │ │ └── NatsWrapper.ts │ │ │ ├── events │ │ │ │ ├── listeneres │ │ │ │ │ ├── OrderCreatedListener.ts │ │ │ │ │ └── queueGroupName.ts │ │ │ │ └── publishers │ │ │ │ │ └── ExpirationCompletePublisher.ts │ │ │ ├── index.ts │ │ │ └── queues │ │ │ │ └── expiration-queue.ts │ │ └── tsconfig.json │ ├── nats-test │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── events │ │ │ │ ├── TicketCreatedListener.ts │ │ │ │ └── TicketCreatedPublisher.ts │ │ │ ├── listener.ts │ │ │ └── publisher.ts │ │ └── tsconfig.json │ ├── orders │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── NatsWrapper.ts │ │ │ ├── __mocks__ │ │ │ │ └── NatsWrapper.ts │ │ │ ├── app.ts │ │ │ ├── events │ │ │ │ ├── listeners │ │ │ │ │ ├── ExpirationCompleteListener.ts │ │ │ │ │ ├── TicketCreatedListener.ts │ │ │ │ │ ├── TicketUpdatedListener.ts │ │ │ │ │ ├── __test__ │ │ │ │ │ │ ├── ExpirationCompleteListener.ts │ │ │ │ │ │ ├── TicketCreatedListener.test.ts │ │ │ │ │ │ └── TicketUpdatedLister.test.ts │ │ │ │ │ └── queueGroupName.ts │ │ │ │ └── publishers │ │ │ │ │ ├── OrderCancelledPublisher.ts │ │ │ │ │ └── OrderCreatedPublisher.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── Order.ts │ │ │ │ └── Ticket.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── delete.test.ts │ │ │ │ │ ├── index.test.ts │ │ │ │ │ ├── new.test.ts │ │ │ │ │ └── show.test.ts │ │ │ │ ├── delete.ts │ │ │ │ ├── index.ts │ │ │ │ ├── new.ts │ │ │ │ └── show.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ └── tickets │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── NatsWrapper.ts │ │ ├── __mocks__ │ │ │ └── NatsWrapper.ts │ │ ├── app.ts │ │ ├── events │ │ │ ├── listeners │ │ │ │ ├── OrderCancelledListener.ts │ │ │ │ ├── OrderCreatedListener.ts │ │ │ │ ├── __test__ │ │ │ │ │ ├── OrderCancelledListener.test.ts │ │ │ │ │ └── OrderCreatedListener.test.ts │ │ │ │ └── queueGroupName.ts │ │ │ └── publishers │ │ │ │ ├── TicketCreatedPublisher.ts │ │ │ │ └── TicketUpdatedPublisher.ts │ │ ├── index.ts │ │ ├── models │ │ │ ├── Ticket.ts │ │ │ └── __test__ │ │ │ │ └── Ticket.test.ts │ │ ├── routes │ │ │ ├── __test__ │ │ │ │ ├── index.test.ts │ │ │ │ ├── new.test.ts │ │ │ │ ├── show.test.ts │ │ │ │ └── update.test.ts │ │ │ ├── index.ts │ │ │ ├── new.ts │ │ │ ├── show.ts │ │ │ └── update.ts │ │ └── test │ │ │ └── setup.ts │ │ └── tsconfig.json ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ ├── auth-mongo-clusterIP.yaml │ ├── auth-mongo-deployment.yaml │ ├── client-clusterIP.yaml │ ├── client-deployment.yaml │ ├── expiration-deployment.yaml │ ├── expiration-redis-clusterIP.yaml │ ├── expiration-redis-deployment.yaml │ ├── ingress-controller.yaml │ ├── nats-clusterIP.yaml │ ├── nats-deployment.yaml │ ├── orders-clusterIP.yaml │ ├── orders-deployment.yaml │ ├── orders-mongo-clusterIP.yaml │ ├── orders-mongo-deployment.yaml │ ├── tickets-clusterIP.yaml │ ├── tickets-deployment.yaml │ ├── tickets-mongo-clusterIP.yaml │ └── tickets-mongo-deployment.yaml └── skaffold │ └── skaffold.yaml ├── 21_Handling_Payments.md ├── 21_Handling_Payments ├── app │ ├── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ └── User.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── current-user.test.ts │ │ │ │ │ ├── signin.test.ts │ │ │ │ │ ├── signout.test.ts │ │ │ │ │ └── signup.test.ts │ │ │ │ ├── current-user.ts │ │ │ │ ├── signin.ts │ │ │ │ ├── signout.ts │ │ │ │ └── signup.ts │ │ │ ├── services │ │ │ │ └── password.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ ├── client │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── api │ │ │ └── build-client.js │ │ ├── components │ │ │ └── Header.js │ │ ├── hooks │ │ │ └── use-request.js │ │ ├── next.config.js │ │ ├── package-lock.json │ │ ├── package.json │ │ └── pages │ │ │ ├── _app.js │ │ │ ├── auth │ │ │ ├── signin.js │ │ │ ├── signout.js │ │ │ └── signup.js │ │ │ └── index.js │ ├── common │ │ ├── .gitignore │ │ ├── package.json │ │ ├── src │ │ │ ├── errors │ │ │ │ ├── bad-request-error.ts │ │ │ │ ├── custom-error.ts │ │ │ │ ├── database-connection-error.ts │ │ │ │ ├── not-authorized-error.ts │ │ │ │ ├── not-found-error.ts │ │ │ │ └── request-validation-error.ts │ │ │ ├── events │ │ │ │ ├── ExpirationCompleteEventInterface.ts │ │ │ │ ├── ListenerAbstract.ts │ │ │ │ ├── OrderCancelledEventInterface.ts │ │ │ │ ├── OrderCreatedEventInterface.ts │ │ │ │ ├── PaymentCreatedEventInteface.ts │ │ │ │ ├── PublisherAbstract.ts │ │ │ │ ├── SubjectsEnum.ts │ │ │ │ ├── TicketCreatedEventInterface.ts │ │ │ │ ├── TicketUpdatedEventInterface.ts │ │ │ │ └── types │ │ │ │ │ └── OrderStatusEnum.ts │ │ │ ├── index.ts │ │ │ └── middlewares │ │ │ │ ├── current-user.ts │ │ │ │ ├── error-handler.ts │ │ │ │ ├── require-auth.ts │ │ │ │ └── validate-request.ts │ │ └── tsconfig.json │ ├── expiration │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── NatsWrapper.ts │ │ │ ├── __mocks__ │ │ │ │ └── NatsWrapper.ts │ │ │ ├── events │ │ │ │ ├── listeneres │ │ │ │ │ ├── OrderCreatedListener.ts │ │ │ │ │ └── queueGroupName.ts │ │ │ │ └── publishers │ │ │ │ │ └── ExpirationCompletePublisher.ts │ │ │ ├── index.ts │ │ │ └── queues │ │ │ │ └── expiration-queue.ts │ │ └── tsconfig.json │ ├── nats-test │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── events │ │ │ │ ├── TicketCreatedListener.ts │ │ │ │ └── TicketCreatedPublisher.ts │ │ │ ├── listener.ts │ │ │ └── publisher.ts │ │ └── tsconfig.json │ ├── orders │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── NatsWrapper.ts │ │ │ ├── __mocks__ │ │ │ │ └── NatsWrapper.ts │ │ │ ├── app.ts │ │ │ ├── events │ │ │ │ ├── listeners │ │ │ │ │ ├── ExpirationCompleteListener.ts │ │ │ │ │ ├── PaymentCreatedListener.ts │ │ │ │ │ ├── TicketCreatedListener.ts │ │ │ │ │ ├── TicketUpdatedListener.ts │ │ │ │ │ ├── __test__ │ │ │ │ │ │ ├── ExpirationCompleteListener.ts │ │ │ │ │ │ ├── TicketCreatedListener.test.ts │ │ │ │ │ │ └── TicketUpdatedLister.test.ts │ │ │ │ │ └── queueGroupName.ts │ │ │ │ └── publishers │ │ │ │ │ ├── OrderCancelledPublisher.ts │ │ │ │ │ └── OrderCreatedPublisher.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── Order.ts │ │ │ │ └── Ticket.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── delete.test.ts │ │ │ │ │ ├── index.test.ts │ │ │ │ │ ├── new.test.ts │ │ │ │ │ └── show.test.ts │ │ │ │ ├── delete.ts │ │ │ │ ├── index.ts │ │ │ │ ├── new.ts │ │ │ │ └── show.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ ├── payments │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── NatsWrapper.ts │ │ │ ├── __mocks__ │ │ │ │ ├── NatsWrapper.ts │ │ │ │ └── stripe.ts.disabled │ │ │ ├── app.ts │ │ │ ├── events │ │ │ │ ├── listeners │ │ │ │ │ ├── OrderCancelledListener.ts │ │ │ │ │ ├── OrderCreatedListener.ts │ │ │ │ │ ├── __test__ │ │ │ │ │ │ ├── OrderCancelledListener.test.ts │ │ │ │ │ │ └── OrderCreatedListener.test.ts │ │ │ │ │ └── queueGroupName.ts │ │ │ │ └── publishers │ │ │ │ │ └── PaymentCreatedPublisher.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── Order.ts │ │ │ │ └── Payment.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ └── new.test.ts │ │ │ │ └── new.ts │ │ │ ├── stripe.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ └── tickets │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── NatsWrapper.ts │ │ ├── __mocks__ │ │ │ └── NatsWrapper.ts │ │ ├── app.ts │ │ ├── events │ │ │ ├── listeners │ │ │ │ ├── OrderCancelledListener.ts │ │ │ │ ├── OrderCreatedListener.ts │ │ │ │ ├── __test__ │ │ │ │ │ ├── OrderCancelledListener.test.ts │ │ │ │ │ └── OrderCreatedListener.test.ts │ │ │ │ └── queueGroupName.ts │ │ │ └── publishers │ │ │ │ ├── TicketCreatedPublisher.ts │ │ │ │ └── TicketUpdatedPublisher.ts │ │ ├── index.ts │ │ ├── models │ │ │ ├── Ticket.ts │ │ │ └── __test__ │ │ │ │ └── Ticket.test.ts │ │ ├── routes │ │ │ ├── __test__ │ │ │ │ ├── index.test.ts │ │ │ │ ├── new.test.ts │ │ │ │ ├── show.test.ts │ │ │ │ └── update.test.ts │ │ │ ├── index.ts │ │ │ ├── new.ts │ │ │ ├── show.ts │ │ │ └── update.ts │ │ └── test │ │ │ └── setup.ts │ │ └── tsconfig.json ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ ├── auth-mongo-clusterIP.yaml │ ├── auth-mongo-deployment.yaml │ ├── client-clusterIP.yaml │ ├── client-deployment.yaml │ ├── expiration-deployment.yaml │ ├── expiration-redis-clusterIP.yaml │ ├── expiration-redis-deployment.yaml │ ├── ingress-controller.yaml │ ├── nats-clusterIP.yaml │ ├── nats-deployment.yaml │ ├── orders-clusterIP.yaml │ ├── orders-deployment.yaml │ ├── orders-mongo-clusterIP.yaml │ ├── orders-mongo-deployment.yaml │ ├── payments-clusterIP.yaml │ ├── payments-deployment.yaml │ ├── payments-mongo-clusterIP.yaml │ ├── payments-mongo-deployment.yaml │ ├── tickets-clusterIP.yaml │ ├── tickets-deployment.yaml │ ├── tickets-mongo-clusterIP.yaml │ └── tickets-mongo-deployment.yaml └── skaffold │ └── skaffold.yaml ├── 22_Back_to_the_Client.md ├── 22_Back_to_the_Client ├── app │ ├── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ └── User.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── current-user.test.ts │ │ │ │ │ ├── signin.test.ts │ │ │ │ │ ├── signout.test.ts │ │ │ │ │ └── signup.test.ts │ │ │ │ ├── current-user.ts │ │ │ │ ├── signin.ts │ │ │ │ ├── signout.ts │ │ │ │ └── signup.ts │ │ │ ├── services │ │ │ │ └── password.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ ├── client │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── api │ │ │ └── build-client.js │ │ ├── components │ │ │ └── Header.js │ │ ├── hooks │ │ │ └── use-request.js │ │ ├── next.config.js │ │ ├── package-lock.json │ │ ├── package.json │ │ └── pages │ │ │ ├── _app.js │ │ │ ├── auth │ │ │ ├── signin.js │ │ │ ├── signout.js │ │ │ └── signup.js │ │ │ ├── index.js │ │ │ ├── orders │ │ │ ├── [orderId].js │ │ │ └── index.js │ │ │ └── tickets │ │ │ ├── [ticketId].js │ │ │ └── new.js │ ├── common │ │ ├── .gitignore │ │ ├── package.json │ │ ├── src │ │ │ ├── errors │ │ │ │ ├── bad-request-error.ts │ │ │ │ ├── custom-error.ts │ │ │ │ ├── database-connection-error.ts │ │ │ │ ├── not-authorized-error.ts │ │ │ │ ├── not-found-error.ts │ │ │ │ └── request-validation-error.ts │ │ │ ├── events │ │ │ │ ├── ExpirationCompleteEventInterface.ts │ │ │ │ ├── ListenerAbstract.ts │ │ │ │ ├── OrderCancelledEventInterface.ts │ │ │ │ ├── OrderCreatedEventInterface.ts │ │ │ │ ├── PaymentCreatedEventInteface.ts │ │ │ │ ├── PublisherAbstract.ts │ │ │ │ ├── SubjectsEnum.ts │ │ │ │ ├── TicketCreatedEventInterface.ts │ │ │ │ ├── TicketUpdatedEventInterface.ts │ │ │ │ └── types │ │ │ │ │ └── OrderStatusEnum.ts │ │ │ ├── index.ts │ │ │ └── middlewares │ │ │ │ ├── current-user.ts │ │ │ │ ├── error-handler.ts │ │ │ │ ├── require-auth.ts │ │ │ │ └── validate-request.ts │ │ └── tsconfig.json │ ├── expiration │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── NatsWrapper.ts │ │ │ ├── __mocks__ │ │ │ │ └── NatsWrapper.ts │ │ │ ├── events │ │ │ │ ├── listeneres │ │ │ │ │ ├── OrderCreatedListener.ts │ │ │ │ │ └── queueGroupName.ts │ │ │ │ └── publishers │ │ │ │ │ └── ExpirationCompletePublisher.ts │ │ │ ├── index.ts │ │ │ └── queues │ │ │ │ └── expiration-queue.ts │ │ └── tsconfig.json │ ├── nats-test │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── events │ │ │ │ ├── TicketCreatedListener.ts │ │ │ │ └── TicketCreatedPublisher.ts │ │ │ ├── listener.ts │ │ │ └── publisher.ts │ │ └── tsconfig.json │ ├── orders │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── NatsWrapper.ts │ │ │ ├── __mocks__ │ │ │ │ └── NatsWrapper.ts │ │ │ ├── app.ts │ │ │ ├── events │ │ │ │ ├── listeners │ │ │ │ │ ├── ExpirationCompleteListener.ts │ │ │ │ │ ├── PaymentCreatedListener.ts │ │ │ │ │ ├── TicketCreatedListener.ts │ │ │ │ │ ├── TicketUpdatedListener.ts │ │ │ │ │ ├── __test__ │ │ │ │ │ │ ├── ExpirationCompleteListener.ts │ │ │ │ │ │ ├── TicketCreatedListener.test.ts │ │ │ │ │ │ └── TicketUpdatedLister.test.ts │ │ │ │ │ └── queueGroupName.ts │ │ │ │ └── publishers │ │ │ │ │ ├── OrderCancelledPublisher.ts │ │ │ │ │ └── OrderCreatedPublisher.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── Order.ts │ │ │ │ └── Ticket.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── delete.test.ts │ │ │ │ │ ├── index.test.ts │ │ │ │ │ ├── new.test.ts │ │ │ │ │ └── show.test.ts │ │ │ │ ├── delete.ts │ │ │ │ ├── index.ts │ │ │ │ ├── new.ts │ │ │ │ └── show.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ ├── payments │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── NatsWrapper.ts │ │ │ ├── __mocks__ │ │ │ │ ├── NatsWrapper.ts │ │ │ │ └── stripe.ts.disabled │ │ │ ├── app.ts │ │ │ ├── events │ │ │ │ ├── listeners │ │ │ │ │ ├── OrderCancelledListener.ts │ │ │ │ │ ├── OrderCreatedListener.ts │ │ │ │ │ ├── __test__ │ │ │ │ │ │ ├── OrderCancelledListener.test.ts │ │ │ │ │ │ └── OrderCreatedListener.test.ts │ │ │ │ │ └── queueGroupName.ts │ │ │ │ └── publishers │ │ │ │ │ └── PaymentCreatedPublisher.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── Order.ts │ │ │ │ └── Payment.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ └── new.test.ts │ │ │ │ └── new.ts │ │ │ ├── stripe.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ └── tickets │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── NatsWrapper.ts │ │ ├── __mocks__ │ │ │ └── NatsWrapper.ts │ │ ├── app.ts │ │ ├── events │ │ │ ├── listeners │ │ │ │ ├── OrderCancelledListener.ts │ │ │ │ ├── OrderCreatedListener.ts │ │ │ │ ├── __test__ │ │ │ │ │ ├── OrderCancelledListener.test.ts │ │ │ │ │ └── OrderCreatedListener.test.ts │ │ │ │ └── queueGroupName.ts │ │ │ └── publishers │ │ │ │ ├── TicketCreatedPublisher.ts │ │ │ │ └── TicketUpdatedPublisher.ts │ │ ├── index.ts │ │ ├── models │ │ │ ├── Ticket.ts │ │ │ └── __test__ │ │ │ │ └── Ticket.test.ts │ │ ├── routes │ │ │ ├── __test__ │ │ │ │ ├── index.test.ts │ │ │ │ ├── new.test.ts │ │ │ │ ├── show.test.ts │ │ │ │ └── update.test.ts │ │ │ ├── index.ts │ │ │ ├── new.ts │ │ │ ├── show.ts │ │ │ └── update.ts │ │ └── test │ │ │ └── setup.ts │ │ └── tsconfig.json ├── k8s │ ├── auth-clusterIP.yaml │ ├── auth-deployment.yaml │ ├── auth-mongo-clusterIP.yaml │ ├── auth-mongo-deployment.yaml │ ├── client-clusterIP.yaml │ ├── client-deployment.yaml │ ├── expiration-deployment.yaml │ ├── expiration-redis-clusterIP.yaml │ ├── expiration-redis-deployment.yaml │ ├── ingress-controller.yaml │ ├── nats-clusterIP.yaml │ ├── nats-deployment.yaml │ ├── orders-clusterIP.yaml │ ├── orders-deployment.yaml │ ├── orders-mongo-clusterIP.yaml │ ├── orders-mongo-deployment.yaml │ ├── payments-clusterIP.yaml │ ├── payments-deployment.yaml │ ├── payments-mongo-clusterIP.yaml │ ├── payments-mongo-deployment.yaml │ ├── tickets-clusterIP.yaml │ ├── tickets-deployment.yaml │ ├── tickets-mongo-clusterIP.yaml │ └── tickets-mongo-deployment.yaml └── skaffold │ └── skaffold.yaml ├── 23_CI_CD.md ├── 23_CI_CD ├── app │ ├── auth │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── app.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ └── User.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── current-user.test.ts │ │ │ │ │ ├── signin.test.ts │ │ │ │ │ ├── signout.test.ts │ │ │ │ │ └── signup.test.ts │ │ │ │ ├── current-user.ts │ │ │ │ ├── signin.ts │ │ │ │ ├── signout.ts │ │ │ │ └── signup.ts │ │ │ ├── services │ │ │ │ └── password.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ ├── client │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── api │ │ │ └── build-client.js │ │ ├── components │ │ │ └── Header.js │ │ ├── hooks │ │ │ └── use-request.js │ │ ├── next.config.js │ │ ├── package-lock.json │ │ ├── package.json │ │ └── pages │ │ │ ├── _app.js │ │ │ ├── auth │ │ │ ├── signin.js │ │ │ ├── signout.js │ │ │ └── signup.js │ │ │ ├── index.js │ │ │ ├── orders │ │ │ ├── [orderId].js │ │ │ └── index.js │ │ │ └── tickets │ │ │ ├── [ticketId].js │ │ │ └── new.js │ ├── common │ │ ├── .gitignore │ │ ├── package.json │ │ ├── src │ │ │ ├── errors │ │ │ │ ├── bad-request-error.ts │ │ │ │ ├── custom-error.ts │ │ │ │ ├── database-connection-error.ts │ │ │ │ ├── not-authorized-error.ts │ │ │ │ ├── not-found-error.ts │ │ │ │ └── request-validation-error.ts │ │ │ ├── events │ │ │ │ ├── ExpirationCompleteEventInterface.ts │ │ │ │ ├── ListenerAbstract.ts │ │ │ │ ├── OrderCancelledEventInterface.ts │ │ │ │ ├── OrderCreatedEventInterface.ts │ │ │ │ ├── PaymentCreatedEventInteface.ts │ │ │ │ ├── PublisherAbstract.ts │ │ │ │ ├── SubjectsEnum.ts │ │ │ │ ├── TicketCreatedEventInterface.ts │ │ │ │ ├── TicketUpdatedEventInterface.ts │ │ │ │ └── types │ │ │ │ │ └── OrderStatusEnum.ts │ │ │ ├── index.ts │ │ │ └── middlewares │ │ │ │ ├── current-user.ts │ │ │ │ ├── error-handler.ts │ │ │ │ ├── require-auth.ts │ │ │ │ └── validate-request.ts │ │ └── tsconfig.json │ ├── expiration │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── NatsWrapper.ts │ │ │ ├── __mocks__ │ │ │ │ └── NatsWrapper.ts │ │ │ ├── events │ │ │ │ ├── listeneres │ │ │ │ │ ├── OrderCreatedListener.ts │ │ │ │ │ └── queueGroupName.ts │ │ │ │ └── publishers │ │ │ │ │ └── ExpirationCompletePublisher.ts │ │ │ ├── index.ts │ │ │ └── queues │ │ │ │ └── expiration-queue.ts │ │ └── tsconfig.json │ ├── nats-test │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── events │ │ │ │ ├── TicketCreatedListener.ts │ │ │ │ └── TicketCreatedPublisher.ts │ │ │ ├── listener.ts │ │ │ └── publisher.ts │ │ └── tsconfig.json │ ├── orders │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── NatsWrapper.ts │ │ │ ├── __mocks__ │ │ │ │ └── NatsWrapper.ts │ │ │ ├── app.ts │ │ │ ├── events │ │ │ │ ├── listeners │ │ │ │ │ ├── ExpirationCompleteListener.ts │ │ │ │ │ ├── PaymentCreatedListener.ts │ │ │ │ │ ├── TicketCreatedListener.ts │ │ │ │ │ ├── TicketUpdatedListener.ts │ │ │ │ │ ├── __test__ │ │ │ │ │ │ ├── ExpirationCompleteListener.ts │ │ │ │ │ │ ├── TicketCreatedListener.test.ts │ │ │ │ │ │ └── TicketUpdatedLister.test.ts │ │ │ │ │ └── queueGroupName.ts │ │ │ │ └── publishers │ │ │ │ │ ├── OrderCancelledPublisher.ts │ │ │ │ │ └── OrderCreatedPublisher.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── Order.ts │ │ │ │ └── Ticket.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ ├── delete.test.ts │ │ │ │ │ ├── index.test.ts │ │ │ │ │ ├── new.test.ts │ │ │ │ │ └── show.test.ts │ │ │ │ ├── delete.ts │ │ │ │ ├── index.ts │ │ │ │ ├── new.ts │ │ │ │ └── show.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ ├── payments │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── NatsWrapper.ts │ │ │ ├── __mocks__ │ │ │ │ ├── NatsWrapper.ts │ │ │ │ └── stripe.ts.disabled │ │ │ ├── app.ts │ │ │ ├── events │ │ │ │ ├── listeners │ │ │ │ │ ├── OrderCancelledListener.ts │ │ │ │ │ ├── OrderCreatedListener.ts │ │ │ │ │ ├── __test__ │ │ │ │ │ │ ├── OrderCancelledListener.test.ts │ │ │ │ │ │ └── OrderCreatedListener.test.ts │ │ │ │ │ └── queueGroupName.ts │ │ │ │ └── publishers │ │ │ │ │ └── PaymentCreatedPublisher.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── Order.ts │ │ │ │ └── Payment.ts │ │ │ ├── routes │ │ │ │ ├── __test__ │ │ │ │ │ └── new.test.ts │ │ │ │ └── new.ts │ │ │ ├── stripe.ts │ │ │ └── test │ │ │ │ └── setup.ts │ │ └── tsconfig.json │ └── tickets │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── NatsWrapper.ts │ │ ├── __mocks__ │ │ │ └── NatsWrapper.ts │ │ ├── app.ts │ │ ├── events │ │ │ ├── listeners │ │ │ │ ├── OrderCancelledListener.ts │ │ │ │ ├── OrderCreatedListener.ts │ │ │ │ ├── __test__ │ │ │ │ │ ├── OrderCancelledListener.test.ts │ │ │ │ │ └── OrderCreatedListener.test.ts │ │ │ │ └── queueGroupName.ts │ │ │ └── publishers │ │ │ │ ├── TicketCreatedPublisher.ts │ │ │ │ └── TicketUpdatedPublisher.ts │ │ ├── index.ts │ │ ├── models │ │ │ ├── Ticket.ts │ │ │ └── __test__ │ │ │ │ └── Ticket.test.ts │ │ ├── routes │ │ │ ├── __test__ │ │ │ │ ├── index.test.ts │ │ │ │ ├── new.test.ts │ │ │ │ ├── show.test.ts │ │ │ │ └── update.test.ts │ │ │ ├── index.ts │ │ │ ├── new.ts │ │ │ ├── show.ts │ │ │ └── update.ts │ │ └── test │ │ │ └── setup.ts │ │ └── tsconfig.json ├── k8s │ ├── common │ │ ├── auth-clusterIP.yaml │ │ ├── auth-deployment.yaml │ │ ├── auth-mongo-clusterIP.yaml │ │ ├── auth-mongo-deployment.yaml │ │ ├── client-clusterIP.yaml │ │ ├── client-deployment.yaml │ │ ├── expiration-deployment.yaml │ │ ├── expiration-redis-clusterIP.yaml │ │ ├── expiration-redis-deployment.yaml │ │ ├── nats-clusterIP.yaml │ │ ├── nats-deployment.yaml │ │ ├── orders-clusterIP.yaml │ │ ├── orders-deployment.yaml │ │ ├── orders-mongo-clusterIP.yaml │ │ ├── orders-mongo-deployment.yaml │ │ ├── payments-clusterIP.yaml │ │ ├── payments-deployment.yaml │ │ ├── payments-mongo-clusterIP.yaml │ │ ├── payments-mongo-deployment.yaml │ │ ├── tickets-clusterIP.yaml │ │ ├── tickets-deployment.yaml │ │ ├── tickets-mongo-clusterIP.yaml │ │ └── tickets-mongo-deployment.yaml │ ├── dev │ │ └── ingress-controller.yaml │ └── prod │ │ └── ingress-controller.yaml └── skaffold │ └── skaffold.yaml ├── Readme.md └── img ├── pic-02-01.png ├── pic-02-02.png ├── pic-02-03.png ├── pic-02-04.png ├── pic-02-05.png ├── pic-02-06.png ├── pic-02-07.png ├── pic-02-08.png ├── pic-02-09.png ├── pic-02-10.png ├── pic-02-11.png ├── pic-02-12.png ├── pic-02-13.png ├── pic-02-14.png ├── pic-02-15.png ├── pic-02-16.png ├── pic-02-17.png ├── pic-02-18.png ├── pic-02-19.png ├── pic-02-20.png ├── pic-02-21.png ├── pic-02-22.png ├── pic-02-23.png ├── pic-04-01.png ├── pic-04-02.png ├── pic-04-03.png ├── pic-04-04.png ├── pic-04-05.png ├── pic-04-06.png ├── pic-04-07.png ├── pic-05-01.png ├── pic-05-02.png ├── pic-05-03.png ├── pic-05-04.png ├── pic-05-05.png ├── pic-08-01.png ├── pic-09-01.png ├── pic-09-02.png ├── pic-09-03.png ├── pic-09-04.png ├── pic-09-05.png ├── pic-09-06.png ├── pic-09-07.png ├── pic-09-08.png ├── pic-09-09.png ├── pic-09-10.png ├── pic-09-11.png ├── pic-09-12.png ├── pic-09-13.png ├── pic-09-14.png ├── pic-09-15.png ├── pic-09-16.png ├── pic-09-17.png ├── pic-09-18.png ├── pic-10-01.png ├── pic-10-02.png ├── pic-10-03.png ├── pic-10-04.png ├── pic-10-05.png ├── pic-11-01.png ├── pic-11-02.png ├── pic-11-03.png ├── pic-11-04.png ├── pic-11-05.png ├── pic-11-06.png ├── pic-11-07.png ├── pic-11-08.png ├── pic-11-09.png ├── pic-11-10.png ├── pic-11-11.png ├── pic-11-12.png ├── pic-11-13.png ├── pic-11-14.png ├── pic-11-15.png ├── pic-12-01.png ├── pic-12-02.png ├── pic-12-03.png ├── pic-12-04.png ├── pic-12-05.png ├── pic-13-01.png ├── pic-14-01.png ├── pic-14-02.png ├── pic-14-03.png ├── pic-14-04.png ├── pic-14-05.png ├── pic-14-06.png ├── pic-14-07.png ├── pic-14-08.png ├── pic-14-09.png ├── pic-14-10.png ├── pic-14-11.png ├── pic-14-12.png ├── pic-15-01.png ├── pic-15-02.png ├── pic-16-01.png ├── pic-16-02.png ├── pic-16-03.png ├── pic-16-04.png ├── pic-16-05.png ├── pic-16-06.png ├── pic-17-01.png ├── pic-17-02.png ├── pic-17-03.png ├── pic-17-04.png ├── pic-17-05.png ├── pic-17-06.png ├── pic-17-07.png ├── pic-18-01.png ├── pic-18-02.png ├── pic-18-03.png ├── pic-19-01.png ├── pic-19-02.png ├── pic-19-03.png ├── pic-19-04.png ├── pic-20-01.png ├── pic-20-02.png ├── pic-20-03.png ├── pic-20-04.png ├── pic-20-05.png ├── pic-21-01.png ├── pic-21-02.png ├── pic-21-03.png ├── pic-21-04.png ├── pic-21-05.png ├── pic-21-06.png ├── pic-21-07.png ├── pic-21-08.png ├── pic-21-09.png ├── pic-21-10.png ├── pic-21-11.png ├── pic-22-01.png ├── pic-22-02.png ├── pic-22-03.png ├── pic-22-04.png ├── pic-22-05.png ├── pic-23-01.png ├── pic-23-02.png ├── pic-23-03.png ├── pic-23-04.png ├── pic-23-05.png └── pic-final-01.png /.github/workflows/tests-auth.yml: -------------------------------------------------------------------------------- 1 | name: tests-auth 2 | 3 | on: 4 | push: 5 | paths: 6 | - '23_CI_CD/app/auth/**' 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-18.04 11 | steps: 12 | - uses: actions/checkout@v2 13 | - run: cd 23_CI_CD/app/auth && npm install && npm run test:ci 14 | -------------------------------------------------------------------------------- /.github/workflows/tests-orders.yml: -------------------------------------------------------------------------------- 1 | name: tests-orders 2 | 3 | on: 4 | push: 5 | paths: 6 | - '23_CI_CD/app/orders/**' 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-18.04 11 | steps: 12 | - uses: actions/checkout@v2 13 | - run: cd 23_CI_CD/app/orders && npm install && npm run test:ci 14 | -------------------------------------------------------------------------------- /.github/workflows/tests-payments.yml: -------------------------------------------------------------------------------- 1 | name: tests-payments 2 | 3 | on: 4 | push: 5 | paths: 6 | - '23_CI_CD/app/payments/**' 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-18.04 11 | steps: 12 | - uses: actions/checkout@v2 13 | - run: cd 23_CI_CD/app/payments && npm install && npm run test:ci 14 | -------------------------------------------------------------------------------- /.github/workflows/tests-tickets.yml: -------------------------------------------------------------------------------- 1 | name: tests-tickets 2 | 3 | on: 4 | push: 5 | paths: 6 | - '23_CI_CD/app/tickets/**' 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-18.04 11 | steps: 12 | - uses: actions/checkout@v2 13 | - run: cd 23_CI_CD/app/tickets && npm install && npm run test:ci 14 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | # *.test.js 3 | # *.spec.js -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "bracketSpacing": true 4 | } 5 | -------------------------------------------------------------------------------- /02_A_Mini_Microservices_App/app/client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/02_A_Mini_Microservices_App/app/client/public/favicon.ico -------------------------------------------------------------------------------- /02_A_Mini_Microservices_App/app/client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /02_A_Mini_Microservices_App/app/client/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PostCreate from './PostCreate'; 3 | import PostList from './PostList'; 4 | 5 | export default () => { 6 | return ( 7 |
8 |

Create Post

9 | 10 |
11 |

Posts

12 | 13 |
14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /02_A_Mini_Microservices_App/app/client/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render(, document.getElementById('root')); 6 | -------------------------------------------------------------------------------- /02_A_Mini_Microservices_App/app/comments/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "comments", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "nodemon index.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "axios": "^0.19.2", 14 | "cors": "^2.8.5", 15 | "express": "^4.17.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /02_A_Mini_Microservices_App/app/event-bus/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "event-bus", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "nodemon index.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "axios": "^0.19.2", 14 | "express": "^4.17.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /02_A_Mini_Microservices_App/app/moderation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "moderation", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "nodemon index.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "axios": "^0.19.2", 14 | "express": "^4.17.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /02_A_Mini_Microservices_App/app/posts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "posts", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "nodemon index.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "axios": "^0.19.2", 14 | "cors": "^2.8.5", 15 | "express": "^4.17.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /02_A_Mini_Microservices_App/app/query/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "query", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "nodemon index.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "axios": "^0.19.2", 14 | "cors": "^2.8.5", 15 | "express": "^4.17.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/app/client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/app/client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/app/client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/04_Orchestrating_Collections_of_Services_with_Kubernetes/app/client/public/favicon.ico -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/app/client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/app/client/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render(, document.getElementById('root')); 6 | -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/app/comments/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/app/comments/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/app/event-bus/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/app/event-bus/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/app/moderation/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/app/moderation/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/app/posts/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/app/posts/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/app/query/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/app/query/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/k8s/client-srv-ClusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: client-svc 5 | spec: 6 | selector: 7 | app: client 8 | ports: 9 | - name: client 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/k8s/comments-srv-ClusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: comments-svc 5 | spec: 6 | selector: 7 | app: comments 8 | ports: 9 | - name: comments 10 | protocol: TCP 11 | port: 4001 12 | targetPort: 4001 13 | -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/k8s/event-bus-srv-ClusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: event-bus-svc 5 | spec: 6 | selector: 7 | app: event-bus 8 | ports: 9 | - name: event-bus 10 | protocol: TCP 11 | port: 4005 12 | targetPort: 4005 13 | -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/k8s/moderation-srv-ClusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: moderation-svc 5 | spec: 6 | selector: 7 | app: moderation 8 | ports: 9 | - name: moderation 10 | protocol: TCP 11 | port: 4003 12 | targetPort: 4003 13 | -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/k8s/posts-srv-ClusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: posts-svc 5 | spec: 6 | selector: 7 | app: posts 8 | ports: 9 | - name: posts 10 | protocol: TCP 11 | port: 4000 12 | targetPort: 4000 13 | -------------------------------------------------------------------------------- /04_Orchestrating_Collections_of_Services_with_Kubernetes/k8s/query-srv-ClusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: query-svc 5 | spec: 6 | selector: 7 | app: query 8 | ports: 9 | - name: query 10 | protocol: TCP 11 | port: 4002 12 | targetPort: 4002 13 | -------------------------------------------------------------------------------- /05_Architecture_of_Multi_Service_Apps/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /05_Architecture_of_Multi_Service_Apps/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /05_Architecture_of_Multi_Service_Apps/app/auth/src/index.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { json } from 'body-parser'; 3 | 4 | const app = express(); 5 | app.use(json()); 6 | 7 | app.get('/api/users/currentuser', (req, res) => { 8 | res.send('Hi there!'); 9 | }); 10 | 11 | app.listen(3000, () => { 12 | console.log('Listening on port 3000'); 13 | }); 14 | -------------------------------------------------------------------------------- /05_Architecture_of_Multi_Service_Apps/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /07_Response_Normalization_Strategies/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /07_Response_Normalization_Strategies/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /07_Response_Normalization_Strategies/app/auth/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /07_Response_Normalization_Strategies/app/auth/src/routes/current-user.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.get('/api/users/currentuser', (req, res) => { 6 | res.send('Hi there!'); 7 | }); 8 | 9 | export { router as currentUserRouter }; 10 | -------------------------------------------------------------------------------- /07_Response_Normalization_Strategies/app/auth/src/routes/signin.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signin', (req, res) => { 6 | res.send('Hi there!'); 7 | }); 8 | 9 | export { router as signinRouter }; 10 | -------------------------------------------------------------------------------- /07_Response_Normalization_Strategies/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | res.send('Hi there!'); 7 | }); 8 | 9 | export { router as signoutRouter }; 10 | -------------------------------------------------------------------------------- /07_Response_Normalization_Strategies/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /08_Database Management_and_Modeling/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /08_Database Management_and_Modeling/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /08_Database Management_and_Modeling/app/auth/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /08_Database Management_and_Modeling/app/auth/src/routes/current-user.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.get('/api/users/currentuser', (req, res) => { 6 | res.send('Hi there!'); 7 | }); 8 | 9 | export { router as currentUserRouter }; 10 | -------------------------------------------------------------------------------- /08_Database Management_and_Modeling/app/auth/src/routes/signin.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signin', (req, res) => { 6 | res.send('Hi there!'); 7 | }); 8 | 9 | export { router as signinRouter }; 10 | -------------------------------------------------------------------------------- /08_Database Management_and_Modeling/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | res.send('Hi there!'); 7 | }); 8 | 9 | export { router as signoutRouter }; 10 | -------------------------------------------------------------------------------- /08_Database Management_and_Modeling/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /08_Database Management_and_Modeling/k8s/auth-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-mongo-svc 5 | spec: 6 | selector: 7 | app: auth-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /09_Authentication_Strategies_and_Options/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /09_Authentication_Strategies_and_Options/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /09_Authentication_Strategies_and_Options/app/auth/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /09_Authentication_Strategies_and_Options/app/auth/src/routes/current-user.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | import { currentUser } from '../middlewares/current-user'; 4 | 5 | const router = express.Router(); 6 | 7 | router.get('/api/users/currentuser', currentUser, (req, res) => { 8 | return res.send({ currentUser: req.currentUser }); 9 | }); 10 | 11 | export { router as currentUserRouter }; 12 | -------------------------------------------------------------------------------- /09_Authentication_Strategies_and_Options/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | req.session = null; 7 | 8 | return res.send({}); 9 | }); 10 | 11 | export { router as signoutRouter }; 12 | -------------------------------------------------------------------------------- /09_Authentication_Strategies_and_Options/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /09_Authentication_Strategies_and_Options/k8s/auth-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-mongo-svc 5 | spec: 6 | selector: 7 | app: auth-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /10_Testing_Isolated_Microservices/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /10_Testing_Isolated_Microservices/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /10_Testing_Isolated_Microservices/app/auth/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /10_Testing_Isolated_Microservices/app/auth/src/routes/current-user.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | import { currentUser } from '../middlewares/current-user'; 4 | 5 | const router = express.Router(); 6 | 7 | router.get('/api/users/currentuser', currentUser, (req, res) => { 8 | return res.send({ currentUser: req.currentUser || null }); 9 | }); 10 | 11 | export { router as currentUserRouter }; 12 | -------------------------------------------------------------------------------- /10_Testing_Isolated_Microservices/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | req.session = null; 7 | 8 | return res.send({}); 9 | }); 10 | 11 | export { router as signoutRouter }; 12 | -------------------------------------------------------------------------------- /10_Testing_Isolated_Microservices/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /10_Testing_Isolated_Microservices/k8s/auth-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-mongo-svc 5 | spec: 6 | selector: 7 | app: auth-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /11_Integrating_a_Server_Side_Rendered_React_App/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /11_Integrating_a_Server_Side_Rendered_React_App/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /11_Integrating_a_Server_Side_Rendered_React_App/app/auth/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /11_Integrating_a_Server_Side_Rendered_React_App/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | req.session = null; 7 | 8 | return res.send({}); 9 | }); 10 | 11 | export { router as signoutRouter }; 12 | -------------------------------------------------------------------------------- /11_Integrating_a_Server_Side_Rendered_React_App/app/client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /11_Integrating_a_Server_Side_Rendered_React_App/app/client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "run", "dev"] -------------------------------------------------------------------------------- /11_Integrating_a_Server_Side_Rendered_React_App/app/client/next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | webpackDevMiddleware: (config) => { 3 | config.watchOptions.poll = 300; 4 | return config; 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /11_Integrating_a_Server_Side_Rendered_React_App/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /11_Integrating_a_Server_Side_Rendered_React_App/k8s/auth-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-mongo-svc 5 | spec: 6 | selector: 7 | app: auth-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /11_Integrating_a_Server_Side_Rendered_React_App/k8s/client-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: client-svc 5 | spec: 6 | selector: 7 | app: client 8 | ports: 9 | - name: client 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /12_Code_Sharing_and_Reuse_Between_Services/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /12_Code_Sharing_and_Reuse_Between_Services/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /12_Code_Sharing_and_Reuse_Between_Services/app/auth/src/routes/current-user.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { currentUser } from '@grider-ms-tickets/common'; 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/api/users/currentuser', currentUser, (req, res) => { 7 | return res.send({ currentUser: req.currentUser || null }); 8 | }); 9 | 10 | export { router as currentUserRouter }; 11 | -------------------------------------------------------------------------------- /12_Code_Sharing_and_Reuse_Between_Services/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | req.session = null; 7 | 8 | return res.send({}); 9 | }); 10 | 11 | export { router as signoutRouter }; 12 | -------------------------------------------------------------------------------- /12_Code_Sharing_and_Reuse_Between_Services/app/client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /12_Code_Sharing_and_Reuse_Between_Services/app/client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "run", "dev"] -------------------------------------------------------------------------------- /12_Code_Sharing_and_Reuse_Between_Services/app/client/next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | webpackDevMiddleware: (config) => { 3 | config.watchOptions.poll = 300; 4 | return config; 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /12_Code_Sharing_and_Reuse_Between_Services/app/common/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules -------------------------------------------------------------------------------- /12_Code_Sharing_and_Reuse_Between_Services/app/common/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /12_Code_Sharing_and_Reuse_Between_Services/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /12_Code_Sharing_and_Reuse_Between_Services/k8s/auth-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-mongo-svc 5 | spec: 6 | selector: 7 | app: auth-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /12_Code_Sharing_and_Reuse_Between_Services/k8s/client-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: client-svc 5 | spec: 6 | selector: 7 | app: client 8 | ports: 9 | - name: client 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /13_Create_Read_Update_Destroy_Server_Setup/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /13_Create_Read_Update_Destroy_Server_Setup/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /13_Create_Read_Update_Destroy_Server_Setup/app/auth/src/routes/current-user.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { currentUser } from '@grider-ms-tickets/common'; 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/api/users/currentuser', currentUser, (req, res) => { 7 | return res.send({ currentUser: req.currentUser || null }); 8 | }); 9 | 10 | export { router as currentUserRouter }; 11 | -------------------------------------------------------------------------------- /13_Create_Read_Update_Destroy_Server_Setup/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | req.session = null; 7 | 8 | return res.send({}); 9 | }); 10 | 11 | export { router as signoutRouter }; 12 | -------------------------------------------------------------------------------- /13_Create_Read_Update_Destroy_Server_Setup/app/client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /13_Create_Read_Update_Destroy_Server_Setup/app/client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "run", "dev"] -------------------------------------------------------------------------------- /13_Create_Read_Update_Destroy_Server_Setup/app/client/next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | webpackDevMiddleware: (config) => { 3 | config.watchOptions.poll = 300; 4 | return config; 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /13_Create_Read_Update_Destroy_Server_Setup/app/common/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules -------------------------------------------------------------------------------- /13_Create_Read_Update_Destroy_Server_Setup/app/common/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /13_Create_Read_Update_Destroy_Server_Setup/app/tickets/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /13_Create_Read_Update_Destroy_Server_Setup/app/tickets/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /13_Create_Read_Update_Destroy_Server_Setup/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /13_Create_Read_Update_Destroy_Server_Setup/k8s/auth-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-mongo-svc 5 | spec: 6 | selector: 7 | app: auth-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /13_Create_Read_Update_Destroy_Server_Setup/k8s/client-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: client-svc 5 | spec: 6 | selector: 7 | app: client 8 | ports: 9 | - name: client 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /13_Create_Read_Update_Destroy_Server_Setup/k8s/tickets-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-svc 5 | spec: 6 | selector: 7 | app: tickets 8 | ports: 9 | - name: tickets 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /13_Create_Read_Update_Destroy_Server_Setup/k8s/tickets-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-mongo-svc 5 | spec: 6 | selector: 7 | app: tickets-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /14_NATS_Streaming_Server_An_Event_Bus_Implementation/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /14_NATS_Streaming_Server_An_Event_Bus_Implementation/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /14_NATS_Streaming_Server_An_Event_Bus_Implementation/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | req.session = null; 7 | 8 | return res.send({}); 9 | }); 10 | 11 | export { router as signoutRouter }; 12 | -------------------------------------------------------------------------------- /14_NATS_Streaming_Server_An_Event_Bus_Implementation/app/client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /14_NATS_Streaming_Server_An_Event_Bus_Implementation/app/client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "run", "dev"] -------------------------------------------------------------------------------- /14_NATS_Streaming_Server_An_Event_Bus_Implementation/app/client/next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | webpackDevMiddleware: (config) => { 3 | config.watchOptions.poll = 300; 4 | return config; 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /14_NATS_Streaming_Server_An_Event_Bus_Implementation/app/common/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules -------------------------------------------------------------------------------- /14_NATS_Streaming_Server_An_Event_Bus_Implementation/app/common/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /14_NATS_Streaming_Server_An_Event_Bus_Implementation/app/tickets/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /14_NATS_Streaming_Server_An_Event_Bus_Implementation/app/tickets/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /14_NATS_Streaming_Server_An_Event_Bus_Implementation/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /14_NATS_Streaming_Server_An_Event_Bus_Implementation/k8s/auth-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-mongo-svc 5 | spec: 6 | selector: 7 | app: auth-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /14_NATS_Streaming_Server_An_Event_Bus_Implementation/k8s/client-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: client-svc 5 | spec: 6 | selector: 7 | app: client 8 | ports: 9 | - name: client 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /14_NATS_Streaming_Server_An_Event_Bus_Implementation/k8s/nats-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nats-svc 5 | spec: 6 | selector: 7 | app: nats 8 | ports: 9 | - name: nats-client 10 | protocol: TCP 11 | port: 4222 12 | targetPort: 4222 13 | - name: nats-monitoring 14 | protocol: TCP 15 | port: 8222 16 | targetPort: 8222 17 | -------------------------------------------------------------------------------- /14_NATS_Streaming_Server_An_Event_Bus_Implementation/k8s/tickets-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-svc 5 | spec: 6 | selector: 7 | app: tickets 8 | ports: 9 | - name: tickets 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /14_NATS_Streaming_Server_An_Event_Bus_Implementation/k8s/tickets-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-mongo-svc 5 | spec: 6 | selector: 7 | app: tickets-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/app/auth/src/routes/current-user.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { currentUser } from '@grider-ms-tickets/common'; 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/api/users/currentuser', currentUser, (req, res) => { 7 | return res.send({ currentUser: req.currentUser || null }); 8 | }); 9 | 10 | export { router as currentUserRouter }; 11 | -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | req.session = null; 7 | 8 | return res.send({}); 9 | }); 10 | 11 | export { router as signoutRouter }; 12 | -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/app/client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/app/client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "run", "dev"] -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/app/client/next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | webpackDevMiddleware: (config) => { 3 | config.watchOptions.poll = 300; 4 | return config; 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/app/common/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/app/common/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/app/common/src/events/SubjectsEnum.ts: -------------------------------------------------------------------------------- 1 | export enum SubjectsEnum { 2 | TicketCreated = 'ticket:created', 3 | TicketUpdated = 'ticket:updated', 4 | } 5 | -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/app/common/src/events/TicketCreatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketCreatedEventInterface { 4 | subject: SubjectsEnum.TicketCreated; 5 | data: { 6 | id: string; 7 | title: string; 8 | price: number; 9 | userId: string; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/app/common/src/events/TicketUpdatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketUpdatedEventInterface { 4 | subject: SubjectsEnum.TicketUpdated; 5 | data: { 6 | id: string; 7 | title: string; 8 | price: number; 9 | userId: string; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/app/nats-test/src/events/TicketCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | TicketCreatedEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketCreatedPublisher extends PublisherAbstract< 8 | TicketCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketCreated = SubjectsEnum.TicketCreated; 11 | } 12 | -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/app/tickets/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/app/tickets/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/k8s/auth-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-mongo-svc 5 | spec: 6 | selector: 7 | app: auth-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/k8s/client-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: client-svc 5 | spec: 6 | selector: 7 | app: client 8 | ports: 9 | - name: client 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/k8s/nats-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nats-svc 5 | spec: 6 | selector: 7 | app: nats 8 | ports: 9 | - name: nats-client 10 | protocol: TCP 11 | port: 4222 12 | targetPort: 4222 13 | - name: nats-monitoring 14 | protocol: TCP 15 | port: 8222 16 | targetPort: 8222 17 | -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/k8s/tickets-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-svc 5 | spec: 6 | selector: 7 | app: tickets 8 | ports: 9 | - name: tickets 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /15_Connecting_to_NATS_in_a_Node_JS_World/k8s/tickets-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-mongo-svc 5 | spec: 6 | selector: 7 | app: tickets-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/auth/src/routes/current-user.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { currentUser } from '@grider-ms-tickets/common'; 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/api/users/currentuser', currentUser, (req, res) => { 7 | return res.send({ currentUser: req.currentUser || null }); 8 | }); 9 | 10 | export { router as currentUserRouter }; 11 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | req.session = null; 7 | 8 | return res.send({}); 9 | }); 10 | 11 | export { router as signoutRouter }; 12 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "run", "dev"] -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/client/api/build-client.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export default ({ req }) => { 4 | if (typeof window === 'undefined') { 5 | return axios.create({ 6 | baseURL: 'http://172-17-0-2.kubernetes.default.svc.cluster.local', 7 | headers: req.headers, 8 | }); 9 | } else { 10 | return axios.create({ 11 | baseUrl: '/', 12 | }); 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/client/next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | webpackDevMiddleware: (config) => { 3 | config.watchOptions.poll = 300; 4 | return config; 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/common/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/common/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/common/src/events/SubjectsEnum.ts: -------------------------------------------------------------------------------- 1 | export enum SubjectsEnum { 2 | TicketCreated = 'ticket:created', 3 | TicketUpdated = 'ticket:updated', 4 | } 5 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/common/src/events/TicketCreatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketCreatedEventInterface { 4 | subject: SubjectsEnum.TicketCreated; 5 | data: { 6 | id: string; 7 | title: string; 8 | price: number; 9 | userId: string; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/common/src/events/TicketUpdatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketUpdatedEventInterface { 4 | subject: SubjectsEnum.TicketUpdated; 5 | data: { 6 | id: string; 7 | title: string; 8 | price: number; 9 | userId: string; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/nats-test/src/events/TicketCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | TicketCreatedEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketCreatedPublisher extends PublisherAbstract< 8 | TicketCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketCreated = SubjectsEnum.TicketCreated; 11 | } 12 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/tickets/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/tickets/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/tickets/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/tickets/src/events/publishers/TicketCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | SubjectsEnum, 4 | TicketCreatedEventInterface, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketCreatedPublisher extends PublisherAbstract< 8 | TicketCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketCreated = SubjectsEnum.TicketCreated; 11 | } 12 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/tickets/src/events/publishers/TicketUpdatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | SubjectsEnum, 4 | TicketUpdatedEventInterface, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketUpdatedPublisher extends PublisherAbstract< 8 | TicketUpdatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketUpdated = SubjectsEnum.TicketUpdated; 11 | } 12 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/app/tickets/src/routes/index.ts: -------------------------------------------------------------------------------- 1 | import express, { Request, Response } from 'express'; 2 | import { Ticket } from '../models/Ticket'; 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/api/tickets', async (req: Request, res: Response) => { 7 | const tickets = await Ticket.find({}); 8 | return res.send(tickets); 9 | }); 10 | 11 | export { router as indexTicketRouter }; 12 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/k8s/auth-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-mongo-svc 5 | spec: 6 | selector: 7 | app: auth-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/k8s/client-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: client-svc 5 | spec: 6 | selector: 7 | app: client 8 | ports: 9 | - name: client 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/k8s/nats-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nats-svc 5 | spec: 6 | selector: 7 | app: nats 8 | ports: 9 | - name: nats-client 10 | protocol: TCP 11 | port: 4222 12 | targetPort: 4222 13 | - name: nats-monitoring 14 | protocol: TCP 15 | port: 8222 16 | targetPort: 8222 17 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/k8s/tickets-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-svc 5 | spec: 6 | selector: 7 | app: tickets 8 | ports: 9 | - name: tickets 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /16_Managing_a_NATS_Client/k8s/tickets-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-mongo-svc 5 | spec: 6 | selector: 7 | app: tickets-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/auth/src/routes/current-user.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { currentUser } from '@grider-ms-tickets/common'; 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/api/users/currentuser', currentUser, (req, res) => { 7 | return res.send({ currentUser: req.currentUser || null }); 8 | }); 9 | 10 | export { router as currentUserRouter }; 11 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | req.session = null; 7 | 8 | return res.send({}); 9 | }); 10 | 11 | export { router as signoutRouter }; 12 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "run", "dev"] -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/client/next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | webpackDevMiddleware: (config) => { 3 | config.watchOptions.poll = 300; 4 | return config; 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/common/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/common/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/common/src/events/SubjectsEnum.ts: -------------------------------------------------------------------------------- 1 | export enum SubjectsEnum { 2 | TicketCreated = 'ticket:created', 3 | TicketUpdated = 'ticket:updated', 4 | } 5 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/common/src/events/TicketCreatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketCreatedEventInterface { 4 | subject: SubjectsEnum.TicketCreated; 5 | data: { 6 | id: string; 7 | title: string; 8 | price: number; 9 | userId: string; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/common/src/events/TicketUpdatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketUpdatedEventInterface { 4 | subject: SubjectsEnum.TicketUpdated; 5 | data: { 6 | id: string; 7 | title: string; 8 | price: number; 9 | userId: string; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/common/src/events/types/OrderStatus.ts: -------------------------------------------------------------------------------- 1 | export enum OrderStatusEnum { 2 | Created = 'created', 3 | Cancelled = 'cancelled', 4 | AwaitingPayment = 'awaiting:payment', 5 | Complete = 'complete', 6 | } 7 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/nats-test/src/events/TicketCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | TicketCreatedEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketCreatedPublisher extends PublisherAbstract< 8 | TicketCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketCreated = SubjectsEnum.TicketCreated; 11 | } 12 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/orders/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/orders/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/orders/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/tickets/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/tickets/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/app/tickets/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/k8s/auth-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-mongo-svc 5 | spec: 6 | selector: 7 | app: auth-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/k8s/client-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: client-svc 5 | spec: 6 | selector: 7 | app: client 8 | ports: 9 | - name: client 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/k8s/nats-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nats-svc 5 | spec: 6 | selector: 7 | app: nats 8 | ports: 9 | - name: nats-client 10 | protocol: TCP 11 | port: 4222 12 | targetPort: 4222 13 | - name: nats-monitoring 14 | protocol: TCP 15 | port: 8222 16 | targetPort: 8222 17 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/k8s/orders-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: orders-svc 5 | spec: 6 | selector: 7 | app: orders 8 | ports: 9 | - name: orders 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/k8s/orders-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: orders-mongo-svc 5 | spec: 6 | selector: 7 | app: orders-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/k8s/tickets-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-svc 5 | spec: 6 | selector: 7 | app: tickets 8 | ports: 9 | - name: tickets 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /17_Cross_Service_Data_Replication_In_Action/k8s/tickets-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-mongo-svc 5 | spec: 6 | selector: 7 | app: tickets-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/auth/src/routes/current-user.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { currentUser } from '@grider-ms-tickets/common'; 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/api/users/currentuser', currentUser, (req, res) => { 7 | return res.send({ currentUser: req.currentUser || null }); 8 | }); 9 | 10 | export { router as currentUserRouter }; 11 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | req.session = null; 7 | 8 | return res.send({}); 9 | }); 10 | 11 | export { router as signoutRouter }; 12 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "run", "dev"] -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/client/api/build-client.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export default ({ req }) => { 4 | if (typeof window === 'undefined') { 5 | return axios.create({ 6 | baseURL: 'http://172-17-0-2.kubernetes.default.svc.cluster.local', 7 | headers: req.headers, 8 | }); 9 | } else { 10 | return axios.create({ 11 | baseUrl: '/', 12 | }); 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/client/next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | webpackDevMiddleware: (config) => { 3 | config.watchOptions.poll = 300; 4 | return config; 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/common/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/common/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/common/src/events/OrderCancelledEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface OrderCancelledEventInterface { 4 | subject: SubjectsEnum.OrderCancelled; 5 | data: { 6 | id: string; 7 | ticket: { 8 | id: string; 9 | }; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/common/src/events/SubjectsEnum.ts: -------------------------------------------------------------------------------- 1 | export enum SubjectsEnum { 2 | TicketCreated = 'ticket:created', 3 | TicketUpdated = 'ticket:updated', 4 | 5 | OrderCreated = 'order:created', 6 | OrderCancelled = 'order:cancelled', 7 | } 8 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/common/src/events/TicketCreatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketCreatedEventInterface { 4 | subject: SubjectsEnum.TicketCreated; 5 | data: { 6 | id: string; 7 | title: string; 8 | price: number; 9 | userId: string; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/common/src/events/TicketUpdatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketUpdatedEventInterface { 4 | subject: SubjectsEnum.TicketUpdated; 5 | data: { 6 | id: string; 7 | title: string; 8 | price: number; 9 | userId: string; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/common/src/events/types/OrderStatusEnum.ts: -------------------------------------------------------------------------------- 1 | export enum OrderStatusEnum { 2 | Created = 'created', 3 | Cancelled = 'cancelled', 4 | AwaitingPayment = 'awaiting:payment', 5 | Complete = 'complete', 6 | } 7 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/nats-test/src/events/TicketCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | TicketCreatedEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketCreatedPublisher extends PublisherAbstract< 8 | TicketCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketCreated = SubjectsEnum.TicketCreated; 11 | } 12 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/orders/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/orders/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/orders/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/orders/src/events/publishers/OrderCancelledPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | OrderCancelledEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class OrderCancelledPublisher extends PublisherAbstract< 8 | OrderCancelledEventInterface 9 | > { 10 | subject: SubjectsEnum.OrderCancelled = SubjectsEnum.OrderCancelled; 11 | } 12 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/orders/src/events/publishers/OrderCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | OrderCreatedEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class OrderCreatedPublisher extends PublisherAbstract< 8 | OrderCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.OrderCreated = SubjectsEnum.OrderCreated; 11 | } 12 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/tickets/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/tickets/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/tickets/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/tickets/src/events/publishers/TicketCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | SubjectsEnum, 4 | TicketCreatedEventInterface, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketCreatedPublisher extends PublisherAbstract< 8 | TicketCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketCreated = SubjectsEnum.TicketCreated; 11 | } 12 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/tickets/src/events/publishers/TicketUpdatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | SubjectsEnum, 4 | TicketUpdatedEventInterface, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketUpdatedPublisher extends PublisherAbstract< 8 | TicketUpdatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketUpdated = SubjectsEnum.TicketUpdated; 11 | } 12 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/app/tickets/src/routes/index.ts: -------------------------------------------------------------------------------- 1 | import express, { Request, Response } from 'express'; 2 | import { Ticket } from '../models/Ticket'; 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/api/tickets', async (req: Request, res: Response) => { 7 | const tickets = await Ticket.find({}); 8 | return res.send(tickets); 9 | }); 10 | 11 | export { router as indexTicketRouter }; 12 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/k8s/auth-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-mongo-svc 5 | spec: 6 | selector: 7 | app: auth-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/k8s/client-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: client-svc 5 | spec: 6 | selector: 7 | app: client 8 | ports: 9 | - name: client 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/k8s/nats-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nats-svc 5 | spec: 6 | selector: 7 | app: nats 8 | ports: 9 | - name: nats-client 10 | protocol: TCP 11 | port: 4222 12 | targetPort: 4222 13 | - name: nats-monitoring 14 | protocol: TCP 15 | port: 8222 16 | targetPort: 8222 17 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/k8s/orders-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: orders-svc 5 | spec: 6 | selector: 7 | app: orders 8 | ports: 9 | - name: orders 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/k8s/orders-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: orders-mongo-svc 5 | spec: 6 | selector: 7 | app: orders-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/k8s/tickets-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-svc 5 | spec: 6 | selector: 7 | app: tickets 8 | ports: 9 | - name: tickets 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /18_Understanding_Event_Flow/k8s/tickets-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-mongo-svc 5 | spec: 6 | selector: 7 | app: tickets-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | req.session = null; 7 | 8 | return res.send({}); 9 | }); 10 | 11 | export { router as signoutRouter }; 12 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "run", "dev"] -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/client/next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | webpackDevMiddleware: (config) => { 3 | config.watchOptions.poll = 300; 4 | return config; 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/common/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/common/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/common/src/events/OrderCancelledEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface OrderCancelledEventInterface { 4 | subject: SubjectsEnum.OrderCancelled; 5 | data: { 6 | id: string; 7 | version: number; 8 | ticket: { 9 | id: string; 10 | }; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/common/src/events/SubjectsEnum.ts: -------------------------------------------------------------------------------- 1 | export enum SubjectsEnum { 2 | TicketCreated = 'ticket:created', 3 | TicketUpdated = 'ticket:updated', 4 | 5 | OrderCreated = 'order:created', 6 | OrderCancelled = 'order:cancelled', 7 | } 8 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/common/src/events/TicketCreatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketCreatedEventInterface { 4 | subject: SubjectsEnum.TicketCreated; 5 | data: { 6 | id: string; 7 | version: number; 8 | title: string; 9 | price: number; 10 | userId: string; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/common/src/events/types/OrderStatusEnum.ts: -------------------------------------------------------------------------------- 1 | export enum OrderStatusEnum { 2 | Created = 'created', 3 | Cancelled = 'cancelled', 4 | AwaitingPayment = 'awaiting:payment', 5 | Complete = 'complete', 6 | } 7 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/orders/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/orders/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/orders/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/orders/src/events/listeners/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'orders-service'; 2 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/tickets/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/tickets/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/tickets/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/app/tickets/src/events/listeners/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'tickets-service'; 2 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/k8s/auth-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-mongo-svc 5 | spec: 6 | selector: 7 | app: auth-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/k8s/client-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: client-svc 5 | spec: 6 | selector: 7 | app: client 8 | ports: 9 | - name: client 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/k8s/nats-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nats-svc 5 | spec: 6 | selector: 7 | app: nats 8 | ports: 9 | - name: nats-client 10 | protocol: TCP 11 | port: 4222 12 | targetPort: 4222 13 | - name: nats-monitoring 14 | protocol: TCP 15 | port: 8222 16 | targetPort: 8222 17 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/k8s/orders-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: orders-svc 5 | spec: 6 | selector: 7 | app: orders 8 | ports: 9 | - name: orders 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/k8s/orders-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: orders-mongo-svc 5 | spec: 6 | selector: 7 | app: orders-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/k8s/tickets-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-svc 5 | spec: 6 | selector: 7 | app: tickets 8 | ports: 9 | - name: tickets 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /19_Listening_for_Events_and_Handling_Concurrency_Issues/k8s/tickets-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-mongo-svc 5 | spec: 6 | selector: 7 | app: tickets-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /20_Worker_Services/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /20_Worker_Services/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /20_Worker_Services/app/auth/src/routes/current-user.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { currentUser } from '@grider-ms-tickets/common'; 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/api/users/currentuser', currentUser, (req, res) => { 7 | return res.send({ currentUser: req.currentUser || null }); 8 | }); 9 | 10 | export { router as currentUserRouter }; 11 | -------------------------------------------------------------------------------- /20_Worker_Services/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | req.session = null; 7 | 8 | return res.send({}); 9 | }); 10 | 11 | export { router as signoutRouter }; 12 | -------------------------------------------------------------------------------- /20_Worker_Services/app/client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /20_Worker_Services/app/client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "run", "dev"] -------------------------------------------------------------------------------- /20_Worker_Services/app/client/api/build-client.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export default ({ req }) => { 4 | if (typeof window === 'undefined') { 5 | return axios.create({ 6 | baseURL: 'http://172-17-0-2.kubernetes.default.svc.cluster.local', 7 | headers: req.headers, 8 | }); 9 | } else { 10 | return axios.create({ 11 | baseUrl: '/', 12 | }); 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /20_Worker_Services/app/client/next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | webpackDevMiddleware: (config) => { 3 | config.watchOptions.poll = 300; 4 | return config; 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /20_Worker_Services/app/common/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules -------------------------------------------------------------------------------- /20_Worker_Services/app/common/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /20_Worker_Services/app/common/src/events/ExpirationCompleteEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface ExpirationCompleteEventInterface { 4 | subject: SubjectsEnum.ExpirationComplete; 5 | data: { 6 | orderId: string; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /20_Worker_Services/app/common/src/events/OrderCancelledEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface OrderCancelledEventInterface { 4 | subject: SubjectsEnum.OrderCancelled; 5 | data: { 6 | id: string; 7 | version: number; 8 | ticket: { 9 | id: string; 10 | }; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /20_Worker_Services/app/common/src/events/SubjectsEnum.ts: -------------------------------------------------------------------------------- 1 | export enum SubjectsEnum { 2 | TicketCreated = 'ticket:created', 3 | TicketUpdated = 'ticket:updated', 4 | 5 | OrderCreated = 'order:created', 6 | OrderCancelled = 'order:cancelled', 7 | 8 | ExpirationComplete = 'expiration:complete', 9 | } 10 | -------------------------------------------------------------------------------- /20_Worker_Services/app/common/src/events/TicketCreatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketCreatedEventInterface { 4 | subject: SubjectsEnum.TicketCreated; 5 | data: { 6 | id: string; 7 | version: number; 8 | title: string; 9 | price: number; 10 | userId: string; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /20_Worker_Services/app/common/src/events/TicketUpdatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketUpdatedEventInterface { 4 | subject: SubjectsEnum.TicketUpdated; 5 | data: { 6 | id: string; 7 | version: number; 8 | title: string; 9 | price: number; 10 | userId: string; 11 | orderId?: string; 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /20_Worker_Services/app/common/src/events/types/OrderStatusEnum.ts: -------------------------------------------------------------------------------- 1 | export enum OrderStatusEnum { 2 | Created = 'created', 3 | Cancelled = 'cancelled', 4 | AwaitingPayment = 'awaiting:payment', 5 | Complete = 'complete', 6 | } 7 | -------------------------------------------------------------------------------- /20_Worker_Services/app/expiration/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /20_Worker_Services/app/expiration/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /20_Worker_Services/app/expiration/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /20_Worker_Services/app/expiration/src/events/listeneres/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'expiration-service'; 2 | -------------------------------------------------------------------------------- /20_Worker_Services/app/nats-test/src/events/TicketCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | TicketCreatedEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketCreatedPublisher extends PublisherAbstract< 8 | TicketCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketCreated = SubjectsEnum.TicketCreated; 11 | } 12 | -------------------------------------------------------------------------------- /20_Worker_Services/app/orders/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /20_Worker_Services/app/orders/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /20_Worker_Services/app/orders/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /20_Worker_Services/app/orders/src/events/listeners/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'orders-service'; 2 | -------------------------------------------------------------------------------- /20_Worker_Services/app/orders/src/events/publishers/OrderCancelledPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | OrderCancelledEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class OrderCancelledPublisher extends PublisherAbstract< 8 | OrderCancelledEventInterface 9 | > { 10 | subject: SubjectsEnum.OrderCancelled = SubjectsEnum.OrderCancelled; 11 | } 12 | -------------------------------------------------------------------------------- /20_Worker_Services/app/orders/src/events/publishers/OrderCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | OrderCreatedEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class OrderCreatedPublisher extends PublisherAbstract< 8 | OrderCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.OrderCreated = SubjectsEnum.OrderCreated; 11 | } 12 | -------------------------------------------------------------------------------- /20_Worker_Services/app/tickets/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /20_Worker_Services/app/tickets/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /20_Worker_Services/app/tickets/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /20_Worker_Services/app/tickets/src/events/listeners/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'tickets-service'; 2 | -------------------------------------------------------------------------------- /20_Worker_Services/app/tickets/src/events/publishers/TicketCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | SubjectsEnum, 4 | TicketCreatedEventInterface, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketCreatedPublisher extends PublisherAbstract< 8 | TicketCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketCreated = SubjectsEnum.TicketCreated; 11 | } 12 | -------------------------------------------------------------------------------- /20_Worker_Services/app/tickets/src/events/publishers/TicketUpdatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | SubjectsEnum, 4 | TicketUpdatedEventInterface, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketUpdatedPublisher extends PublisherAbstract< 8 | TicketUpdatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketUpdated = SubjectsEnum.TicketUpdated; 11 | } 12 | -------------------------------------------------------------------------------- /20_Worker_Services/app/tickets/src/routes/index.ts: -------------------------------------------------------------------------------- 1 | import express, { Request, Response } from 'express'; 2 | import { Ticket } from '../models/Ticket'; 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/api/tickets', async (req: Request, res: Response) => { 7 | const tickets = await Ticket.find({}); 8 | return res.send(tickets); 9 | }); 10 | 11 | export { router as indexTicketRouter }; 12 | -------------------------------------------------------------------------------- /20_Worker_Services/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /20_Worker_Services/k8s/auth-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-mongo-svc 5 | spec: 6 | selector: 7 | app: auth-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /20_Worker_Services/k8s/client-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: client-svc 5 | spec: 6 | selector: 7 | app: client 8 | ports: 9 | - name: client 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /20_Worker_Services/k8s/expiration-redis-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: expiration-redis-svc 5 | spec: 6 | selector: 7 | app: expiration-redis 8 | ports: 9 | - name: expiration-redis 10 | protocol: TCP 11 | port: 6379 12 | targetPort: 6379 13 | -------------------------------------------------------------------------------- /20_Worker_Services/k8s/nats-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nats-svc 5 | spec: 6 | selector: 7 | app: nats 8 | ports: 9 | - name: nats-client 10 | protocol: TCP 11 | port: 4222 12 | targetPort: 4222 13 | - name: nats-monitoring 14 | protocol: TCP 15 | port: 8222 16 | targetPort: 8222 17 | -------------------------------------------------------------------------------- /20_Worker_Services/k8s/orders-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: orders-svc 5 | spec: 6 | selector: 7 | app: orders 8 | ports: 9 | - name: orders 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /20_Worker_Services/k8s/orders-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: orders-mongo-svc 5 | spec: 6 | selector: 7 | app: orders-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /20_Worker_Services/k8s/tickets-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-svc 5 | spec: 6 | selector: 7 | app: tickets 8 | ports: 9 | - name: tickets 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /20_Worker_Services/k8s/tickets-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-mongo-svc 5 | spec: 6 | selector: 7 | app: tickets-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /21_Handling_Payments/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /21_Handling_Payments/app/auth/src/routes/current-user.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { currentUser } from '@grider-ms-tickets/common'; 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/api/users/currentuser', currentUser, (req, res) => { 7 | return res.send({ currentUser: req.currentUser || null }); 8 | }); 9 | 10 | export { router as currentUserRouter }; 11 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | req.session = null; 7 | 8 | return res.send({}); 9 | }); 10 | 11 | export { router as signoutRouter }; 12 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /21_Handling_Payments/app/client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "run", "dev"] -------------------------------------------------------------------------------- /21_Handling_Payments/app/client/api/build-client.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export default ({ req }) => { 4 | if (typeof window === 'undefined') { 5 | return axios.create({ 6 | baseURL: 'http://172-17-0-2.kubernetes.default.svc.cluster.local', 7 | headers: req.headers, 8 | }); 9 | } else { 10 | return axios.create({ 11 | baseUrl: '/', 12 | }); 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/client/next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | webpackDevMiddleware: (config) => { 3 | config.watchOptions.poll = 300; 4 | return config; 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/common/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules -------------------------------------------------------------------------------- /21_Handling_Payments/app/common/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/common/src/events/ExpirationCompleteEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface ExpirationCompleteEventInterface { 4 | subject: SubjectsEnum.ExpirationComplete; 5 | data: { 6 | orderId: string; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/common/src/events/OrderCancelledEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface OrderCancelledEventInterface { 4 | subject: SubjectsEnum.OrderCancelled; 5 | data: { 6 | id: string; 7 | version: number; 8 | ticket: { 9 | id: string; 10 | }; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/common/src/events/PaymentCreatedEventInteface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface PaymentCreatedEventInteface { 4 | subject: SubjectsEnum.PaymentCreated; 5 | data: { 6 | id: string; 7 | orderId: string; 8 | stripeId: string; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/common/src/events/SubjectsEnum.ts: -------------------------------------------------------------------------------- 1 | export enum SubjectsEnum { 2 | TicketCreated = 'ticket:created', 3 | TicketUpdated = 'ticket:updated', 4 | 5 | OrderCreated = 'order:created', 6 | OrderCancelled = 'order:cancelled', 7 | 8 | ExpirationComplete = 'expiration:complete', 9 | 10 | PaymentCreated = 'payment:created', 11 | } 12 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/common/src/events/TicketCreatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketCreatedEventInterface { 4 | subject: SubjectsEnum.TicketCreated; 5 | data: { 6 | id: string; 7 | version: number; 8 | title: string; 9 | price: number; 10 | userId: string; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/common/src/events/TicketUpdatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketUpdatedEventInterface { 4 | subject: SubjectsEnum.TicketUpdated; 5 | data: { 6 | id: string; 7 | version: number; 8 | title: string; 9 | price: number; 10 | userId: string; 11 | orderId?: string; 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/common/src/events/types/OrderStatusEnum.ts: -------------------------------------------------------------------------------- 1 | export enum OrderStatusEnum { 2 | Created = 'created', 3 | Cancelled = 'cancelled', 4 | AwaitingPayment = 'awaiting:payment', 5 | Complete = 'complete', 6 | } 7 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/expiration/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /21_Handling_Payments/app/expiration/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /21_Handling_Payments/app/expiration/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/expiration/src/events/listeneres/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'expiration-service'; 2 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/nats-test/src/events/TicketCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | TicketCreatedEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketCreatedPublisher extends PublisherAbstract< 8 | TicketCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketCreated = SubjectsEnum.TicketCreated; 11 | } 12 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/orders/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /21_Handling_Payments/app/orders/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /21_Handling_Payments/app/orders/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/orders/src/events/listeners/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'orders-service'; 2 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/orders/src/events/publishers/OrderCancelledPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | OrderCancelledEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class OrderCancelledPublisher extends PublisherAbstract< 8 | OrderCancelledEventInterface 9 | > { 10 | subject: SubjectsEnum.OrderCancelled = SubjectsEnum.OrderCancelled; 11 | } 12 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/orders/src/events/publishers/OrderCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | OrderCreatedEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class OrderCreatedPublisher extends PublisherAbstract< 8 | OrderCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.OrderCreated = SubjectsEnum.OrderCreated; 11 | } 12 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/payments/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /21_Handling_Payments/app/payments/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /21_Handling_Payments/app/payments/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/payments/src/__mocks__/stripe.ts.disabled: -------------------------------------------------------------------------------- 1 | export const stripe = { 2 | charges: { 3 | create: jest.fn().mockResolvedValue({}), 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/payments/src/events/listeners/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'payments-service'; 2 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/payments/src/events/publishers/PaymentCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | SubjectsEnum, 3 | PublisherAbstract, 4 | PaymentCreatedEventInteface, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class PaymentCreatedPublisher extends PublisherAbstract< 8 | PaymentCreatedEventInteface 9 | > { 10 | subject: SubjectsEnum.PaymentCreated = SubjectsEnum.PaymentCreated; 11 | } 12 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/payments/src/stripe.ts: -------------------------------------------------------------------------------- 1 | import Stripe from 'stripe'; 2 | 3 | export const stripe = new Stripe(process.env.STRIPE_KEY!, { 4 | apiVersion: '2020-03-02', 5 | }); 6 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/tickets/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /21_Handling_Payments/app/tickets/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /21_Handling_Payments/app/tickets/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/tickets/src/events/listeners/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'tickets-service'; 2 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/tickets/src/events/publishers/TicketCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | SubjectsEnum, 4 | TicketCreatedEventInterface, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketCreatedPublisher extends PublisherAbstract< 8 | TicketCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketCreated = SubjectsEnum.TicketCreated; 11 | } 12 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/tickets/src/events/publishers/TicketUpdatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | SubjectsEnum, 4 | TicketUpdatedEventInterface, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketUpdatedPublisher extends PublisherAbstract< 8 | TicketUpdatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketUpdated = SubjectsEnum.TicketUpdated; 11 | } 12 | -------------------------------------------------------------------------------- /21_Handling_Payments/app/tickets/src/routes/index.ts: -------------------------------------------------------------------------------- 1 | import express, { Request, Response } from 'express'; 2 | import { Ticket } from '../models/Ticket'; 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/api/tickets', async (req: Request, res: Response) => { 7 | const tickets = await Ticket.find({}); 8 | return res.send(tickets); 9 | }); 10 | 11 | export { router as indexTicketRouter }; 12 | -------------------------------------------------------------------------------- /21_Handling_Payments/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /21_Handling_Payments/k8s/auth-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-mongo-svc 5 | spec: 6 | selector: 7 | app: auth-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /21_Handling_Payments/k8s/client-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: client-svc 5 | spec: 6 | selector: 7 | app: client 8 | ports: 9 | - name: client 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /21_Handling_Payments/k8s/expiration-redis-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: expiration-redis-svc 5 | spec: 6 | selector: 7 | app: expiration-redis 8 | ports: 9 | - name: expiration-redis 10 | protocol: TCP 11 | port: 6379 12 | targetPort: 6379 13 | -------------------------------------------------------------------------------- /21_Handling_Payments/k8s/nats-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nats-svc 5 | spec: 6 | selector: 7 | app: nats 8 | ports: 9 | - name: nats-client 10 | protocol: TCP 11 | port: 4222 12 | targetPort: 4222 13 | - name: nats-monitoring 14 | protocol: TCP 15 | port: 8222 16 | targetPort: 8222 17 | -------------------------------------------------------------------------------- /21_Handling_Payments/k8s/orders-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: orders-svc 5 | spec: 6 | selector: 7 | app: orders 8 | ports: 9 | - name: orders 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /21_Handling_Payments/k8s/orders-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: orders-mongo-svc 5 | spec: 6 | selector: 7 | app: orders-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /21_Handling_Payments/k8s/payments-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: payments-svc 5 | spec: 6 | selector: 7 | app: payments 8 | ports: 9 | - name: payments 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /21_Handling_Payments/k8s/payments-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: payments-mongo-svc 5 | spec: 6 | selector: 7 | app: payments-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /21_Handling_Payments/k8s/tickets-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-svc 5 | spec: 6 | selector: 7 | app: tickets 8 | ports: 9 | - name: tickets 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /21_Handling_Payments/k8s/tickets-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-mongo-svc 5 | spec: 6 | selector: 7 | app: tickets-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/auth/src/routes/current-user.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { currentUser } from '@grider-ms-tickets/common'; 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/api/users/currentuser', currentUser, (req, res) => { 7 | return res.send({ currentUser: req.currentUser || null }); 8 | }); 9 | 10 | export { router as currentUserRouter }; 11 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | req.session = null; 7 | 8 | return res.send({}); 9 | }); 10 | 11 | export { router as signoutRouter }; 12 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "run", "dev"] -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/client/api/build-client.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export default ({ req }) => { 4 | if (typeof window === 'undefined') { 5 | return axios.create({ 6 | baseURL: 'http://172-17-0-2.kubernetes.default.svc.cluster.local', 7 | headers: req.headers, 8 | }); 9 | } else { 10 | return axios.create({ 11 | baseUrl: '/', 12 | }); 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/client/next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | webpackDevMiddleware: (config) => { 3 | config.watchOptions.poll = 300; 4 | return config; 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/common/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/common/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/common/src/events/ExpirationCompleteEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface ExpirationCompleteEventInterface { 4 | subject: SubjectsEnum.ExpirationComplete; 5 | data: { 6 | orderId: string; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/common/src/events/OrderCancelledEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface OrderCancelledEventInterface { 4 | subject: SubjectsEnum.OrderCancelled; 5 | data: { 6 | id: string; 7 | version: number; 8 | ticket: { 9 | id: string; 10 | }; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/common/src/events/PaymentCreatedEventInteface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface PaymentCreatedEventInteface { 4 | subject: SubjectsEnum.PaymentCreated; 5 | data: { 6 | id: string; 7 | orderId: string; 8 | stripeId: string; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/common/src/events/SubjectsEnum.ts: -------------------------------------------------------------------------------- 1 | export enum SubjectsEnum { 2 | TicketCreated = 'ticket:created', 3 | TicketUpdated = 'ticket:updated', 4 | 5 | OrderCreated = 'order:created', 6 | OrderCancelled = 'order:cancelled', 7 | 8 | ExpirationComplete = 'expiration:complete', 9 | 10 | PaymentCreated = 'payment:created', 11 | } 12 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/common/src/events/TicketCreatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketCreatedEventInterface { 4 | subject: SubjectsEnum.TicketCreated; 5 | data: { 6 | id: string; 7 | version: number; 8 | title: string; 9 | price: number; 10 | userId: string; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/common/src/events/TicketUpdatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketUpdatedEventInterface { 4 | subject: SubjectsEnum.TicketUpdated; 5 | data: { 6 | id: string; 7 | version: number; 8 | title: string; 9 | price: number; 10 | userId: string; 11 | orderId?: string; 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/common/src/events/types/OrderStatusEnum.ts: -------------------------------------------------------------------------------- 1 | export enum OrderStatusEnum { 2 | Created = 'created', 3 | Cancelled = 'cancelled', 4 | AwaitingPayment = 'awaiting:payment', 5 | Complete = 'complete', 6 | } 7 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/expiration/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/expiration/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/expiration/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/expiration/src/events/listeneres/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'expiration-service'; 2 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/nats-test/src/events/TicketCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | TicketCreatedEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketCreatedPublisher extends PublisherAbstract< 8 | TicketCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketCreated = SubjectsEnum.TicketCreated; 11 | } 12 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/orders/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/orders/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/orders/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/orders/src/events/listeners/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'orders-service'; 2 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/orders/src/events/publishers/OrderCancelledPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | OrderCancelledEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class OrderCancelledPublisher extends PublisherAbstract< 8 | OrderCancelledEventInterface 9 | > { 10 | subject: SubjectsEnum.OrderCancelled = SubjectsEnum.OrderCancelled; 11 | } 12 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/orders/src/events/publishers/OrderCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | OrderCreatedEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class OrderCreatedPublisher extends PublisherAbstract< 8 | OrderCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.OrderCreated = SubjectsEnum.OrderCreated; 11 | } 12 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/payments/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/payments/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/payments/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/payments/src/__mocks__/stripe.ts.disabled: -------------------------------------------------------------------------------- 1 | export const stripe = { 2 | charges: { 3 | create: jest.fn().mockResolvedValue({}), 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/payments/src/events/listeners/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'payments-service'; 2 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/payments/src/events/publishers/PaymentCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | SubjectsEnum, 3 | PublisherAbstract, 4 | PaymentCreatedEventInteface, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class PaymentCreatedPublisher extends PublisherAbstract< 8 | PaymentCreatedEventInteface 9 | > { 10 | subject: SubjectsEnum.PaymentCreated = SubjectsEnum.PaymentCreated; 11 | } 12 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/payments/src/stripe.ts: -------------------------------------------------------------------------------- 1 | import Stripe from 'stripe'; 2 | 3 | export const stripe = new Stripe(process.env.STRIPE_KEY!, { 4 | apiVersion: '2020-03-02', 5 | }); 6 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/tickets/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/tickets/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/tickets/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/tickets/src/events/listeners/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'tickets-service'; 2 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/tickets/src/events/publishers/TicketCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | SubjectsEnum, 4 | TicketCreatedEventInterface, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketCreatedPublisher extends PublisherAbstract< 8 | TicketCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketCreated = SubjectsEnum.TicketCreated; 11 | } 12 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/app/tickets/src/events/publishers/TicketUpdatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | SubjectsEnum, 4 | TicketUpdatedEventInterface, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketUpdatedPublisher extends PublisherAbstract< 8 | TicketUpdatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketUpdated = SubjectsEnum.TicketUpdated; 11 | } 12 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/k8s/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/k8s/auth-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-mongo-svc 5 | spec: 6 | selector: 7 | app: auth-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/k8s/client-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: client-svc 5 | spec: 6 | selector: 7 | app: client 8 | ports: 9 | - name: client 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/k8s/expiration-redis-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: expiration-redis-svc 5 | spec: 6 | selector: 7 | app: expiration-redis 8 | ports: 9 | - name: expiration-redis 10 | protocol: TCP 11 | port: 6379 12 | targetPort: 6379 13 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/k8s/nats-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nats-svc 5 | spec: 6 | selector: 7 | app: nats 8 | ports: 9 | - name: nats-client 10 | protocol: TCP 11 | port: 4222 12 | targetPort: 4222 13 | - name: nats-monitoring 14 | protocol: TCP 15 | port: 8222 16 | targetPort: 8222 17 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/k8s/orders-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: orders-svc 5 | spec: 6 | selector: 7 | app: orders 8 | ports: 9 | - name: orders 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/k8s/orders-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: orders-mongo-svc 5 | spec: 6 | selector: 7 | app: orders-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/k8s/payments-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: payments-svc 5 | spec: 6 | selector: 7 | app: payments 8 | ports: 9 | - name: payments 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/k8s/payments-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: payments-mongo-svc 5 | spec: 6 | selector: 7 | app: payments-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/k8s/tickets-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-svc 5 | spec: 6 | selector: 7 | app: tickets 8 | ports: 9 | - name: tickets 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /22_Back_to_the_Client/k8s/tickets-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-mongo-svc 5 | spec: 6 | selector: 7 | app: tickets-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /23_CI_CD/app/auth/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /23_CI_CD/app/auth/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /23_CI_CD/app/auth/src/routes/current-user.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { currentUser } from '@grider-ms-tickets/common'; 3 | 4 | const router = express.Router(); 5 | 6 | router.get('/api/users/currentuser', currentUser, (req, res) => { 7 | return res.send({ currentUser: req.currentUser || null }); 8 | }); 9 | 10 | export { router as currentUserRouter }; 11 | -------------------------------------------------------------------------------- /23_CI_CD/app/auth/src/routes/signout.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.post('/api/users/signout', (req, res) => { 6 | req.session = null; 7 | 8 | return res.send({}); 9 | }); 10 | 11 | export { router as signoutRouter }; 12 | -------------------------------------------------------------------------------- /23_CI_CD/app/client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /23_CI_CD/app/client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "run", "dev"] -------------------------------------------------------------------------------- /23_CI_CD/app/client/api/build-client.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export default ({ req }) => { 4 | if (typeof window === 'undefined') { 5 | return axios.create({ 6 | baseURL: 'http://172-17-0-2.kubernetes.default.svc.cluster.local', 7 | headers: req.headers, 8 | }); 9 | } else { 10 | return axios.create({ 11 | baseUrl: '/', 12 | }); 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /23_CI_CD/app/client/next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | webpackDevMiddleware: (config) => { 3 | config.watchOptions.poll = 300; 4 | return config; 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /23_CI_CD/app/common/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules -------------------------------------------------------------------------------- /23_CI_CD/app/common/src/errors/custom-error.ts: -------------------------------------------------------------------------------- 1 | export abstract class CustomError extends Error { 2 | abstract statusCode: number; 3 | 4 | constructor(message: string) { 5 | super(message); 6 | Object.setPrototypeOf(this, CustomError.prototype); 7 | } 8 | 9 | abstract serializeErrors(): { message: string; field?: string }[]; 10 | } 11 | -------------------------------------------------------------------------------- /23_CI_CD/app/common/src/errors/not-found-error.ts: -------------------------------------------------------------------------------- 1 | import { CustomError } from './custom-error'; 2 | 3 | export class NotFoundError extends CustomError { 4 | statusCode = 404; 5 | 6 | constructor() { 7 | super('Route not found'); 8 | 9 | Object.setPrototypeOf(this, NotFoundError.prototype); 10 | } 11 | 12 | serializeErrors() { 13 | return [{ message: 'Not Found' }]; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /23_CI_CD/app/common/src/events/ExpirationCompleteEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface ExpirationCompleteEventInterface { 4 | subject: SubjectsEnum.ExpirationComplete; 5 | data: { 6 | orderId: string; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /23_CI_CD/app/common/src/events/OrderCancelledEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface OrderCancelledEventInterface { 4 | subject: SubjectsEnum.OrderCancelled; 5 | data: { 6 | id: string; 7 | version: number; 8 | ticket: { 9 | id: string; 10 | }; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /23_CI_CD/app/common/src/events/PaymentCreatedEventInteface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface PaymentCreatedEventInteface { 4 | subject: SubjectsEnum.PaymentCreated; 5 | data: { 6 | id: string; 7 | orderId: string; 8 | stripeId: string; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /23_CI_CD/app/common/src/events/SubjectsEnum.ts: -------------------------------------------------------------------------------- 1 | export enum SubjectsEnum { 2 | TicketCreated = 'ticket:created', 3 | TicketUpdated = 'ticket:updated', 4 | 5 | OrderCreated = 'order:created', 6 | OrderCancelled = 'order:cancelled', 7 | 8 | ExpirationComplete = 'expiration:complete', 9 | 10 | PaymentCreated = 'payment:created', 11 | } 12 | -------------------------------------------------------------------------------- /23_CI_CD/app/common/src/events/TicketCreatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketCreatedEventInterface { 4 | subject: SubjectsEnum.TicketCreated; 5 | data: { 6 | id: string; 7 | version: number; 8 | title: string; 9 | price: number; 10 | userId: string; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /23_CI_CD/app/common/src/events/TicketUpdatedEventInterface.ts: -------------------------------------------------------------------------------- 1 | import { SubjectsEnum } from './SubjectsEnum'; 2 | 3 | export interface TicketUpdatedEventInterface { 4 | subject: SubjectsEnum.TicketUpdated; 5 | data: { 6 | id: string; 7 | version: number; 8 | title: string; 9 | price: number; 10 | userId: string; 11 | orderId?: string; 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /23_CI_CD/app/common/src/events/types/OrderStatusEnum.ts: -------------------------------------------------------------------------------- 1 | export enum OrderStatusEnum { 2 | Created = 'created', 3 | Cancelled = 'cancelled', 4 | AwaitingPayment = 'awaiting:payment', 5 | Complete = 'complete', 6 | } 7 | -------------------------------------------------------------------------------- /23_CI_CD/app/common/src/middlewares/require-auth.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response, NextFunction } from 'express'; 2 | import { NotAuthorizedError } from '../errors/not-authorized-error'; 3 | 4 | export const requireAuth = ( 5 | req: Request, 6 | res: Response, 7 | next: NextFunction 8 | ) => { 9 | if (!req.currentUser) { 10 | throw new NotAuthorizedError(); 11 | } 12 | 13 | next(); 14 | }; 15 | -------------------------------------------------------------------------------- /23_CI_CD/app/expiration/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /23_CI_CD/app/expiration/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /23_CI_CD/app/expiration/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /23_CI_CD/app/expiration/src/events/listeneres/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'expiration-service'; 2 | -------------------------------------------------------------------------------- /23_CI_CD/app/nats-test/src/events/TicketCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | TicketCreatedEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketCreatedPublisher extends PublisherAbstract< 8 | TicketCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketCreated = SubjectsEnum.TicketCreated; 11 | } 12 | -------------------------------------------------------------------------------- /23_CI_CD/app/orders/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /23_CI_CD/app/orders/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /23_CI_CD/app/orders/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /23_CI_CD/app/orders/src/events/listeners/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'orders-service'; 2 | -------------------------------------------------------------------------------- /23_CI_CD/app/orders/src/events/publishers/OrderCancelledPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | OrderCancelledEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class OrderCancelledPublisher extends PublisherAbstract< 8 | OrderCancelledEventInterface 9 | > { 10 | subject: SubjectsEnum.OrderCancelled = SubjectsEnum.OrderCancelled; 11 | } 12 | -------------------------------------------------------------------------------- /23_CI_CD/app/orders/src/events/publishers/OrderCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | OrderCreatedEventInterface, 4 | SubjectsEnum, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class OrderCreatedPublisher extends PublisherAbstract< 8 | OrderCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.OrderCreated = SubjectsEnum.OrderCreated; 11 | } 12 | -------------------------------------------------------------------------------- /23_CI_CD/app/payments/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /23_CI_CD/app/payments/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /23_CI_CD/app/payments/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /23_CI_CD/app/payments/src/__mocks__/stripe.ts.disabled: -------------------------------------------------------------------------------- 1 | export const stripe = { 2 | charges: { 3 | create: jest.fn().mockResolvedValue({}), 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /23_CI_CD/app/payments/src/events/listeners/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'payments-service'; 2 | -------------------------------------------------------------------------------- /23_CI_CD/app/payments/src/events/publishers/PaymentCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | SubjectsEnum, 3 | PublisherAbstract, 4 | PaymentCreatedEventInteface, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class PaymentCreatedPublisher extends PublisherAbstract< 8 | PaymentCreatedEventInteface 9 | > { 10 | subject: SubjectsEnum.PaymentCreated = SubjectsEnum.PaymentCreated; 11 | } 12 | -------------------------------------------------------------------------------- /23_CI_CD/app/payments/src/stripe.ts: -------------------------------------------------------------------------------- 1 | import Stripe from 'stripe'; 2 | 3 | export const stripe = new Stripe(process.env.STRIPE_KEY!, { 4 | apiVersion: '2020-03-02', 5 | }); 6 | -------------------------------------------------------------------------------- /23_CI_CD/app/tickets/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /23_CI_CD/app/tickets/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.16.3-alpine3.9 2 | 3 | WORKDIR /app 4 | COPY package.json ./ 5 | RUN npm install --only=prod 6 | COPY ./ ./ 7 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /23_CI_CD/app/tickets/src/__mocks__/NatsWrapper.ts: -------------------------------------------------------------------------------- 1 | export const natsWrapper = { 2 | client: { 3 | publish: jest 4 | .fn() 5 | .mockImplementationOnce( 6 | (subject: string, data: string, callback: () => void) => { 7 | callback(); 8 | } 9 | ), 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /23_CI_CD/app/tickets/src/events/listeners/queueGroupName.ts: -------------------------------------------------------------------------------- 1 | export const queueGroupName = 'tickets-service'; 2 | -------------------------------------------------------------------------------- /23_CI_CD/app/tickets/src/events/publishers/TicketCreatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | SubjectsEnum, 4 | TicketCreatedEventInterface, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketCreatedPublisher extends PublisherAbstract< 8 | TicketCreatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketCreated = SubjectsEnum.TicketCreated; 11 | } 12 | -------------------------------------------------------------------------------- /23_CI_CD/app/tickets/src/events/publishers/TicketUpdatedPublisher.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PublisherAbstract, 3 | SubjectsEnum, 4 | TicketUpdatedEventInterface, 5 | } from '@grider-ms-tickets/common'; 6 | 7 | export class TicketUpdatedPublisher extends PublisherAbstract< 8 | TicketUpdatedEventInterface 9 | > { 10 | subject: SubjectsEnum.TicketUpdated = SubjectsEnum.TicketUpdated; 11 | } 12 | -------------------------------------------------------------------------------- /23_CI_CD/k8s/common/auth-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-svc 5 | spec: 6 | selector: 7 | app: auth 8 | ports: 9 | - name: auth 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /23_CI_CD/k8s/common/auth-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: auth-mongo-svc 5 | spec: 6 | selector: 7 | app: auth-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /23_CI_CD/k8s/common/client-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: client-svc 5 | spec: 6 | selector: 7 | app: client 8 | ports: 9 | - name: client 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /23_CI_CD/k8s/common/expiration-redis-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: expiration-redis-svc 5 | spec: 6 | selector: 7 | app: expiration-redis 8 | ports: 9 | - name: expiration-redis 10 | protocol: TCP 11 | port: 6379 12 | targetPort: 6379 13 | -------------------------------------------------------------------------------- /23_CI_CD/k8s/common/nats-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nats-svc 5 | spec: 6 | selector: 7 | app: nats 8 | ports: 9 | - name: nats-client 10 | protocol: TCP 11 | port: 4222 12 | targetPort: 4222 13 | - name: nats-monitoring 14 | protocol: TCP 15 | port: 8222 16 | targetPort: 8222 17 | -------------------------------------------------------------------------------- /23_CI_CD/k8s/common/orders-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: orders-svc 5 | spec: 6 | selector: 7 | app: orders 8 | ports: 9 | - name: orders 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /23_CI_CD/k8s/common/orders-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: orders-mongo-svc 5 | spec: 6 | selector: 7 | app: orders-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /23_CI_CD/k8s/common/payments-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: payments-svc 5 | spec: 6 | selector: 7 | app: payments 8 | ports: 9 | - name: payments 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /23_CI_CD/k8s/common/payments-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: payments-mongo-svc 5 | spec: 6 | selector: 7 | app: payments-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /23_CI_CD/k8s/common/tickets-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-svc 5 | spec: 6 | selector: 7 | app: tickets 8 | ports: 9 | - name: tickets 10 | protocol: TCP 11 | port: 3000 12 | targetPort: 3000 13 | -------------------------------------------------------------------------------- /23_CI_CD/k8s/common/tickets-mongo-clusterIP.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: tickets-mongo-svc 5 | spec: 6 | selector: 7 | app: tickets-mongo 8 | ports: 9 | - name: db 10 | protocol: TCP 11 | port: 27017 12 | targetPort: 27017 13 | -------------------------------------------------------------------------------- /img/pic-02-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-01.png -------------------------------------------------------------------------------- /img/pic-02-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-02.png -------------------------------------------------------------------------------- /img/pic-02-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-03.png -------------------------------------------------------------------------------- /img/pic-02-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-04.png -------------------------------------------------------------------------------- /img/pic-02-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-05.png -------------------------------------------------------------------------------- /img/pic-02-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-06.png -------------------------------------------------------------------------------- /img/pic-02-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-07.png -------------------------------------------------------------------------------- /img/pic-02-08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-08.png -------------------------------------------------------------------------------- /img/pic-02-09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-09.png -------------------------------------------------------------------------------- /img/pic-02-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-10.png -------------------------------------------------------------------------------- /img/pic-02-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-11.png -------------------------------------------------------------------------------- /img/pic-02-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-12.png -------------------------------------------------------------------------------- /img/pic-02-13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-13.png -------------------------------------------------------------------------------- /img/pic-02-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-14.png -------------------------------------------------------------------------------- /img/pic-02-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-15.png -------------------------------------------------------------------------------- /img/pic-02-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-16.png -------------------------------------------------------------------------------- /img/pic-02-17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-17.png -------------------------------------------------------------------------------- /img/pic-02-18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-18.png -------------------------------------------------------------------------------- /img/pic-02-19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-19.png -------------------------------------------------------------------------------- /img/pic-02-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-20.png -------------------------------------------------------------------------------- /img/pic-02-21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-21.png -------------------------------------------------------------------------------- /img/pic-02-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-22.png -------------------------------------------------------------------------------- /img/pic-02-23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-02-23.png -------------------------------------------------------------------------------- /img/pic-04-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-04-01.png -------------------------------------------------------------------------------- /img/pic-04-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-04-02.png -------------------------------------------------------------------------------- /img/pic-04-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-04-03.png -------------------------------------------------------------------------------- /img/pic-04-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-04-04.png -------------------------------------------------------------------------------- /img/pic-04-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-04-05.png -------------------------------------------------------------------------------- /img/pic-04-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-04-06.png -------------------------------------------------------------------------------- /img/pic-04-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-04-07.png -------------------------------------------------------------------------------- /img/pic-05-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-05-01.png -------------------------------------------------------------------------------- /img/pic-05-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-05-02.png -------------------------------------------------------------------------------- /img/pic-05-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-05-03.png -------------------------------------------------------------------------------- /img/pic-05-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-05-04.png -------------------------------------------------------------------------------- /img/pic-05-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-05-05.png -------------------------------------------------------------------------------- /img/pic-08-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-08-01.png -------------------------------------------------------------------------------- /img/pic-09-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-01.png -------------------------------------------------------------------------------- /img/pic-09-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-02.png -------------------------------------------------------------------------------- /img/pic-09-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-03.png -------------------------------------------------------------------------------- /img/pic-09-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-04.png -------------------------------------------------------------------------------- /img/pic-09-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-05.png -------------------------------------------------------------------------------- /img/pic-09-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-06.png -------------------------------------------------------------------------------- /img/pic-09-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-07.png -------------------------------------------------------------------------------- /img/pic-09-08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-08.png -------------------------------------------------------------------------------- /img/pic-09-09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-09.png -------------------------------------------------------------------------------- /img/pic-09-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-10.png -------------------------------------------------------------------------------- /img/pic-09-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-11.png -------------------------------------------------------------------------------- /img/pic-09-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-12.png -------------------------------------------------------------------------------- /img/pic-09-13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-13.png -------------------------------------------------------------------------------- /img/pic-09-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-14.png -------------------------------------------------------------------------------- /img/pic-09-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-15.png -------------------------------------------------------------------------------- /img/pic-09-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-16.png -------------------------------------------------------------------------------- /img/pic-09-17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-17.png -------------------------------------------------------------------------------- /img/pic-09-18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-09-18.png -------------------------------------------------------------------------------- /img/pic-10-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-10-01.png -------------------------------------------------------------------------------- /img/pic-10-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-10-02.png -------------------------------------------------------------------------------- /img/pic-10-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-10-03.png -------------------------------------------------------------------------------- /img/pic-10-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-10-04.png -------------------------------------------------------------------------------- /img/pic-10-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-10-05.png -------------------------------------------------------------------------------- /img/pic-11-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-11-01.png -------------------------------------------------------------------------------- /img/pic-11-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-11-02.png -------------------------------------------------------------------------------- /img/pic-11-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-11-03.png -------------------------------------------------------------------------------- /img/pic-11-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-11-04.png -------------------------------------------------------------------------------- /img/pic-11-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-11-05.png -------------------------------------------------------------------------------- /img/pic-11-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-11-06.png -------------------------------------------------------------------------------- /img/pic-11-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-11-07.png -------------------------------------------------------------------------------- /img/pic-11-08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-11-08.png -------------------------------------------------------------------------------- /img/pic-11-09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-11-09.png -------------------------------------------------------------------------------- /img/pic-11-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-11-10.png -------------------------------------------------------------------------------- /img/pic-11-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-11-11.png -------------------------------------------------------------------------------- /img/pic-11-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-11-12.png -------------------------------------------------------------------------------- /img/pic-11-13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-11-13.png -------------------------------------------------------------------------------- /img/pic-11-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-11-14.png -------------------------------------------------------------------------------- /img/pic-11-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-11-15.png -------------------------------------------------------------------------------- /img/pic-12-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-12-01.png -------------------------------------------------------------------------------- /img/pic-12-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-12-02.png -------------------------------------------------------------------------------- /img/pic-12-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-12-03.png -------------------------------------------------------------------------------- /img/pic-12-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-12-04.png -------------------------------------------------------------------------------- /img/pic-12-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-12-05.png -------------------------------------------------------------------------------- /img/pic-13-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-13-01.png -------------------------------------------------------------------------------- /img/pic-14-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-14-01.png -------------------------------------------------------------------------------- /img/pic-14-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-14-02.png -------------------------------------------------------------------------------- /img/pic-14-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-14-03.png -------------------------------------------------------------------------------- /img/pic-14-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-14-04.png -------------------------------------------------------------------------------- /img/pic-14-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-14-05.png -------------------------------------------------------------------------------- /img/pic-14-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-14-06.png -------------------------------------------------------------------------------- /img/pic-14-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-14-07.png -------------------------------------------------------------------------------- /img/pic-14-08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-14-08.png -------------------------------------------------------------------------------- /img/pic-14-09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-14-09.png -------------------------------------------------------------------------------- /img/pic-14-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-14-10.png -------------------------------------------------------------------------------- /img/pic-14-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-14-11.png -------------------------------------------------------------------------------- /img/pic-14-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-14-12.png -------------------------------------------------------------------------------- /img/pic-15-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-15-01.png -------------------------------------------------------------------------------- /img/pic-15-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-15-02.png -------------------------------------------------------------------------------- /img/pic-16-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-16-01.png -------------------------------------------------------------------------------- /img/pic-16-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-16-02.png -------------------------------------------------------------------------------- /img/pic-16-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-16-03.png -------------------------------------------------------------------------------- /img/pic-16-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-16-04.png -------------------------------------------------------------------------------- /img/pic-16-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-16-05.png -------------------------------------------------------------------------------- /img/pic-16-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-16-06.png -------------------------------------------------------------------------------- /img/pic-17-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-17-01.png -------------------------------------------------------------------------------- /img/pic-17-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-17-02.png -------------------------------------------------------------------------------- /img/pic-17-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-17-03.png -------------------------------------------------------------------------------- /img/pic-17-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-17-04.png -------------------------------------------------------------------------------- /img/pic-17-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-17-05.png -------------------------------------------------------------------------------- /img/pic-17-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-17-06.png -------------------------------------------------------------------------------- /img/pic-17-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-17-07.png -------------------------------------------------------------------------------- /img/pic-18-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-18-01.png -------------------------------------------------------------------------------- /img/pic-18-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-18-02.png -------------------------------------------------------------------------------- /img/pic-18-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-18-03.png -------------------------------------------------------------------------------- /img/pic-19-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-19-01.png -------------------------------------------------------------------------------- /img/pic-19-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-19-02.png -------------------------------------------------------------------------------- /img/pic-19-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-19-03.png -------------------------------------------------------------------------------- /img/pic-19-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-19-04.png -------------------------------------------------------------------------------- /img/pic-20-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-20-01.png -------------------------------------------------------------------------------- /img/pic-20-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-20-02.png -------------------------------------------------------------------------------- /img/pic-20-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-20-03.png -------------------------------------------------------------------------------- /img/pic-20-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-20-04.png -------------------------------------------------------------------------------- /img/pic-20-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-20-05.png -------------------------------------------------------------------------------- /img/pic-21-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-21-01.png -------------------------------------------------------------------------------- /img/pic-21-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-21-02.png -------------------------------------------------------------------------------- /img/pic-21-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-21-03.png -------------------------------------------------------------------------------- /img/pic-21-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-21-04.png -------------------------------------------------------------------------------- /img/pic-21-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-21-05.png -------------------------------------------------------------------------------- /img/pic-21-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-21-06.png -------------------------------------------------------------------------------- /img/pic-21-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-21-07.png -------------------------------------------------------------------------------- /img/pic-21-08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-21-08.png -------------------------------------------------------------------------------- /img/pic-21-09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-21-09.png -------------------------------------------------------------------------------- /img/pic-21-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-21-10.png -------------------------------------------------------------------------------- /img/pic-21-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-21-11.png -------------------------------------------------------------------------------- /img/pic-22-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-22-01.png -------------------------------------------------------------------------------- /img/pic-22-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-22-02.png -------------------------------------------------------------------------------- /img/pic-22-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-22-03.png -------------------------------------------------------------------------------- /img/pic-22-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-22-04.png -------------------------------------------------------------------------------- /img/pic-22-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-22-05.png -------------------------------------------------------------------------------- /img/pic-23-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-23-01.png -------------------------------------------------------------------------------- /img/pic-23-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-23-02.png -------------------------------------------------------------------------------- /img/pic-23-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-23-03.png -------------------------------------------------------------------------------- /img/pic-23-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-23-04.png -------------------------------------------------------------------------------- /img/pic-23-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-23-05.png -------------------------------------------------------------------------------- /img/pic-final-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webmakaka/Microservices-with-Node-JS-and-React/4f3a385676b6612e2afec9d5e7fbd9887162150b/img/pic-final-01.png --------------------------------------------------------------------------------