├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── deploy-monolith.sh ├── microservices ├── .gitignore ├── package-lock.json ├── package.json └── src │ ├── frontend │ ├── .dockerignore │ ├── .gcloudignore │ ├── .gitignore │ ├── Dockerfile │ ├── k8s │ │ ├── deployment.yml │ │ └── service.yml │ ├── package-lock.json │ ├── package.json │ └── server.js │ ├── orders │ ├── .dockerignore │ ├── .gitignore │ ├── Dockerfile │ ├── data │ │ └── orders.json │ ├── k8s │ │ ├── deployment.yml │ │ └── service.yml │ ├── package-lock.json │ ├── package.json │ └── server.js │ └── products │ ├── .dockerignore │ ├── .gitignore │ ├── Dockerfile │ ├── data │ └── products.json │ ├── k8s │ ├── deployment.yml │ └── service.yml │ ├── package-lock.json │ ├── package.json │ └── server.js ├── monolith ├── .dockerignore ├── .gcloudignore ├── .gitignore ├── Dockerfile ├── data │ ├── orders.json │ └── products.json ├── k8s │ ├── deployment.yml │ └── service.yml ├── package-lock.json ├── package.json └── src │ └── server.js ├── package-lock.json ├── react-app ├── .env ├── .env.monolith ├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public │ ├── index.html │ ├── manifest.json │ ├── robots.txt │ └── static │ │ └── img │ │ └── products │ │ ├── air-plant.jpg │ │ ├── barista-kit.jpg │ │ ├── camera-lens.jpg │ │ ├── camp-mug.jpg │ │ ├── city-bike.jpg │ │ ├── credits.txt │ │ ├── film-camera.jpg │ │ ├── record-player.jpg │ │ ├── terrarium.jpg │ │ └── typewriter.jpg ├── scripts │ └── post-build.js └── src │ ├── App.js │ ├── components │ └── ClippedDrawer │ │ └── index.js │ ├── index.js │ └── pages │ ├── Home │ ├── index.js │ └── index.js.new │ ├── NotFound │ └── index.js │ ├── OrderDetails │ └── index.js │ ├── Orders │ └── index.js │ └── Products │ └── index.js └── setup.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # misc 7 | .DS_Store 8 | 9 | /logs -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution; 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | 25 | ## Community Guidelines 26 | 27 | This project follows [Google's Open Source Community 28 | Guidelines](https://opensource.google.com/conduct/). -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Google LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | https://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Monolith to Microservices 2 | 3 | ## NOTE: This is not an officially supported Google product 4 | 5 | ## Introduction 6 | 7 | ### This project is used by the Google Cloud Platform team to demonstrate different services within Google Cloud. This project contains two versions of the same application, one architected as a monolith and the other as a set of microservices 8 | 9 | ## Setup 10 | 11 | ### **NOTE:** Make sure you have a newer version of NodeJS (16.13.0) or newer (in Cloud Shell you can run `nvm install --lts`) 12 | 13 | ```bash 14 | git clone https://github.com/googlecodelabs/monolith-to-microservices 15 | cd monolith-to-microservices 16 | ./setup.sh 17 | ``` 18 | 19 | ## Monolith 20 | 21 | ### To run the monolith project use the following commands from the top level directory 22 | 23 | ```bash 24 | cd monolith 25 | npm start 26 | ``` 27 | 28 | You should see output similar to the following 29 | 30 | ```text 31 | Monolith listening on port 8080! 32 | ``` 33 | 34 | #### That's it! You now have a perfectly functioning monolith running on your machine 35 | 36 | ### Docker - Monolith 37 | 38 | #### To create a Docker image for the monolith, execute the following commands 39 | 40 | ```bash 41 | cd monolith 42 | docker build -t monolith:1.0.0 . 43 | ``` 44 | 45 | To run the Docker image, execute the following commands 46 | 47 | ```bash 48 | docker run --rm -p 8080:8080 monolith:1.0.0 49 | ``` 50 | 51 | ## Microservices 52 | 53 | ### To run the microservices project use the following commands from the top level directory 54 | 55 | ```bash 56 | cd microservices 57 | npm start 58 | ``` 59 | 60 | You should see output similar to the following 61 | 62 | ```text 63 | [0] Frontend microservice listening on port 8080! 64 | [2] Orders microservice listening on port 8081! 65 | [1] Products microservice listening on port 8082! 66 | ``` 67 | 68 | ### That's it! You now have a perfectly functioning set of microservices running on your machine 69 | 70 | ### Docker - Microservices 71 | 72 | ### To create a Docker image for the microservices, you will have to create a Docker image for each service. Execute the following commands for each folder under the microservices folder 73 | 74 | ```bash 75 | cd microservices/src/frontend 76 | docker build -t frontend:1.0.0 . 77 | 78 | cd ../products 79 | docker build -t products:1.0.0 . 80 | 81 | cd ../orders 82 | docker build -t orders:1.0.0 . 83 | ``` 84 | 85 | To run the Docker image, execute the following commands 86 | 87 | ```bash 88 | docker run -d --rm -p 8080:8080 monolith:1.0.0 89 | docker run -d --rm -p 8081:8081 orders:1.0.0 90 | docker run -d --rm -p 8082:8082 products:1.0.0 91 | ``` 92 | 93 | #### To stop the containers, you will need to find the CONTAINER ID for each and stop them individually. See the steps below 94 | 95 | ```bash 96 | docker ps -a 97 | 98 | CONTAINER ID IMAGE COMMAND CREATED 99 | 4c01db0b339c frontend:1.0.0 bash 17 seconds ago 100 | d7886598dbe2 orders:1.0.0 bash 17 seconds ago 101 | d85756f57265 products:1.0.0 bash 17 seconds ago 102 | 103 | docker stop 4c01db0b339c 104 | docker stop d7886598dbe2 105 | docker stop d85756f57265 106 | ``` 107 | 108 | ## React App 109 | 110 | ### The react-app folder contains a React application created from `create-react-app`. You can modify this fronted, but afterwards, you will need to build and move the static files to the monolith and microservices project. You can do this by running the standard create-react-app build command below 111 | 112 | ```bash 113 | npm run build 114 | ``` 115 | 116 | #### This will run the build script to create the static files two times. The first will build with relative URLs and copy the static files to the monolith/public folder. The second run will build with the standard microservices URLs and copy the static files to the microservices/src/frontend/public folder 117 | -------------------------------------------------------------------------------- /deploy-monolith.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2019 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | printf "Enabling Cloud Build APIs...\n" 18 | gcloud services enable cloudbuild.googleapis.com 19 | printf "Completed.\n\n" 20 | 21 | printf "Building Monolith Container...\n" 22 | cd ~/monolith-to-microservices/monolith 23 | gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:1.0.0 . 24 | printf "Completed.\n\n" 25 | 26 | printf "Deploying Monolith To GKE Cluster...\n" 27 | kubectl create deployment monolith --image=gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:1.0.0 28 | kubectl expose deployment monolith --type=LoadBalancer --port 80 --target-port 8080 29 | printf "Completed.\n\n" 30 | 31 | printf "Please run the following command to find the IP address for the monolith service: kubectl get service monolith\n\n" 32 | 33 | printf "Deployment completed successfully!\n" 34 | -------------------------------------------------------------------------------- /microservices/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | 7 | # misc 8 | .DS_Store -------------------------------------------------------------------------------- /microservices/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "microservices", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "concurrently \"npm run frontend\" \"npm run products\" \"npm run orders\"", 9 | "frontend": "node ./src/frontend/server.js", 10 | "products": "node ./src/products/server.js", 11 | "orders": "node ./src/orders/server.js", 12 | "install-all": "npm-recursive-install" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "Apache-2.0", 17 | "devDependencies": { 18 | "concurrently": "^7.6.0" 19 | }, 20 | "dependencies": { 21 | "cors": "^2.8.5", 22 | "express": "^4.18.2" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /microservices/src/frontend/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /microservices/src/frontend/.gcloudignore: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | .git 16 | .gitignore 17 | node_modules/ 18 | -------------------------------------------------------------------------------- /microservices/src/frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /public 6 | 7 | # misc 8 | .DS_Store -------------------------------------------------------------------------------- /microservices/src/frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM node:16 16 | 17 | # Create app directory 18 | WORKDIR /usr/src/app 19 | 20 | # Install app dependencies 21 | # A wildcard is used to ensure both package.json AND package-lock.json are copied 22 | # where available (npm@5+) 23 | COPY package*.json ./ 24 | 25 | RUN npm install 26 | # If you are building your code for production 27 | # RUN npm ci --only=production 28 | 29 | # Bundle app source 30 | COPY . . 31 | 32 | EXPOSE 8080 33 | CMD [ "node", "server.js" ] -------------------------------------------------------------------------------- /microservices/src/frontend/k8s/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: frontend 5 | labels: 6 | app: frontend 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: frontend 12 | template: 13 | metadata: 14 | labels: 15 | app: frontend 16 | spec: 17 | containers: 18 | - name: frontend 19 | image: gcr.io//frontend:1.0.0 20 | imagePullPolicy: Always 21 | ports: 22 | - containerPort: 8080 -------------------------------------------------------------------------------- /microservices/src/frontend/k8s/service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: frontend 5 | spec: 6 | type: LoadBalancer 7 | ports: 8 | - port: 80 9 | targetPort: 8080 10 | protocol: TCP 11 | selector: 12 | app: frontend -------------------------------------------------------------------------------- /microservices/src/frontend/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.8", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 10 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 11 | "requires": { 12 | "mime-types": "~2.1.34", 13 | "negotiator": "0.6.3" 14 | } 15 | }, 16 | "array-flatten": { 17 | "version": "1.1.1", 18 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 19 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 20 | }, 21 | "body-parser": { 22 | "version": "1.20.3", 23 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", 24 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", 25 | "requires": { 26 | "bytes": "3.1.2", 27 | "content-type": "~1.0.5", 28 | "debug": "2.6.9", 29 | "depd": "2.0.0", 30 | "destroy": "1.2.0", 31 | "http-errors": "2.0.0", 32 | "iconv-lite": "0.4.24", 33 | "on-finished": "2.4.1", 34 | "qs": "6.13.0", 35 | "raw-body": "2.5.2", 36 | "type-is": "~1.6.18", 37 | "unpipe": "1.0.0" 38 | } 39 | }, 40 | "bytes": { 41 | "version": "3.1.2", 42 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 43 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 44 | }, 45 | "call-bind": { 46 | "version": "1.0.7", 47 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", 48 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", 49 | "requires": { 50 | "es-define-property": "^1.0.0", 51 | "es-errors": "^1.3.0", 52 | "function-bind": "^1.1.2", 53 | "get-intrinsic": "^1.2.4", 54 | "set-function-length": "^1.2.1" 55 | } 56 | }, 57 | "content-disposition": { 58 | "version": "0.5.4", 59 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 60 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 61 | "requires": { 62 | "safe-buffer": "5.2.1" 63 | } 64 | }, 65 | "content-type": { 66 | "version": "1.0.5", 67 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 68 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" 69 | }, 70 | "cookie": { 71 | "version": "0.7.1", 72 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", 73 | "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==" 74 | }, 75 | "cookie-signature": { 76 | "version": "1.0.6", 77 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 78 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 79 | }, 80 | "debug": { 81 | "version": "2.6.9", 82 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 83 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 84 | "requires": { 85 | "ms": "2.0.0" 86 | } 87 | }, 88 | "define-data-property": { 89 | "version": "1.1.4", 90 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", 91 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", 92 | "requires": { 93 | "es-define-property": "^1.0.0", 94 | "es-errors": "^1.3.0", 95 | "gopd": "^1.0.1" 96 | } 97 | }, 98 | "depd": { 99 | "version": "2.0.0", 100 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 101 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 102 | }, 103 | "destroy": { 104 | "version": "1.2.0", 105 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 106 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" 107 | }, 108 | "ee-first": { 109 | "version": "1.1.1", 110 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 111 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 112 | }, 113 | "encodeurl": { 114 | "version": "2.0.0", 115 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 116 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" 117 | }, 118 | "es-define-property": { 119 | "version": "1.0.0", 120 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", 121 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", 122 | "requires": { 123 | "get-intrinsic": "^1.2.4" 124 | } 125 | }, 126 | "es-errors": { 127 | "version": "1.3.0", 128 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 129 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" 130 | }, 131 | "escape-html": { 132 | "version": "1.0.3", 133 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 134 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 135 | }, 136 | "etag": { 137 | "version": "1.8.1", 138 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 139 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" 140 | }, 141 | "express": { 142 | "version": "4.21.1", 143 | "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", 144 | "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", 145 | "requires": { 146 | "accepts": "~1.3.8", 147 | "array-flatten": "1.1.1", 148 | "body-parser": "1.20.3", 149 | "content-disposition": "0.5.4", 150 | "content-type": "~1.0.4", 151 | "cookie": "0.7.1", 152 | "cookie-signature": "1.0.6", 153 | "debug": "2.6.9", 154 | "depd": "2.0.0", 155 | "encodeurl": "~2.0.0", 156 | "escape-html": "~1.0.3", 157 | "etag": "~1.8.1", 158 | "finalhandler": "1.3.1", 159 | "fresh": "0.5.2", 160 | "http-errors": "2.0.0", 161 | "merge-descriptors": "1.0.3", 162 | "methods": "~1.1.2", 163 | "on-finished": "2.4.1", 164 | "parseurl": "~1.3.3", 165 | "path-to-regexp": "0.1.10", 166 | "proxy-addr": "~2.0.7", 167 | "qs": "6.13.0", 168 | "range-parser": "~1.2.1", 169 | "safe-buffer": "5.2.1", 170 | "send": "0.19.0", 171 | "serve-static": "1.16.2", 172 | "setprototypeof": "1.2.0", 173 | "statuses": "2.0.1", 174 | "type-is": "~1.6.18", 175 | "utils-merge": "1.0.1", 176 | "vary": "~1.1.2" 177 | } 178 | }, 179 | "finalhandler": { 180 | "version": "1.3.1", 181 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", 182 | "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", 183 | "requires": { 184 | "debug": "2.6.9", 185 | "encodeurl": "~2.0.0", 186 | "escape-html": "~1.0.3", 187 | "on-finished": "2.4.1", 188 | "parseurl": "~1.3.3", 189 | "statuses": "2.0.1", 190 | "unpipe": "~1.0.0" 191 | } 192 | }, 193 | "forwarded": { 194 | "version": "0.2.0", 195 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 196 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 197 | }, 198 | "fresh": { 199 | "version": "0.5.2", 200 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 201 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" 202 | }, 203 | "function-bind": { 204 | "version": "1.1.2", 205 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 206 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" 207 | }, 208 | "get-intrinsic": { 209 | "version": "1.2.4", 210 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", 211 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", 212 | "requires": { 213 | "es-errors": "^1.3.0", 214 | "function-bind": "^1.1.2", 215 | "has-proto": "^1.0.1", 216 | "has-symbols": "^1.0.3", 217 | "hasown": "^2.0.0" 218 | } 219 | }, 220 | "gopd": { 221 | "version": "1.0.1", 222 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 223 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 224 | "requires": { 225 | "get-intrinsic": "^1.1.3" 226 | } 227 | }, 228 | "has-property-descriptors": { 229 | "version": "1.0.2", 230 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", 231 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", 232 | "requires": { 233 | "es-define-property": "^1.0.0" 234 | } 235 | }, 236 | "has-proto": { 237 | "version": "1.0.3", 238 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", 239 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" 240 | }, 241 | "has-symbols": { 242 | "version": "1.0.3", 243 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 244 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" 245 | }, 246 | "hasown": { 247 | "version": "2.0.2", 248 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 249 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 250 | "requires": { 251 | "function-bind": "^1.1.2" 252 | } 253 | }, 254 | "http-errors": { 255 | "version": "2.0.0", 256 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 257 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 258 | "requires": { 259 | "depd": "2.0.0", 260 | "inherits": "2.0.4", 261 | "setprototypeof": "1.2.0", 262 | "statuses": "2.0.1", 263 | "toidentifier": "1.0.1" 264 | } 265 | }, 266 | "iconv-lite": { 267 | "version": "0.4.24", 268 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 269 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 270 | "requires": { 271 | "safer-buffer": ">= 2.1.2 < 3" 272 | } 273 | }, 274 | "inherits": { 275 | "version": "2.0.4", 276 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 277 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 278 | }, 279 | "ipaddr.js": { 280 | "version": "1.9.1", 281 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 282 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 283 | }, 284 | "media-typer": { 285 | "version": "0.3.0", 286 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 287 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" 288 | }, 289 | "merge-descriptors": { 290 | "version": "1.0.3", 291 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", 292 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==" 293 | }, 294 | "methods": { 295 | "version": "1.1.2", 296 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 297 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" 298 | }, 299 | "mime": { 300 | "version": "1.6.0", 301 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 302 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 303 | }, 304 | "mime-db": { 305 | "version": "1.52.0", 306 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 307 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 308 | }, 309 | "mime-types": { 310 | "version": "2.1.35", 311 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 312 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 313 | "requires": { 314 | "mime-db": "1.52.0" 315 | } 316 | }, 317 | "ms": { 318 | "version": "2.0.0", 319 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 320 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 321 | }, 322 | "negotiator": { 323 | "version": "0.6.3", 324 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 325 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 326 | }, 327 | "object-inspect": { 328 | "version": "1.13.2", 329 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", 330 | "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==" 331 | }, 332 | "on-finished": { 333 | "version": "2.4.1", 334 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 335 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 336 | "requires": { 337 | "ee-first": "1.1.1" 338 | } 339 | }, 340 | "parseurl": { 341 | "version": "1.3.3", 342 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 343 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 344 | }, 345 | "path-to-regexp": { 346 | "version": "0.1.10", 347 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", 348 | "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" 349 | }, 350 | "proxy-addr": { 351 | "version": "2.0.7", 352 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 353 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 354 | "requires": { 355 | "forwarded": "0.2.0", 356 | "ipaddr.js": "1.9.1" 357 | } 358 | }, 359 | "qs": { 360 | "version": "6.13.0", 361 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", 362 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", 363 | "requires": { 364 | "side-channel": "^1.0.6" 365 | } 366 | }, 367 | "range-parser": { 368 | "version": "1.2.1", 369 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 370 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 371 | }, 372 | "raw-body": { 373 | "version": "2.5.2", 374 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 375 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 376 | "requires": { 377 | "bytes": "3.1.2", 378 | "http-errors": "2.0.0", 379 | "iconv-lite": "0.4.24", 380 | "unpipe": "1.0.0" 381 | } 382 | }, 383 | "safe-buffer": { 384 | "version": "5.2.1", 385 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 386 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 387 | }, 388 | "safer-buffer": { 389 | "version": "2.1.2", 390 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 391 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 392 | }, 393 | "send": { 394 | "version": "0.19.0", 395 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", 396 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", 397 | "requires": { 398 | "debug": "2.6.9", 399 | "depd": "2.0.0", 400 | "destroy": "1.2.0", 401 | "encodeurl": "~1.0.2", 402 | "escape-html": "~1.0.3", 403 | "etag": "~1.8.1", 404 | "fresh": "0.5.2", 405 | "http-errors": "2.0.0", 406 | "mime": "1.6.0", 407 | "ms": "2.1.3", 408 | "on-finished": "2.4.1", 409 | "range-parser": "~1.2.1", 410 | "statuses": "2.0.1" 411 | }, 412 | "dependencies": { 413 | "encodeurl": { 414 | "version": "1.0.2", 415 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 416 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" 417 | }, 418 | "ms": { 419 | "version": "2.1.3", 420 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 421 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 422 | } 423 | } 424 | }, 425 | "serve-static": { 426 | "version": "1.16.2", 427 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", 428 | "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", 429 | "requires": { 430 | "encodeurl": "~2.0.0", 431 | "escape-html": "~1.0.3", 432 | "parseurl": "~1.3.3", 433 | "send": "0.19.0" 434 | } 435 | }, 436 | "set-function-length": { 437 | "version": "1.2.2", 438 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", 439 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", 440 | "requires": { 441 | "define-data-property": "^1.1.4", 442 | "es-errors": "^1.3.0", 443 | "function-bind": "^1.1.2", 444 | "get-intrinsic": "^1.2.4", 445 | "gopd": "^1.0.1", 446 | "has-property-descriptors": "^1.0.2" 447 | } 448 | }, 449 | "setprototypeof": { 450 | "version": "1.2.0", 451 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 452 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 453 | }, 454 | "side-channel": { 455 | "version": "1.0.6", 456 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", 457 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", 458 | "requires": { 459 | "call-bind": "^1.0.7", 460 | "es-errors": "^1.3.0", 461 | "get-intrinsic": "^1.2.4", 462 | "object-inspect": "^1.13.1" 463 | } 464 | }, 465 | "statuses": { 466 | "version": "2.0.1", 467 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 468 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" 469 | }, 470 | "toidentifier": { 471 | "version": "1.0.1", 472 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 473 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 474 | }, 475 | "type-is": { 476 | "version": "1.6.18", 477 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 478 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 479 | "requires": { 480 | "media-typer": "0.3.0", 481 | "mime-types": "~2.1.24" 482 | } 483 | }, 484 | "unpipe": { 485 | "version": "1.0.0", 486 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 487 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" 488 | }, 489 | "utils-merge": { 490 | "version": "1.0.1", 491 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 492 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" 493 | }, 494 | "vary": { 495 | "version": "1.1.2", 496 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 497 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" 498 | } 499 | } 500 | } 501 | -------------------------------------------------------------------------------- /microservices/src/frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node server.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "Apache-2.0", 13 | "dependencies": { 14 | "express": "^4.17.2" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /microservices/src/frontend/server.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | const express = require("express"); 17 | const path = require("path"); 18 | const app = express(); 19 | const port = process.env.PORT || 8080; 20 | 21 | //Serve website 22 | app.use(express.static(path.join(__dirname, "public"))); 23 | 24 | //Client side routing fix on page refresh or direct browsing to non-root directory 25 | app.get("/*", (req, res) => { 26 | res.sendFile(path.join(__dirname, "public", "index.html"), err => { 27 | if (err) { 28 | res.status(500).send(err); 29 | } 30 | }); 31 | }); 32 | 33 | //Start the server 34 | app.listen(port, () => console.log(`Frontend microservice listening on port ${port}!`)); 35 | -------------------------------------------------------------------------------- /microservices/src/orders/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /microservices/src/orders/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # misc 7 | .DS_Store -------------------------------------------------------------------------------- /microservices/src/orders/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM node:16 16 | 17 | # Create app directory 18 | WORKDIR /usr/src/app 19 | 20 | # Install app dependencies 21 | # A wildcard is used to ensure both package.json AND package-lock.json are copied 22 | # where available (npm@5+) 23 | COPY package*.json ./ 24 | 25 | RUN npm install 26 | # If you are building your code for production 27 | # RUN npm ci --only=production 28 | 29 | # Bundle app source 30 | COPY . . 31 | 32 | EXPOSE 8081 33 | CMD [ "node", "server.js" ] -------------------------------------------------------------------------------- /microservices/src/orders/data/orders.json: -------------------------------------------------------------------------------- 1 | { 2 | "orders": [ 3 | { 4 | "id": "ORD-000001-MICROSERVICE", 5 | "date": "7/01/2019", 6 | "cost": 67.99, 7 | "items": ["OLJCESPC7Z"] 8 | }, 9 | { 10 | "id": "ORD-000002-MICROSERVICE", 11 | "date": "7/24/2019", 12 | "cost": 124, 13 | "items": ["1YMWWN1N4O"] 14 | }, 15 | { 16 | "id": "ORD-000003-MICROSERVICE", 17 | "date": "8/03/2019", 18 | "cost": 12.49, 19 | "items": ["66VCHSJNUP"] 20 | }, 21 | { 22 | "id": "ORD-000004-MICROSERVICE", 23 | "date": "8/14/2019", 24 | "cost": 89.83, 25 | "items": ["0PUK6V6EV0", "LS4PSXUNUM"] 26 | }, 27 | { 28 | "id": "ORD-000005-MICROSERVICE", 29 | "date": "8/29/2019", 30 | "cost": 12.30, 31 | "items": ["6E92ZMYYFZ"] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /microservices/src/orders/k8s/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: orders 5 | labels: 6 | app: orders 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: orders 12 | template: 13 | metadata: 14 | labels: 15 | app: orders 16 | spec: 17 | containers: 18 | - name: orders 19 | image: gcr.io//orders:1.0.0 20 | imagePullPolicy: Always 21 | ports: 22 | - containerPort: 8080 -------------------------------------------------------------------------------- /microservices/src/orders/k8s/service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: orders 5 | spec: 6 | type: LoadBalancer 7 | ports: 8 | - port: 80 9 | targetPort: 8080 10 | protocol: TCP 11 | selector: 12 | app: orders -------------------------------------------------------------------------------- /microservices/src/orders/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "orders", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.8", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 10 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 11 | "requires": { 12 | "mime-types": "~2.1.34", 13 | "negotiator": "0.6.3" 14 | } 15 | }, 16 | "array-flatten": { 17 | "version": "1.1.1", 18 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 19 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 20 | }, 21 | "body-parser": { 22 | "version": "1.20.3", 23 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", 24 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", 25 | "requires": { 26 | "bytes": "3.1.2", 27 | "content-type": "~1.0.5", 28 | "debug": "2.6.9", 29 | "depd": "2.0.0", 30 | "destroy": "1.2.0", 31 | "http-errors": "2.0.0", 32 | "iconv-lite": "0.4.24", 33 | "on-finished": "2.4.1", 34 | "qs": "6.13.0", 35 | "raw-body": "2.5.2", 36 | "type-is": "~1.6.18", 37 | "unpipe": "1.0.0" 38 | } 39 | }, 40 | "bytes": { 41 | "version": "3.1.2", 42 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 43 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 44 | }, 45 | "call-bind": { 46 | "version": "1.0.7", 47 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", 48 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", 49 | "requires": { 50 | "es-define-property": "^1.0.0", 51 | "es-errors": "^1.3.0", 52 | "function-bind": "^1.1.2", 53 | "get-intrinsic": "^1.2.4", 54 | "set-function-length": "^1.2.1" 55 | } 56 | }, 57 | "content-disposition": { 58 | "version": "0.5.4", 59 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 60 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 61 | "requires": { 62 | "safe-buffer": "5.2.1" 63 | } 64 | }, 65 | "content-type": { 66 | "version": "1.0.5", 67 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 68 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" 69 | }, 70 | "cookie": { 71 | "version": "0.6.0", 72 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", 73 | "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==" 74 | }, 75 | "cookie-signature": { 76 | "version": "1.0.6", 77 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 78 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 79 | }, 80 | "cors": { 81 | "version": "2.8.5", 82 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 83 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 84 | "requires": { 85 | "object-assign": "^4", 86 | "vary": "^1" 87 | } 88 | }, 89 | "debug": { 90 | "version": "2.6.9", 91 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 92 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 93 | "requires": { 94 | "ms": "2.0.0" 95 | } 96 | }, 97 | "define-data-property": { 98 | "version": "1.1.4", 99 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", 100 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", 101 | "requires": { 102 | "es-define-property": "^1.0.0", 103 | "es-errors": "^1.3.0", 104 | "gopd": "^1.0.1" 105 | } 106 | }, 107 | "depd": { 108 | "version": "2.0.0", 109 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 110 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 111 | }, 112 | "destroy": { 113 | "version": "1.2.0", 114 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 115 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" 116 | }, 117 | "ee-first": { 118 | "version": "1.1.1", 119 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 120 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 121 | }, 122 | "encodeurl": { 123 | "version": "2.0.0", 124 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 125 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" 126 | }, 127 | "es-define-property": { 128 | "version": "1.0.0", 129 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", 130 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", 131 | "requires": { 132 | "get-intrinsic": "^1.2.4" 133 | } 134 | }, 135 | "es-errors": { 136 | "version": "1.3.0", 137 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 138 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" 139 | }, 140 | "escape-html": { 141 | "version": "1.0.3", 142 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 143 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 144 | }, 145 | "etag": { 146 | "version": "1.8.1", 147 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 148 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" 149 | }, 150 | "express": { 151 | "version": "4.21.0", 152 | "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", 153 | "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", 154 | "requires": { 155 | "accepts": "~1.3.8", 156 | "array-flatten": "1.1.1", 157 | "body-parser": "1.20.3", 158 | "content-disposition": "0.5.4", 159 | "content-type": "~1.0.4", 160 | "cookie": "0.6.0", 161 | "cookie-signature": "1.0.6", 162 | "debug": "2.6.9", 163 | "depd": "2.0.0", 164 | "encodeurl": "~2.0.0", 165 | "escape-html": "~1.0.3", 166 | "etag": "~1.8.1", 167 | "finalhandler": "1.3.1", 168 | "fresh": "0.5.2", 169 | "http-errors": "2.0.0", 170 | "merge-descriptors": "1.0.3", 171 | "methods": "~1.1.2", 172 | "on-finished": "2.4.1", 173 | "parseurl": "~1.3.3", 174 | "path-to-regexp": "0.1.10", 175 | "proxy-addr": "~2.0.7", 176 | "qs": "6.13.0", 177 | "range-parser": "~1.2.1", 178 | "safe-buffer": "5.2.1", 179 | "send": "0.19.0", 180 | "serve-static": "1.16.2", 181 | "setprototypeof": "1.2.0", 182 | "statuses": "2.0.1", 183 | "type-is": "~1.6.18", 184 | "utils-merge": "1.0.1", 185 | "vary": "~1.1.2" 186 | } 187 | }, 188 | "finalhandler": { 189 | "version": "1.3.1", 190 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", 191 | "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", 192 | "requires": { 193 | "debug": "2.6.9", 194 | "encodeurl": "~2.0.0", 195 | "escape-html": "~1.0.3", 196 | "on-finished": "2.4.1", 197 | "parseurl": "~1.3.3", 198 | "statuses": "2.0.1", 199 | "unpipe": "~1.0.0" 200 | } 201 | }, 202 | "forwarded": { 203 | "version": "0.2.0", 204 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 205 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 206 | }, 207 | "fresh": { 208 | "version": "0.5.2", 209 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 210 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" 211 | }, 212 | "function-bind": { 213 | "version": "1.1.2", 214 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 215 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" 216 | }, 217 | "get-intrinsic": { 218 | "version": "1.2.4", 219 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", 220 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", 221 | "requires": { 222 | "es-errors": "^1.3.0", 223 | "function-bind": "^1.1.2", 224 | "has-proto": "^1.0.1", 225 | "has-symbols": "^1.0.3", 226 | "hasown": "^2.0.0" 227 | } 228 | }, 229 | "gopd": { 230 | "version": "1.0.1", 231 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 232 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 233 | "requires": { 234 | "get-intrinsic": "^1.1.3" 235 | } 236 | }, 237 | "has-property-descriptors": { 238 | "version": "1.0.2", 239 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", 240 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", 241 | "requires": { 242 | "es-define-property": "^1.0.0" 243 | } 244 | }, 245 | "has-proto": { 246 | "version": "1.0.3", 247 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", 248 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" 249 | }, 250 | "has-symbols": { 251 | "version": "1.0.3", 252 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 253 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" 254 | }, 255 | "hasown": { 256 | "version": "2.0.2", 257 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 258 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 259 | "requires": { 260 | "function-bind": "^1.1.2" 261 | } 262 | }, 263 | "http-errors": { 264 | "version": "2.0.0", 265 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 266 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 267 | "requires": { 268 | "depd": "2.0.0", 269 | "inherits": "2.0.4", 270 | "setprototypeof": "1.2.0", 271 | "statuses": "2.0.1", 272 | "toidentifier": "1.0.1" 273 | } 274 | }, 275 | "iconv-lite": { 276 | "version": "0.4.24", 277 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 278 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 279 | "requires": { 280 | "safer-buffer": ">= 2.1.2 < 3" 281 | } 282 | }, 283 | "inherits": { 284 | "version": "2.0.4", 285 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 286 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 287 | }, 288 | "ipaddr.js": { 289 | "version": "1.9.1", 290 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 291 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 292 | }, 293 | "media-typer": { 294 | "version": "0.3.0", 295 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 296 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" 297 | }, 298 | "merge-descriptors": { 299 | "version": "1.0.3", 300 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", 301 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==" 302 | }, 303 | "methods": { 304 | "version": "1.1.2", 305 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 306 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" 307 | }, 308 | "mime": { 309 | "version": "1.6.0", 310 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 311 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 312 | }, 313 | "mime-db": { 314 | "version": "1.52.0", 315 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 316 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 317 | }, 318 | "mime-types": { 319 | "version": "2.1.35", 320 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 321 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 322 | "requires": { 323 | "mime-db": "1.52.0" 324 | } 325 | }, 326 | "ms": { 327 | "version": "2.0.0", 328 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 329 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 330 | }, 331 | "negotiator": { 332 | "version": "0.6.3", 333 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 334 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 335 | }, 336 | "object-assign": { 337 | "version": "4.1.1", 338 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 339 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 340 | }, 341 | "object-inspect": { 342 | "version": "1.13.2", 343 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", 344 | "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==" 345 | }, 346 | "on-finished": { 347 | "version": "2.4.1", 348 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 349 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 350 | "requires": { 351 | "ee-first": "1.1.1" 352 | } 353 | }, 354 | "parseurl": { 355 | "version": "1.3.3", 356 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 357 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 358 | }, 359 | "path-to-regexp": { 360 | "version": "0.1.10", 361 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", 362 | "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" 363 | }, 364 | "proxy-addr": { 365 | "version": "2.0.7", 366 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 367 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 368 | "requires": { 369 | "forwarded": "0.2.0", 370 | "ipaddr.js": "1.9.1" 371 | } 372 | }, 373 | "qs": { 374 | "version": "6.13.0", 375 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", 376 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", 377 | "requires": { 378 | "side-channel": "^1.0.6" 379 | } 380 | }, 381 | "range-parser": { 382 | "version": "1.2.1", 383 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 384 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 385 | }, 386 | "raw-body": { 387 | "version": "2.5.2", 388 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 389 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 390 | "requires": { 391 | "bytes": "3.1.2", 392 | "http-errors": "2.0.0", 393 | "iconv-lite": "0.4.24", 394 | "unpipe": "1.0.0" 395 | } 396 | }, 397 | "safe-buffer": { 398 | "version": "5.2.1", 399 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 400 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 401 | }, 402 | "safer-buffer": { 403 | "version": "2.1.2", 404 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 405 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 406 | }, 407 | "send": { 408 | "version": "0.19.0", 409 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", 410 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", 411 | "requires": { 412 | "debug": "2.6.9", 413 | "depd": "2.0.0", 414 | "destroy": "1.2.0", 415 | "encodeurl": "~1.0.2", 416 | "escape-html": "~1.0.3", 417 | "etag": "~1.8.1", 418 | "fresh": "0.5.2", 419 | "http-errors": "2.0.0", 420 | "mime": "1.6.0", 421 | "ms": "2.1.3", 422 | "on-finished": "2.4.1", 423 | "range-parser": "~1.2.1", 424 | "statuses": "2.0.1" 425 | }, 426 | "dependencies": { 427 | "encodeurl": { 428 | "version": "1.0.2", 429 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 430 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" 431 | }, 432 | "ms": { 433 | "version": "2.1.3", 434 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 435 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 436 | } 437 | } 438 | }, 439 | "serve-static": { 440 | "version": "1.16.2", 441 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", 442 | "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", 443 | "requires": { 444 | "encodeurl": "~2.0.0", 445 | "escape-html": "~1.0.3", 446 | "parseurl": "~1.3.3", 447 | "send": "0.19.0" 448 | } 449 | }, 450 | "set-function-length": { 451 | "version": "1.2.2", 452 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", 453 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", 454 | "requires": { 455 | "define-data-property": "^1.1.4", 456 | "es-errors": "^1.3.0", 457 | "function-bind": "^1.1.2", 458 | "get-intrinsic": "^1.2.4", 459 | "gopd": "^1.0.1", 460 | "has-property-descriptors": "^1.0.2" 461 | } 462 | }, 463 | "setprototypeof": { 464 | "version": "1.2.0", 465 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 466 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 467 | }, 468 | "side-channel": { 469 | "version": "1.0.6", 470 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", 471 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", 472 | "requires": { 473 | "call-bind": "^1.0.7", 474 | "es-errors": "^1.3.0", 475 | "get-intrinsic": "^1.2.4", 476 | "object-inspect": "^1.13.1" 477 | } 478 | }, 479 | "statuses": { 480 | "version": "2.0.1", 481 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 482 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" 483 | }, 484 | "toidentifier": { 485 | "version": "1.0.1", 486 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 487 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 488 | }, 489 | "type-is": { 490 | "version": "1.6.18", 491 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 492 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 493 | "requires": { 494 | "media-typer": "0.3.0", 495 | "mime-types": "~2.1.24" 496 | } 497 | }, 498 | "unpipe": { 499 | "version": "1.0.0", 500 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 501 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" 502 | }, 503 | "utils-merge": { 504 | "version": "1.0.1", 505 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 506 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" 507 | }, 508 | "vary": { 509 | "version": "1.1.2", 510 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 511 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 512 | } 513 | } 514 | } 515 | -------------------------------------------------------------------------------- /microservices/src/orders/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "orders", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node server.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "Apache-2.0", 13 | "dependencies": { 14 | "cors": "^2.8.5", 15 | "express": "^4.17.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /microservices/src/orders/server.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | const express = require("express"); 17 | const cors = require("cors"); 18 | const app = express(); 19 | const port = process.env.PORT || 8081; 20 | 21 | //Load orders for pseudo database 22 | const orders = require("./data/orders.json").orders; 23 | 24 | //Enable cors 25 | app.use(cors()); 26 | 27 | //Get all orders 28 | app.get("/api/orders", (req, res) => res.json(orders)); 29 | 30 | //Get orders by ID 31 | app.get("/api/orders/:id", (req, res) => 32 | res.json(orders.find(order => order.id === req.params.id)) 33 | ); 34 | 35 | app.listen(port, () => 36 | console.log(`Orders microservice listening on port ${port}!`) 37 | ); 38 | -------------------------------------------------------------------------------- /microservices/src/products/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /microservices/src/products/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # misc 7 | .DS_Store -------------------------------------------------------------------------------- /microservices/src/products/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM node:16 16 | 17 | # Create app directory 18 | WORKDIR /usr/src/app 19 | 20 | # Install app dependencies 21 | # A wildcard is used to ensure both package.json AND package-lock.json are copied 22 | # where available (npm@5+) 23 | COPY package*.json ./ 24 | 25 | RUN npm install 26 | # If you are building your code for production 27 | # RUN npm ci --only=production 28 | 29 | # Bundle app source 30 | COPY . . 31 | 32 | EXPOSE 8082 33 | CMD [ "node", "server.js" ] -------------------------------------------------------------------------------- /microservices/src/products/data/products.json: -------------------------------------------------------------------------------- 1 | { 2 | "products": [ 3 | { 4 | "id": "OLJCESPC7Z", 5 | "name": "MS - Vintage Typewriter", 6 | "description": "This typewriter looks good in your living room.", 7 | "picture": "static/img/products/typewriter.jpg", 8 | "cost": 67.99, 9 | "categories": ["vintage"] 10 | }, 11 | { 12 | "id": "66VCHSJNUP", 13 | "name": "MS - Vintage Camera Lens", 14 | "description": "You won't have a camera to use it and it probably doesn't work anyway.", 15 | "picture": "static/img/products/camera-lens.jpg", 16 | "cost": 12.49, 17 | "categories": ["photography", "vintage"] 18 | }, 19 | { 20 | "id": "1YMWWN1N4O", 21 | "name": "MS - Home Barista Kit", 22 | "description": "Always wanted to brew coffee with Chemex and Aeropress at home?", 23 | "picture": "static/img/products/barista-kit.jpg", 24 | "cost": 124, 25 | "categories": ["cookware"] 26 | }, 27 | { 28 | "id": "L9ECAV7KIM", 29 | "name": "MS - Terrarium", 30 | "description": "This terrarium will looks great in your white painted living room.", 31 | "picture": "static/img/products/terrarium.jpg", 32 | "cost": 36.45, 33 | "categories": ["gardening"] 34 | }, 35 | { 36 | "id": "2ZYFJ3GM2N", 37 | "name": "MS - Film Camera", 38 | "description": "This camera looks like it's a film camera, but it's actually digital.", 39 | "picture": "static/img/products/film-camera.jpg", 40 | "cost": 2245, 41 | "categories": ["photography", "vintage"] 42 | }, 43 | { 44 | "id": "0PUK6V6EV0", 45 | "name": "MS - Vintage Record Player", 46 | "description": "It still works.", 47 | "picture": "static/img/products/record-player.jpg", 48 | "cost": 65.50, 49 | "categories": ["music", "vintage"] 50 | }, 51 | { 52 | "id": "LS4PSXUNUM", 53 | "description": "You probably don't go camping that often but this is better than plastic cups.", 54 | "name": "MS - Metal Camping Mug", 55 | "picture": "static/img/products/camp-mug.jpg", 56 | "cost": 24.33, 57 | "categories": ["cookware"] 58 | }, 59 | { 60 | "id": "9SIQT8TOJO", 61 | "name": "MS - City Bike", 62 | "description": "This single gear bike probably cannot climb the hills of San Francisco.", 63 | "picture": "static/img/products/city-bike.jpg", 64 | "cost": 789.50, 65 | "categories": ["cycling"] 66 | }, 67 | { 68 | "id": "6E92ZMYYFZ", 69 | "name": "MS - Air Plant", 70 | "description": "Have you ever wondered whether air plants need water? Buy one and figure out.", 71 | "picture": "static/img/products/air-plant.jpg", 72 | "cost": 12.30, 73 | "categories": ["gardening"] 74 | } 75 | ] 76 | } -------------------------------------------------------------------------------- /microservices/src/products/k8s/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: products 5 | labels: 6 | app: products 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: products 12 | template: 13 | metadata: 14 | labels: 15 | app: products 16 | spec: 17 | containers: 18 | - name: products 19 | image: gcr.io//products:1.0.0 20 | imagePullPolicy: Always 21 | ports: 22 | - containerPort: 8080 -------------------------------------------------------------------------------- /microservices/src/products/k8s/service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: products 5 | spec: 6 | type: LoadBalancer 7 | ports: 8 | - port: 80 9 | targetPort: 8080 10 | protocol: TCP 11 | selector: 12 | app: products -------------------------------------------------------------------------------- /microservices/src/products/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "products", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.8", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 10 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 11 | "requires": { 12 | "mime-types": "~2.1.34", 13 | "negotiator": "0.6.3" 14 | } 15 | }, 16 | "array-flatten": { 17 | "version": "1.1.1", 18 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 19 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 20 | }, 21 | "body-parser": { 22 | "version": "1.20.3", 23 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", 24 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", 25 | "requires": { 26 | "bytes": "3.1.2", 27 | "content-type": "~1.0.5", 28 | "debug": "2.6.9", 29 | "depd": "2.0.0", 30 | "destroy": "1.2.0", 31 | "http-errors": "2.0.0", 32 | "iconv-lite": "0.4.24", 33 | "on-finished": "2.4.1", 34 | "qs": "6.13.0", 35 | "raw-body": "2.5.2", 36 | "type-is": "~1.6.18", 37 | "unpipe": "1.0.0" 38 | } 39 | }, 40 | "bytes": { 41 | "version": "3.1.2", 42 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 43 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 44 | }, 45 | "call-bind": { 46 | "version": "1.0.7", 47 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", 48 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", 49 | "requires": { 50 | "es-define-property": "^1.0.0", 51 | "es-errors": "^1.3.0", 52 | "function-bind": "^1.1.2", 53 | "get-intrinsic": "^1.2.4", 54 | "set-function-length": "^1.2.1" 55 | } 56 | }, 57 | "content-disposition": { 58 | "version": "0.5.4", 59 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 60 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 61 | "requires": { 62 | "safe-buffer": "5.2.1" 63 | } 64 | }, 65 | "content-type": { 66 | "version": "1.0.5", 67 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 68 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" 69 | }, 70 | "cookie": { 71 | "version": "0.7.1", 72 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", 73 | "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==" 74 | }, 75 | "cookie-signature": { 76 | "version": "1.0.6", 77 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 78 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 79 | }, 80 | "cors": { 81 | "version": "2.8.5", 82 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 83 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 84 | "requires": { 85 | "object-assign": "^4", 86 | "vary": "^1" 87 | } 88 | }, 89 | "debug": { 90 | "version": "2.6.9", 91 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 92 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 93 | "requires": { 94 | "ms": "2.0.0" 95 | } 96 | }, 97 | "define-data-property": { 98 | "version": "1.1.4", 99 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", 100 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", 101 | "requires": { 102 | "es-define-property": "^1.0.0", 103 | "es-errors": "^1.3.0", 104 | "gopd": "^1.0.1" 105 | } 106 | }, 107 | "depd": { 108 | "version": "2.0.0", 109 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 110 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 111 | }, 112 | "destroy": { 113 | "version": "1.2.0", 114 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 115 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" 116 | }, 117 | "ee-first": { 118 | "version": "1.1.1", 119 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 120 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 121 | }, 122 | "encodeurl": { 123 | "version": "2.0.0", 124 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 125 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" 126 | }, 127 | "es-define-property": { 128 | "version": "1.0.0", 129 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", 130 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", 131 | "requires": { 132 | "get-intrinsic": "^1.2.4" 133 | } 134 | }, 135 | "es-errors": { 136 | "version": "1.3.0", 137 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 138 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" 139 | }, 140 | "escape-html": { 141 | "version": "1.0.3", 142 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 143 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 144 | }, 145 | "etag": { 146 | "version": "1.8.1", 147 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 148 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" 149 | }, 150 | "express": { 151 | "version": "4.21.1", 152 | "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", 153 | "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", 154 | "requires": { 155 | "accepts": "~1.3.8", 156 | "array-flatten": "1.1.1", 157 | "body-parser": "1.20.3", 158 | "content-disposition": "0.5.4", 159 | "content-type": "~1.0.4", 160 | "cookie": "0.7.1", 161 | "cookie-signature": "1.0.6", 162 | "debug": "2.6.9", 163 | "depd": "2.0.0", 164 | "encodeurl": "~2.0.0", 165 | "escape-html": "~1.0.3", 166 | "etag": "~1.8.1", 167 | "finalhandler": "1.3.1", 168 | "fresh": "0.5.2", 169 | "http-errors": "2.0.0", 170 | "merge-descriptors": "1.0.3", 171 | "methods": "~1.1.2", 172 | "on-finished": "2.4.1", 173 | "parseurl": "~1.3.3", 174 | "path-to-regexp": "0.1.10", 175 | "proxy-addr": "~2.0.7", 176 | "qs": "6.13.0", 177 | "range-parser": "~1.2.1", 178 | "safe-buffer": "5.2.1", 179 | "send": "0.19.0", 180 | "serve-static": "1.16.2", 181 | "setprototypeof": "1.2.0", 182 | "statuses": "2.0.1", 183 | "type-is": "~1.6.18", 184 | "utils-merge": "1.0.1", 185 | "vary": "~1.1.2" 186 | } 187 | }, 188 | "finalhandler": { 189 | "version": "1.3.1", 190 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", 191 | "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", 192 | "requires": { 193 | "debug": "2.6.9", 194 | "encodeurl": "~2.0.0", 195 | "escape-html": "~1.0.3", 196 | "on-finished": "2.4.1", 197 | "parseurl": "~1.3.3", 198 | "statuses": "2.0.1", 199 | "unpipe": "~1.0.0" 200 | } 201 | }, 202 | "forwarded": { 203 | "version": "0.2.0", 204 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 205 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 206 | }, 207 | "fresh": { 208 | "version": "0.5.2", 209 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 210 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" 211 | }, 212 | "function-bind": { 213 | "version": "1.1.2", 214 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 215 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" 216 | }, 217 | "get-intrinsic": { 218 | "version": "1.2.4", 219 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", 220 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", 221 | "requires": { 222 | "es-errors": "^1.3.0", 223 | "function-bind": "^1.1.2", 224 | "has-proto": "^1.0.1", 225 | "has-symbols": "^1.0.3", 226 | "hasown": "^2.0.0" 227 | } 228 | }, 229 | "gopd": { 230 | "version": "1.0.1", 231 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 232 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 233 | "requires": { 234 | "get-intrinsic": "^1.1.3" 235 | } 236 | }, 237 | "has-property-descriptors": { 238 | "version": "1.0.2", 239 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", 240 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", 241 | "requires": { 242 | "es-define-property": "^1.0.0" 243 | } 244 | }, 245 | "has-proto": { 246 | "version": "1.0.3", 247 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", 248 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" 249 | }, 250 | "has-symbols": { 251 | "version": "1.0.3", 252 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 253 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" 254 | }, 255 | "hasown": { 256 | "version": "2.0.2", 257 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 258 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 259 | "requires": { 260 | "function-bind": "^1.1.2" 261 | } 262 | }, 263 | "http-errors": { 264 | "version": "2.0.0", 265 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 266 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 267 | "requires": { 268 | "depd": "2.0.0", 269 | "inherits": "2.0.4", 270 | "setprototypeof": "1.2.0", 271 | "statuses": "2.0.1", 272 | "toidentifier": "1.0.1" 273 | } 274 | }, 275 | "iconv-lite": { 276 | "version": "0.4.24", 277 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 278 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 279 | "requires": { 280 | "safer-buffer": ">= 2.1.2 < 3" 281 | } 282 | }, 283 | "inherits": { 284 | "version": "2.0.4", 285 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 286 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 287 | }, 288 | "ipaddr.js": { 289 | "version": "1.9.1", 290 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 291 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 292 | }, 293 | "media-typer": { 294 | "version": "0.3.0", 295 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 296 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" 297 | }, 298 | "merge-descriptors": { 299 | "version": "1.0.3", 300 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", 301 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==" 302 | }, 303 | "methods": { 304 | "version": "1.1.2", 305 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 306 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" 307 | }, 308 | "mime": { 309 | "version": "1.6.0", 310 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 311 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 312 | }, 313 | "mime-db": { 314 | "version": "1.52.0", 315 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 316 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 317 | }, 318 | "mime-types": { 319 | "version": "2.1.35", 320 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 321 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 322 | "requires": { 323 | "mime-db": "1.52.0" 324 | } 325 | }, 326 | "ms": { 327 | "version": "2.0.0", 328 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 329 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 330 | }, 331 | "negotiator": { 332 | "version": "0.6.3", 333 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 334 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 335 | }, 336 | "object-assign": { 337 | "version": "4.1.1", 338 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 339 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 340 | }, 341 | "object-inspect": { 342 | "version": "1.13.2", 343 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", 344 | "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==" 345 | }, 346 | "on-finished": { 347 | "version": "2.4.1", 348 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 349 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 350 | "requires": { 351 | "ee-first": "1.1.1" 352 | } 353 | }, 354 | "parseurl": { 355 | "version": "1.3.3", 356 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 357 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 358 | }, 359 | "path-to-regexp": { 360 | "version": "0.1.10", 361 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", 362 | "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" 363 | }, 364 | "proxy-addr": { 365 | "version": "2.0.7", 366 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 367 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 368 | "requires": { 369 | "forwarded": "0.2.0", 370 | "ipaddr.js": "1.9.1" 371 | } 372 | }, 373 | "qs": { 374 | "version": "6.13.0", 375 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", 376 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", 377 | "requires": { 378 | "side-channel": "^1.0.6" 379 | } 380 | }, 381 | "range-parser": { 382 | "version": "1.2.1", 383 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 384 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 385 | }, 386 | "raw-body": { 387 | "version": "2.5.2", 388 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 389 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 390 | "requires": { 391 | "bytes": "3.1.2", 392 | "http-errors": "2.0.0", 393 | "iconv-lite": "0.4.24", 394 | "unpipe": "1.0.0" 395 | } 396 | }, 397 | "safe-buffer": { 398 | "version": "5.2.1", 399 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 400 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 401 | }, 402 | "safer-buffer": { 403 | "version": "2.1.2", 404 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 405 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 406 | }, 407 | "send": { 408 | "version": "0.19.0", 409 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", 410 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", 411 | "requires": { 412 | "debug": "2.6.9", 413 | "depd": "2.0.0", 414 | "destroy": "1.2.0", 415 | "encodeurl": "~1.0.2", 416 | "escape-html": "~1.0.3", 417 | "etag": "~1.8.1", 418 | "fresh": "0.5.2", 419 | "http-errors": "2.0.0", 420 | "mime": "1.6.0", 421 | "ms": "2.1.3", 422 | "on-finished": "2.4.1", 423 | "range-parser": "~1.2.1", 424 | "statuses": "2.0.1" 425 | }, 426 | "dependencies": { 427 | "encodeurl": { 428 | "version": "1.0.2", 429 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 430 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" 431 | }, 432 | "ms": { 433 | "version": "2.1.3", 434 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 435 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 436 | } 437 | } 438 | }, 439 | "serve-static": { 440 | "version": "1.16.2", 441 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", 442 | "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", 443 | "requires": { 444 | "encodeurl": "~2.0.0", 445 | "escape-html": "~1.0.3", 446 | "parseurl": "~1.3.3", 447 | "send": "0.19.0" 448 | } 449 | }, 450 | "set-function-length": { 451 | "version": "1.2.2", 452 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", 453 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", 454 | "requires": { 455 | "define-data-property": "^1.1.4", 456 | "es-errors": "^1.3.0", 457 | "function-bind": "^1.1.2", 458 | "get-intrinsic": "^1.2.4", 459 | "gopd": "^1.0.1", 460 | "has-property-descriptors": "^1.0.2" 461 | } 462 | }, 463 | "setprototypeof": { 464 | "version": "1.2.0", 465 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 466 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 467 | }, 468 | "side-channel": { 469 | "version": "1.0.6", 470 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", 471 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", 472 | "requires": { 473 | "call-bind": "^1.0.7", 474 | "es-errors": "^1.3.0", 475 | "get-intrinsic": "^1.2.4", 476 | "object-inspect": "^1.13.1" 477 | } 478 | }, 479 | "statuses": { 480 | "version": "2.0.1", 481 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 482 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" 483 | }, 484 | "toidentifier": { 485 | "version": "1.0.1", 486 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 487 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 488 | }, 489 | "type-is": { 490 | "version": "1.6.18", 491 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 492 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 493 | "requires": { 494 | "media-typer": "0.3.0", 495 | "mime-types": "~2.1.24" 496 | } 497 | }, 498 | "unpipe": { 499 | "version": "1.0.0", 500 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 501 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" 502 | }, 503 | "utils-merge": { 504 | "version": "1.0.1", 505 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 506 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" 507 | }, 508 | "vary": { 509 | "version": "1.1.2", 510 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 511 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 512 | } 513 | } 514 | } 515 | -------------------------------------------------------------------------------- /microservices/src/products/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "products", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node server.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "Apache-2.0", 13 | "dependencies": { 14 | "cors": "^2.8.5", 15 | "express": "^4.17.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /microservices/src/products/server.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | const express = require("express"); 17 | const cors = require("cors"); 18 | const app = express(); 19 | const port = process.env.PORT || 8082; 20 | 21 | //Load product for pseudo database 22 | const products = require("./data/products.json").products; 23 | 24 | //Enable cors 25 | app.use(cors()); 26 | 27 | //Get all products 28 | app.get("/api/products", (req, res) => res.json(products)); 29 | 30 | //Get products by ID 31 | app.get("/api/products/:id", (req, res) => 32 | res.json(products.find(product => product.id === req.params.id)) 33 | ); 34 | 35 | app.listen(port, () => 36 | console.log(`Products microservice listening on port ${port}!`) 37 | ); 38 | -------------------------------------------------------------------------------- /monolith/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /monolith/.gcloudignore: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | .git 16 | .gitignore 17 | node_modules/ 18 | -------------------------------------------------------------------------------- /monolith/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /public 6 | 7 | # misc 8 | .DS_Store -------------------------------------------------------------------------------- /monolith/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM node:16 16 | 17 | # Create app directory 18 | WORKDIR /usr/src/app 19 | 20 | # Install app dependencies 21 | # A wildcard is used to ensure both package.json AND package-lock.json are copied 22 | # where available (npm@5+) 23 | COPY package*.json ./ 24 | 25 | RUN npm install 26 | # If you are building your code for production 27 | # RUN npm ci --only=production 28 | 29 | # Bundle app source 30 | COPY . . 31 | 32 | EXPOSE 8080 33 | CMD [ "node", "src/server.js" ] -------------------------------------------------------------------------------- /monolith/data/orders.json: -------------------------------------------------------------------------------- 1 | { 2 | "orders": [ 3 | { 4 | "id": "ORD-000001", 5 | "date": "7/01/2019", 6 | "cost": 67.99, 7 | "items": ["OLJCESPC7Z"] 8 | }, 9 | { 10 | "id": "ORD-000002", 11 | "date": "7/24/2019", 12 | "cost": 124, 13 | "items": ["1YMWWN1N4O"] 14 | }, 15 | { 16 | "id": "ORD-000003", 17 | "date": "8/03/2019", 18 | "cost": 12.49, 19 | "items": ["66VCHSJNUP"] 20 | }, 21 | { 22 | "id": "ORD-000004", 23 | "date": "8/14/2019", 24 | "cost": 89.83, 25 | "items": ["0PUK6V6EV0", "LS4PSXUNUM"] 26 | }, 27 | { 28 | "id": "ORD-000005", 29 | "date": "8/29/2019", 30 | "cost": 12.30, 31 | "items": ["6E92ZMYYFZ"] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /monolith/data/products.json: -------------------------------------------------------------------------------- 1 | { 2 | "products": [ 3 | { 4 | "id": "OLJCESPC7Z", 5 | "name": "Vintage Typewriter", 6 | "description": "This typewriter looks good in your living room.", 7 | "picture": "static/img/products/typewriter.jpg", 8 | "cost": 67.99, 9 | "categories": ["vintage"] 10 | }, 11 | { 12 | "id": "66VCHSJNUP", 13 | "name": "Vintage Camera Lens", 14 | "description": "You won't have a camera to use it and it probably doesn't work anyway.", 15 | "picture": "static/img/products/camera-lens.jpg", 16 | "cost": 12.49, 17 | "categories": ["photography", "vintage"] 18 | }, 19 | { 20 | "id": "1YMWWN1N4O", 21 | "name": "Home Barista Kit", 22 | "description": "Always wanted to brew coffee with Chemex and Aeropress at home?", 23 | "picture": "static/img/products/barista-kit.jpg", 24 | "cost": 124, 25 | "categories": ["cookware"] 26 | }, 27 | { 28 | "id": "L9ECAV7KIM", 29 | "name": "Terrarium", 30 | "description": "This terrarium will looks great in your white painted living room.", 31 | "picture": "static/img/products/terrarium.jpg", 32 | "cost": 36.45, 33 | "categories": ["gardening"] 34 | }, 35 | { 36 | "id": "2ZYFJ3GM2N", 37 | "name": "Film Camera", 38 | "description": "This camera looks like it's a film camera, but it's actually digital.", 39 | "picture": "static/img/products/film-camera.jpg", 40 | "cost": 2245, 41 | "categories": ["photography", "vintage"] 42 | }, 43 | { 44 | "id": "0PUK6V6EV0", 45 | "name": "Vintage Record Player", 46 | "description": "It still works.", 47 | "picture": "static/img/products/record-player.jpg", 48 | "cost": 65.50, 49 | "categories": ["music", "vintage"] 50 | }, 51 | { 52 | "id": "LS4PSXUNUM", 53 | "name": "Metal Camping Mug", 54 | "description": "You probably don't go camping that often but this is better than plastic cups.", 55 | "picture": "static/img/products/camp-mug.jpg", 56 | "cost": 24.33, 57 | "categories": ["cookware"] 58 | }, 59 | { 60 | "id": "9SIQT8TOJO", 61 | "name": "City Bike", 62 | "description": "This single gear bike probably cannot climb the hills of San Francisco.", 63 | "picture": "static/img/products/city-bike.jpg", 64 | "cost": 789.50, 65 | "categories": ["cycling"] 66 | }, 67 | { 68 | "id": "6E92ZMYYFZ", 69 | "name": "Air Plant", 70 | "description": "Have you ever wondered whether air plants need water? Buy one and figure out.", 71 | "picture": "static/img/products/air-plant.jpg", 72 | "cost": 12.30, 73 | "categories": ["gardening"] 74 | } 75 | ] 76 | } -------------------------------------------------------------------------------- /monolith/k8s/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: monolith 5 | labels: 6 | app: monolith 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: monolith 12 | template: 13 | metadata: 14 | labels: 15 | app: monolith 16 | spec: 17 | containers: 18 | - name: monolith 19 | image: gcr.io//monolith:1.0.0 20 | imagePullPolicy: Always 21 | ports: 22 | - containerPort: 8080 -------------------------------------------------------------------------------- /monolith/k8s/service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: monolith 5 | spec: 6 | type: LoadBalancer 7 | ports: 8 | - port: 80 9 | targetPort: 8080 10 | protocol: TCP 11 | selector: 12 | app: monolith 13 | -------------------------------------------------------------------------------- /monolith/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "monolith", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "monolith", 9 | "version": "1.0.0", 10 | "license": "Apache-2.0", 11 | "dependencies": { 12 | "body-parser": "^1.20.2", 13 | "express": "^4.18.2" 14 | } 15 | }, 16 | "node_modules/accepts": { 17 | "version": "1.3.8", 18 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 19 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 20 | "dependencies": { 21 | "mime-types": "~2.1.34", 22 | "negotiator": "0.6.3" 23 | }, 24 | "engines": { 25 | "node": ">= 0.6" 26 | } 27 | }, 28 | "node_modules/array-flatten": { 29 | "version": "1.1.1", 30 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 31 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 32 | }, 33 | "node_modules/body-parser": { 34 | "version": "1.20.3", 35 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", 36 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", 37 | "dependencies": { 38 | "bytes": "3.1.2", 39 | "content-type": "~1.0.5", 40 | "debug": "2.6.9", 41 | "depd": "2.0.0", 42 | "destroy": "1.2.0", 43 | "http-errors": "2.0.0", 44 | "iconv-lite": "0.4.24", 45 | "on-finished": "2.4.1", 46 | "qs": "6.13.0", 47 | "raw-body": "2.5.2", 48 | "type-is": "~1.6.18", 49 | "unpipe": "1.0.0" 50 | }, 51 | "engines": { 52 | "node": ">= 0.8", 53 | "npm": "1.2.8000 || >= 1.4.16" 54 | } 55 | }, 56 | "node_modules/body-parser/node_modules/qs": { 57 | "version": "6.13.0", 58 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", 59 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", 60 | "dependencies": { 61 | "side-channel": "^1.0.6" 62 | }, 63 | "engines": { 64 | "node": ">=0.6" 65 | }, 66 | "funding": { 67 | "url": "https://github.com/sponsors/ljharb" 68 | } 69 | }, 70 | "node_modules/bytes": { 71 | "version": "3.1.2", 72 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 73 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 74 | "engines": { 75 | "node": ">= 0.8" 76 | } 77 | }, 78 | "node_modules/call-bind": { 79 | "version": "1.0.7", 80 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", 81 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", 82 | "dependencies": { 83 | "es-define-property": "^1.0.0", 84 | "es-errors": "^1.3.0", 85 | "function-bind": "^1.1.2", 86 | "get-intrinsic": "^1.2.4", 87 | "set-function-length": "^1.2.1" 88 | }, 89 | "engines": { 90 | "node": ">= 0.4" 91 | }, 92 | "funding": { 93 | "url": "https://github.com/sponsors/ljharb" 94 | } 95 | }, 96 | "node_modules/content-disposition": { 97 | "version": "0.5.4", 98 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 99 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 100 | "dependencies": { 101 | "safe-buffer": "5.2.1" 102 | }, 103 | "engines": { 104 | "node": ">= 0.6" 105 | } 106 | }, 107 | "node_modules/content-type": { 108 | "version": "1.0.5", 109 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 110 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 111 | "engines": { 112 | "node": ">= 0.6" 113 | } 114 | }, 115 | "node_modules/cookie": { 116 | "version": "0.6.0", 117 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", 118 | "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", 119 | "engines": { 120 | "node": ">= 0.6" 121 | } 122 | }, 123 | "node_modules/cookie-signature": { 124 | "version": "1.0.6", 125 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 126 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 127 | }, 128 | "node_modules/debug": { 129 | "version": "2.6.9", 130 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 131 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 132 | "dependencies": { 133 | "ms": "2.0.0" 134 | } 135 | }, 136 | "node_modules/define-data-property": { 137 | "version": "1.1.4", 138 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", 139 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", 140 | "dependencies": { 141 | "es-define-property": "^1.0.0", 142 | "es-errors": "^1.3.0", 143 | "gopd": "^1.0.1" 144 | }, 145 | "engines": { 146 | "node": ">= 0.4" 147 | }, 148 | "funding": { 149 | "url": "https://github.com/sponsors/ljharb" 150 | } 151 | }, 152 | "node_modules/depd": { 153 | "version": "2.0.0", 154 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 155 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 156 | "engines": { 157 | "node": ">= 0.8" 158 | } 159 | }, 160 | "node_modules/destroy": { 161 | "version": "1.2.0", 162 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 163 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 164 | "engines": { 165 | "node": ">= 0.8", 166 | "npm": "1.2.8000 || >= 1.4.16" 167 | } 168 | }, 169 | "node_modules/ee-first": { 170 | "version": "1.1.1", 171 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 172 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 173 | }, 174 | "node_modules/encodeurl": { 175 | "version": "1.0.2", 176 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 177 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 178 | "engines": { 179 | "node": ">= 0.8" 180 | } 181 | }, 182 | "node_modules/es-define-property": { 183 | "version": "1.0.0", 184 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", 185 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", 186 | "dependencies": { 187 | "get-intrinsic": "^1.2.4" 188 | }, 189 | "engines": { 190 | "node": ">= 0.4" 191 | } 192 | }, 193 | "node_modules/es-errors": { 194 | "version": "1.3.0", 195 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 196 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 197 | "engines": { 198 | "node": ">= 0.4" 199 | } 200 | }, 201 | "node_modules/escape-html": { 202 | "version": "1.0.3", 203 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 204 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 205 | }, 206 | "node_modules/etag": { 207 | "version": "1.8.1", 208 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 209 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 210 | "engines": { 211 | "node": ">= 0.6" 212 | } 213 | }, 214 | "node_modules/express": { 215 | "version": "4.20.0", 216 | "resolved": "https://registry.npmjs.org/express/-/express-4.20.0.tgz", 217 | "integrity": "sha512-pLdae7I6QqShF5PnNTCVn4hI91Dx0Grkn2+IAsMTgMIKuQVte2dN9PeGSSAME2FR8anOhVA62QDIUaWVfEXVLw==", 218 | "dependencies": { 219 | "accepts": "~1.3.8", 220 | "array-flatten": "1.1.1", 221 | "body-parser": "1.20.3", 222 | "content-disposition": "0.5.4", 223 | "content-type": "~1.0.4", 224 | "cookie": "0.6.0", 225 | "cookie-signature": "1.0.6", 226 | "debug": "2.6.9", 227 | "depd": "2.0.0", 228 | "encodeurl": "~2.0.0", 229 | "escape-html": "~1.0.3", 230 | "etag": "~1.8.1", 231 | "finalhandler": "1.2.0", 232 | "fresh": "0.5.2", 233 | "http-errors": "2.0.0", 234 | "merge-descriptors": "1.0.3", 235 | "methods": "~1.1.2", 236 | "on-finished": "2.4.1", 237 | "parseurl": "~1.3.3", 238 | "path-to-regexp": "0.1.10", 239 | "proxy-addr": "~2.0.7", 240 | "qs": "6.11.0", 241 | "range-parser": "~1.2.1", 242 | "safe-buffer": "5.2.1", 243 | "send": "0.19.0", 244 | "serve-static": "1.16.0", 245 | "setprototypeof": "1.2.0", 246 | "statuses": "2.0.1", 247 | "type-is": "~1.6.18", 248 | "utils-merge": "1.0.1", 249 | "vary": "~1.1.2" 250 | }, 251 | "engines": { 252 | "node": ">= 0.10.0" 253 | } 254 | }, 255 | "node_modules/express/node_modules/encodeurl": { 256 | "version": "2.0.0", 257 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 258 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 259 | "engines": { 260 | "node": ">= 0.8" 261 | } 262 | }, 263 | "node_modules/finalhandler": { 264 | "version": "1.2.0", 265 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 266 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 267 | "dependencies": { 268 | "debug": "2.6.9", 269 | "encodeurl": "~1.0.2", 270 | "escape-html": "~1.0.3", 271 | "on-finished": "2.4.1", 272 | "parseurl": "~1.3.3", 273 | "statuses": "2.0.1", 274 | "unpipe": "~1.0.0" 275 | }, 276 | "engines": { 277 | "node": ">= 0.8" 278 | } 279 | }, 280 | "node_modules/forwarded": { 281 | "version": "0.2.0", 282 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 283 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 284 | "engines": { 285 | "node": ">= 0.6" 286 | } 287 | }, 288 | "node_modules/fresh": { 289 | "version": "0.5.2", 290 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 291 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 292 | "engines": { 293 | "node": ">= 0.6" 294 | } 295 | }, 296 | "node_modules/function-bind": { 297 | "version": "1.1.2", 298 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 299 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 300 | "funding": { 301 | "url": "https://github.com/sponsors/ljharb" 302 | } 303 | }, 304 | "node_modules/get-intrinsic": { 305 | "version": "1.2.4", 306 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", 307 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", 308 | "dependencies": { 309 | "es-errors": "^1.3.0", 310 | "function-bind": "^1.1.2", 311 | "has-proto": "^1.0.1", 312 | "has-symbols": "^1.0.3", 313 | "hasown": "^2.0.0" 314 | }, 315 | "engines": { 316 | "node": ">= 0.4" 317 | }, 318 | "funding": { 319 | "url": "https://github.com/sponsors/ljharb" 320 | } 321 | }, 322 | "node_modules/gopd": { 323 | "version": "1.0.1", 324 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 325 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 326 | "dependencies": { 327 | "get-intrinsic": "^1.1.3" 328 | }, 329 | "funding": { 330 | "url": "https://github.com/sponsors/ljharb" 331 | } 332 | }, 333 | "node_modules/has-property-descriptors": { 334 | "version": "1.0.2", 335 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", 336 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", 337 | "dependencies": { 338 | "es-define-property": "^1.0.0" 339 | }, 340 | "funding": { 341 | "url": "https://github.com/sponsors/ljharb" 342 | } 343 | }, 344 | "node_modules/has-proto": { 345 | "version": "1.0.3", 346 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", 347 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", 348 | "engines": { 349 | "node": ">= 0.4" 350 | }, 351 | "funding": { 352 | "url": "https://github.com/sponsors/ljharb" 353 | } 354 | }, 355 | "node_modules/has-symbols": { 356 | "version": "1.0.3", 357 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 358 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 359 | "engines": { 360 | "node": ">= 0.4" 361 | }, 362 | "funding": { 363 | "url": "https://github.com/sponsors/ljharb" 364 | } 365 | }, 366 | "node_modules/hasown": { 367 | "version": "2.0.2", 368 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 369 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 370 | "dependencies": { 371 | "function-bind": "^1.1.2" 372 | }, 373 | "engines": { 374 | "node": ">= 0.4" 375 | } 376 | }, 377 | "node_modules/http-errors": { 378 | "version": "2.0.0", 379 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 380 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 381 | "dependencies": { 382 | "depd": "2.0.0", 383 | "inherits": "2.0.4", 384 | "setprototypeof": "1.2.0", 385 | "statuses": "2.0.1", 386 | "toidentifier": "1.0.1" 387 | }, 388 | "engines": { 389 | "node": ">= 0.8" 390 | } 391 | }, 392 | "node_modules/iconv-lite": { 393 | "version": "0.4.24", 394 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 395 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 396 | "dependencies": { 397 | "safer-buffer": ">= 2.1.2 < 3" 398 | }, 399 | "engines": { 400 | "node": ">=0.10.0" 401 | } 402 | }, 403 | "node_modules/inherits": { 404 | "version": "2.0.4", 405 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 406 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 407 | }, 408 | "node_modules/ipaddr.js": { 409 | "version": "1.9.1", 410 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 411 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 412 | "engines": { 413 | "node": ">= 0.10" 414 | } 415 | }, 416 | "node_modules/media-typer": { 417 | "version": "0.3.0", 418 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 419 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", 420 | "engines": { 421 | "node": ">= 0.6" 422 | } 423 | }, 424 | "node_modules/merge-descriptors": { 425 | "version": "1.0.3", 426 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", 427 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", 428 | "funding": { 429 | "url": "https://github.com/sponsors/sindresorhus" 430 | } 431 | }, 432 | "node_modules/methods": { 433 | "version": "1.1.2", 434 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 435 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", 436 | "engines": { 437 | "node": ">= 0.6" 438 | } 439 | }, 440 | "node_modules/mime": { 441 | "version": "1.6.0", 442 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 443 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 444 | "bin": { 445 | "mime": "cli.js" 446 | }, 447 | "engines": { 448 | "node": ">=4" 449 | } 450 | }, 451 | "node_modules/mime-db": { 452 | "version": "1.52.0", 453 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 454 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 455 | "engines": { 456 | "node": ">= 0.6" 457 | } 458 | }, 459 | "node_modules/mime-types": { 460 | "version": "2.1.35", 461 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 462 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 463 | "dependencies": { 464 | "mime-db": "1.52.0" 465 | }, 466 | "engines": { 467 | "node": ">= 0.6" 468 | } 469 | }, 470 | "node_modules/ms": { 471 | "version": "2.0.0", 472 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 473 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 474 | }, 475 | "node_modules/negotiator": { 476 | "version": "0.6.3", 477 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 478 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 479 | "engines": { 480 | "node": ">= 0.6" 481 | } 482 | }, 483 | "node_modules/object-inspect": { 484 | "version": "1.13.2", 485 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", 486 | "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", 487 | "engines": { 488 | "node": ">= 0.4" 489 | }, 490 | "funding": { 491 | "url": "https://github.com/sponsors/ljharb" 492 | } 493 | }, 494 | "node_modules/on-finished": { 495 | "version": "2.4.1", 496 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 497 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 498 | "dependencies": { 499 | "ee-first": "1.1.1" 500 | }, 501 | "engines": { 502 | "node": ">= 0.8" 503 | } 504 | }, 505 | "node_modules/parseurl": { 506 | "version": "1.3.3", 507 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 508 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 509 | "engines": { 510 | "node": ">= 0.8" 511 | } 512 | }, 513 | "node_modules/path-to-regexp": { 514 | "version": "0.1.10", 515 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", 516 | "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" 517 | }, 518 | "node_modules/proxy-addr": { 519 | "version": "2.0.7", 520 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 521 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 522 | "dependencies": { 523 | "forwarded": "0.2.0", 524 | "ipaddr.js": "1.9.1" 525 | }, 526 | "engines": { 527 | "node": ">= 0.10" 528 | } 529 | }, 530 | "node_modules/qs": { 531 | "version": "6.11.0", 532 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 533 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 534 | "dependencies": { 535 | "side-channel": "^1.0.4" 536 | }, 537 | "engines": { 538 | "node": ">=0.6" 539 | }, 540 | "funding": { 541 | "url": "https://github.com/sponsors/ljharb" 542 | } 543 | }, 544 | "node_modules/range-parser": { 545 | "version": "1.2.1", 546 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 547 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 548 | "engines": { 549 | "node": ">= 0.6" 550 | } 551 | }, 552 | "node_modules/raw-body": { 553 | "version": "2.5.2", 554 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 555 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 556 | "dependencies": { 557 | "bytes": "3.1.2", 558 | "http-errors": "2.0.0", 559 | "iconv-lite": "0.4.24", 560 | "unpipe": "1.0.0" 561 | }, 562 | "engines": { 563 | "node": ">= 0.8" 564 | } 565 | }, 566 | "node_modules/safe-buffer": { 567 | "version": "5.2.1", 568 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 569 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 570 | "funding": [ 571 | { 572 | "type": "github", 573 | "url": "https://github.com/sponsors/feross" 574 | }, 575 | { 576 | "type": "patreon", 577 | "url": "https://www.patreon.com/feross" 578 | }, 579 | { 580 | "type": "consulting", 581 | "url": "https://feross.org/support" 582 | } 583 | ] 584 | }, 585 | "node_modules/safer-buffer": { 586 | "version": "2.1.2", 587 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 588 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 589 | }, 590 | "node_modules/send": { 591 | "version": "0.19.0", 592 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", 593 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", 594 | "dependencies": { 595 | "debug": "2.6.9", 596 | "depd": "2.0.0", 597 | "destroy": "1.2.0", 598 | "encodeurl": "~1.0.2", 599 | "escape-html": "~1.0.3", 600 | "etag": "~1.8.1", 601 | "fresh": "0.5.2", 602 | "http-errors": "2.0.0", 603 | "mime": "1.6.0", 604 | "ms": "2.1.3", 605 | "on-finished": "2.4.1", 606 | "range-parser": "~1.2.1", 607 | "statuses": "2.0.1" 608 | }, 609 | "engines": { 610 | "node": ">= 0.8.0" 611 | } 612 | }, 613 | "node_modules/send/node_modules/ms": { 614 | "version": "2.1.3", 615 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 616 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 617 | }, 618 | "node_modules/serve-static": { 619 | "version": "1.16.0", 620 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.0.tgz", 621 | "integrity": "sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA==", 622 | "dependencies": { 623 | "encodeurl": "~1.0.2", 624 | "escape-html": "~1.0.3", 625 | "parseurl": "~1.3.3", 626 | "send": "0.18.0" 627 | }, 628 | "engines": { 629 | "node": ">= 0.8.0" 630 | } 631 | }, 632 | "node_modules/serve-static/node_modules/ms": { 633 | "version": "2.1.3", 634 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 635 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 636 | }, 637 | "node_modules/serve-static/node_modules/send": { 638 | "version": "0.18.0", 639 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 640 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 641 | "dependencies": { 642 | "debug": "2.6.9", 643 | "depd": "2.0.0", 644 | "destroy": "1.2.0", 645 | "encodeurl": "~1.0.2", 646 | "escape-html": "~1.0.3", 647 | "etag": "~1.8.1", 648 | "fresh": "0.5.2", 649 | "http-errors": "2.0.0", 650 | "mime": "1.6.0", 651 | "ms": "2.1.3", 652 | "on-finished": "2.4.1", 653 | "range-parser": "~1.2.1", 654 | "statuses": "2.0.1" 655 | }, 656 | "engines": { 657 | "node": ">= 0.8.0" 658 | } 659 | }, 660 | "node_modules/set-function-length": { 661 | "version": "1.2.2", 662 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", 663 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", 664 | "dependencies": { 665 | "define-data-property": "^1.1.4", 666 | "es-errors": "^1.3.0", 667 | "function-bind": "^1.1.2", 668 | "get-intrinsic": "^1.2.4", 669 | "gopd": "^1.0.1", 670 | "has-property-descriptors": "^1.0.2" 671 | }, 672 | "engines": { 673 | "node": ">= 0.4" 674 | } 675 | }, 676 | "node_modules/setprototypeof": { 677 | "version": "1.2.0", 678 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 679 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 680 | }, 681 | "node_modules/side-channel": { 682 | "version": "1.0.6", 683 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", 684 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", 685 | "dependencies": { 686 | "call-bind": "^1.0.7", 687 | "es-errors": "^1.3.0", 688 | "get-intrinsic": "^1.2.4", 689 | "object-inspect": "^1.13.1" 690 | }, 691 | "engines": { 692 | "node": ">= 0.4" 693 | }, 694 | "funding": { 695 | "url": "https://github.com/sponsors/ljharb" 696 | } 697 | }, 698 | "node_modules/statuses": { 699 | "version": "2.0.1", 700 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 701 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 702 | "engines": { 703 | "node": ">= 0.8" 704 | } 705 | }, 706 | "node_modules/toidentifier": { 707 | "version": "1.0.1", 708 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 709 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 710 | "engines": { 711 | "node": ">=0.6" 712 | } 713 | }, 714 | "node_modules/type-is": { 715 | "version": "1.6.18", 716 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 717 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 718 | "dependencies": { 719 | "media-typer": "0.3.0", 720 | "mime-types": "~2.1.24" 721 | }, 722 | "engines": { 723 | "node": ">= 0.6" 724 | } 725 | }, 726 | "node_modules/unpipe": { 727 | "version": "1.0.0", 728 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 729 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", 730 | "engines": { 731 | "node": ">= 0.8" 732 | } 733 | }, 734 | "node_modules/utils-merge": { 735 | "version": "1.0.1", 736 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 737 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", 738 | "engines": { 739 | "node": ">= 0.4.0" 740 | } 741 | }, 742 | "node_modules/vary": { 743 | "version": "1.1.2", 744 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 745 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", 746 | "engines": { 747 | "node": ">= 0.8" 748 | } 749 | } 750 | }, 751 | "dependencies": { 752 | "accepts": { 753 | "version": "1.3.8", 754 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 755 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 756 | "requires": { 757 | "mime-types": "~2.1.34", 758 | "negotiator": "0.6.3" 759 | } 760 | }, 761 | "array-flatten": { 762 | "version": "1.1.1", 763 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 764 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 765 | }, 766 | "body-parser": { 767 | "version": "1.20.3", 768 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", 769 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", 770 | "requires": { 771 | "bytes": "3.1.2", 772 | "content-type": "~1.0.5", 773 | "debug": "2.6.9", 774 | "depd": "2.0.0", 775 | "destroy": "1.2.0", 776 | "http-errors": "2.0.0", 777 | "iconv-lite": "0.4.24", 778 | "on-finished": "2.4.1", 779 | "qs": "6.13.0", 780 | "raw-body": "2.5.2", 781 | "type-is": "~1.6.18", 782 | "unpipe": "1.0.0" 783 | }, 784 | "dependencies": { 785 | "qs": { 786 | "version": "6.13.0", 787 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", 788 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", 789 | "requires": { 790 | "side-channel": "^1.0.6" 791 | } 792 | } 793 | } 794 | }, 795 | "bytes": { 796 | "version": "3.1.2", 797 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 798 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 799 | }, 800 | "call-bind": { 801 | "version": "1.0.7", 802 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", 803 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", 804 | "requires": { 805 | "es-define-property": "^1.0.0", 806 | "es-errors": "^1.3.0", 807 | "function-bind": "^1.1.2", 808 | "get-intrinsic": "^1.2.4", 809 | "set-function-length": "^1.2.1" 810 | } 811 | }, 812 | "content-disposition": { 813 | "version": "0.5.4", 814 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 815 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 816 | "requires": { 817 | "safe-buffer": "5.2.1" 818 | } 819 | }, 820 | "content-type": { 821 | "version": "1.0.5", 822 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 823 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" 824 | }, 825 | "cookie": { 826 | "version": "0.6.0", 827 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", 828 | "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==" 829 | }, 830 | "cookie-signature": { 831 | "version": "1.0.6", 832 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 833 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 834 | }, 835 | "debug": { 836 | "version": "2.6.9", 837 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 838 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 839 | "requires": { 840 | "ms": "2.0.0" 841 | } 842 | }, 843 | "define-data-property": { 844 | "version": "1.1.4", 845 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", 846 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", 847 | "requires": { 848 | "es-define-property": "^1.0.0", 849 | "es-errors": "^1.3.0", 850 | "gopd": "^1.0.1" 851 | } 852 | }, 853 | "depd": { 854 | "version": "2.0.0", 855 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 856 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 857 | }, 858 | "destroy": { 859 | "version": "1.2.0", 860 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 861 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" 862 | }, 863 | "ee-first": { 864 | "version": "1.1.1", 865 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 866 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 867 | }, 868 | "encodeurl": { 869 | "version": "1.0.2", 870 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 871 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" 872 | }, 873 | "es-define-property": { 874 | "version": "1.0.0", 875 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", 876 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", 877 | "requires": { 878 | "get-intrinsic": "^1.2.4" 879 | } 880 | }, 881 | "es-errors": { 882 | "version": "1.3.0", 883 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 884 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" 885 | }, 886 | "escape-html": { 887 | "version": "1.0.3", 888 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 889 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 890 | }, 891 | "etag": { 892 | "version": "1.8.1", 893 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 894 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" 895 | }, 896 | "express": { 897 | "version": "4.20.0", 898 | "resolved": "https://registry.npmjs.org/express/-/express-4.20.0.tgz", 899 | "integrity": "sha512-pLdae7I6QqShF5PnNTCVn4hI91Dx0Grkn2+IAsMTgMIKuQVte2dN9PeGSSAME2FR8anOhVA62QDIUaWVfEXVLw==", 900 | "requires": { 901 | "accepts": "~1.3.8", 902 | "array-flatten": "1.1.1", 903 | "body-parser": "1.20.3", 904 | "content-disposition": "0.5.4", 905 | "content-type": "~1.0.4", 906 | "cookie": "0.6.0", 907 | "cookie-signature": "1.0.6", 908 | "debug": "2.6.9", 909 | "depd": "2.0.0", 910 | "encodeurl": "~2.0.0", 911 | "escape-html": "~1.0.3", 912 | "etag": "~1.8.1", 913 | "finalhandler": "1.2.0", 914 | "fresh": "0.5.2", 915 | "http-errors": "2.0.0", 916 | "merge-descriptors": "1.0.3", 917 | "methods": "~1.1.2", 918 | "on-finished": "2.4.1", 919 | "parseurl": "~1.3.3", 920 | "path-to-regexp": "0.1.10", 921 | "proxy-addr": "~2.0.7", 922 | "qs": "6.11.0", 923 | "range-parser": "~1.2.1", 924 | "safe-buffer": "5.2.1", 925 | "send": "0.19.0", 926 | "serve-static": "1.16.0", 927 | "setprototypeof": "1.2.0", 928 | "statuses": "2.0.1", 929 | "type-is": "~1.6.18", 930 | "utils-merge": "1.0.1", 931 | "vary": "~1.1.2" 932 | }, 933 | "dependencies": { 934 | "encodeurl": { 935 | "version": "2.0.0", 936 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 937 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" 938 | } 939 | } 940 | }, 941 | "finalhandler": { 942 | "version": "1.2.0", 943 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 944 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 945 | "requires": { 946 | "debug": "2.6.9", 947 | "encodeurl": "~1.0.2", 948 | "escape-html": "~1.0.3", 949 | "on-finished": "2.4.1", 950 | "parseurl": "~1.3.3", 951 | "statuses": "2.0.1", 952 | "unpipe": "~1.0.0" 953 | } 954 | }, 955 | "forwarded": { 956 | "version": "0.2.0", 957 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 958 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 959 | }, 960 | "fresh": { 961 | "version": "0.5.2", 962 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 963 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" 964 | }, 965 | "function-bind": { 966 | "version": "1.1.2", 967 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 968 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" 969 | }, 970 | "get-intrinsic": { 971 | "version": "1.2.4", 972 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", 973 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", 974 | "requires": { 975 | "es-errors": "^1.3.0", 976 | "function-bind": "^1.1.2", 977 | "has-proto": "^1.0.1", 978 | "has-symbols": "^1.0.3", 979 | "hasown": "^2.0.0" 980 | } 981 | }, 982 | "gopd": { 983 | "version": "1.0.1", 984 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 985 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 986 | "requires": { 987 | "get-intrinsic": "^1.1.3" 988 | } 989 | }, 990 | "has-property-descriptors": { 991 | "version": "1.0.2", 992 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", 993 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", 994 | "requires": { 995 | "es-define-property": "^1.0.0" 996 | } 997 | }, 998 | "has-proto": { 999 | "version": "1.0.3", 1000 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", 1001 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" 1002 | }, 1003 | "has-symbols": { 1004 | "version": "1.0.3", 1005 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 1006 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" 1007 | }, 1008 | "hasown": { 1009 | "version": "2.0.2", 1010 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 1011 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 1012 | "requires": { 1013 | "function-bind": "^1.1.2" 1014 | } 1015 | }, 1016 | "http-errors": { 1017 | "version": "2.0.0", 1018 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 1019 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 1020 | "requires": { 1021 | "depd": "2.0.0", 1022 | "inherits": "2.0.4", 1023 | "setprototypeof": "1.2.0", 1024 | "statuses": "2.0.1", 1025 | "toidentifier": "1.0.1" 1026 | } 1027 | }, 1028 | "iconv-lite": { 1029 | "version": "0.4.24", 1030 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 1031 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 1032 | "requires": { 1033 | "safer-buffer": ">= 2.1.2 < 3" 1034 | } 1035 | }, 1036 | "inherits": { 1037 | "version": "2.0.4", 1038 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1039 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1040 | }, 1041 | "ipaddr.js": { 1042 | "version": "1.9.1", 1043 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 1044 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 1045 | }, 1046 | "media-typer": { 1047 | "version": "0.3.0", 1048 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 1049 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 1050 | }, 1051 | "merge-descriptors": { 1052 | "version": "1.0.3", 1053 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", 1054 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==" 1055 | }, 1056 | "methods": { 1057 | "version": "1.1.2", 1058 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1059 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 1060 | }, 1061 | "mime": { 1062 | "version": "1.6.0", 1063 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1064 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 1065 | }, 1066 | "mime-db": { 1067 | "version": "1.52.0", 1068 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1069 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 1070 | }, 1071 | "mime-types": { 1072 | "version": "2.1.35", 1073 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1074 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1075 | "requires": { 1076 | "mime-db": "1.52.0" 1077 | } 1078 | }, 1079 | "ms": { 1080 | "version": "2.0.0", 1081 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1082 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1083 | }, 1084 | "negotiator": { 1085 | "version": "0.6.3", 1086 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 1087 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 1088 | }, 1089 | "object-inspect": { 1090 | "version": "1.13.2", 1091 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", 1092 | "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==" 1093 | }, 1094 | "on-finished": { 1095 | "version": "2.4.1", 1096 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 1097 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 1098 | "requires": { 1099 | "ee-first": "1.1.1" 1100 | } 1101 | }, 1102 | "parseurl": { 1103 | "version": "1.3.3", 1104 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1105 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 1106 | }, 1107 | "path-to-regexp": { 1108 | "version": "0.1.10", 1109 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", 1110 | "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" 1111 | }, 1112 | "proxy-addr": { 1113 | "version": "2.0.7", 1114 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1115 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1116 | "requires": { 1117 | "forwarded": "0.2.0", 1118 | "ipaddr.js": "1.9.1" 1119 | } 1120 | }, 1121 | "qs": { 1122 | "version": "6.11.0", 1123 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 1124 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 1125 | "requires": { 1126 | "side-channel": "^1.0.4" 1127 | } 1128 | }, 1129 | "range-parser": { 1130 | "version": "1.2.1", 1131 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1132 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 1133 | }, 1134 | "raw-body": { 1135 | "version": "2.5.2", 1136 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 1137 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 1138 | "requires": { 1139 | "bytes": "3.1.2", 1140 | "http-errors": "2.0.0", 1141 | "iconv-lite": "0.4.24", 1142 | "unpipe": "1.0.0" 1143 | } 1144 | }, 1145 | "safe-buffer": { 1146 | "version": "5.2.1", 1147 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1148 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 1149 | }, 1150 | "safer-buffer": { 1151 | "version": "2.1.2", 1152 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1153 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1154 | }, 1155 | "send": { 1156 | "version": "0.19.0", 1157 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", 1158 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", 1159 | "requires": { 1160 | "debug": "2.6.9", 1161 | "depd": "2.0.0", 1162 | "destroy": "1.2.0", 1163 | "encodeurl": "~1.0.2", 1164 | "escape-html": "~1.0.3", 1165 | "etag": "~1.8.1", 1166 | "fresh": "0.5.2", 1167 | "http-errors": "2.0.0", 1168 | "mime": "1.6.0", 1169 | "ms": "2.1.3", 1170 | "on-finished": "2.4.1", 1171 | "range-parser": "~1.2.1", 1172 | "statuses": "2.0.1" 1173 | }, 1174 | "dependencies": { 1175 | "ms": { 1176 | "version": "2.1.3", 1177 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1178 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1179 | } 1180 | } 1181 | }, 1182 | "serve-static": { 1183 | "version": "1.16.0", 1184 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.0.tgz", 1185 | "integrity": "sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA==", 1186 | "requires": { 1187 | "encodeurl": "~1.0.2", 1188 | "escape-html": "~1.0.3", 1189 | "parseurl": "~1.3.3", 1190 | "send": "0.18.0" 1191 | }, 1192 | "dependencies": { 1193 | "ms": { 1194 | "version": "2.1.3", 1195 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1196 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1197 | }, 1198 | "send": { 1199 | "version": "0.18.0", 1200 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 1201 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 1202 | "requires": { 1203 | "debug": "2.6.9", 1204 | "depd": "2.0.0", 1205 | "destroy": "1.2.0", 1206 | "encodeurl": "~1.0.2", 1207 | "escape-html": "~1.0.3", 1208 | "etag": "~1.8.1", 1209 | "fresh": "0.5.2", 1210 | "http-errors": "2.0.0", 1211 | "mime": "1.6.0", 1212 | "ms": "2.1.3", 1213 | "on-finished": "2.4.1", 1214 | "range-parser": "~1.2.1", 1215 | "statuses": "2.0.1" 1216 | } 1217 | } 1218 | } 1219 | }, 1220 | "set-function-length": { 1221 | "version": "1.2.2", 1222 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", 1223 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", 1224 | "requires": { 1225 | "define-data-property": "^1.1.4", 1226 | "es-errors": "^1.3.0", 1227 | "function-bind": "^1.1.2", 1228 | "get-intrinsic": "^1.2.4", 1229 | "gopd": "^1.0.1", 1230 | "has-property-descriptors": "^1.0.2" 1231 | } 1232 | }, 1233 | "setprototypeof": { 1234 | "version": "1.2.0", 1235 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1236 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 1237 | }, 1238 | "side-channel": { 1239 | "version": "1.0.6", 1240 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", 1241 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", 1242 | "requires": { 1243 | "call-bind": "^1.0.7", 1244 | "es-errors": "^1.3.0", 1245 | "get-intrinsic": "^1.2.4", 1246 | "object-inspect": "^1.13.1" 1247 | } 1248 | }, 1249 | "statuses": { 1250 | "version": "2.0.1", 1251 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 1252 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" 1253 | }, 1254 | "toidentifier": { 1255 | "version": "1.0.1", 1256 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1257 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 1258 | }, 1259 | "type-is": { 1260 | "version": "1.6.18", 1261 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1262 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1263 | "requires": { 1264 | "media-typer": "0.3.0", 1265 | "mime-types": "~2.1.24" 1266 | } 1267 | }, 1268 | "unpipe": { 1269 | "version": "1.0.0", 1270 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1271 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 1272 | }, 1273 | "utils-merge": { 1274 | "version": "1.0.1", 1275 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1276 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 1277 | }, 1278 | "vary": { 1279 | "version": "1.1.2", 1280 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1281 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 1282 | } 1283 | } 1284 | } 1285 | -------------------------------------------------------------------------------- /monolith/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "monolith", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node ./src/server.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "Apache-2.0", 13 | "dependencies": { 14 | "body-parser": "^1.20.2", 15 | "express": "^4.18.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /monolith/src/server.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | const express = require("express"); 17 | const path = require("path"); 18 | const app = express(); 19 | const port = process.env.PORT || 8080; 20 | 21 | //Load orders and products for pseudo database 22 | const orders = require("../data/orders.json").orders; 23 | const products = require("../data/products.json").products; 24 | 25 | //Serve website 26 | app.use(express.static(path.join(__dirname, "..", "public"))); 27 | 28 | //Get all products 29 | app.get("/service/products", (req, res) => res.json(products)); 30 | 31 | //Get products by ID 32 | app.get("/service/products/:id", (req, res) => 33 | res.json(products.find((product) => product.id === req.params.id)) 34 | ); 35 | 36 | //Get all orders 37 | app.get("/service/orders", (req, res) => res.json(orders)); 38 | 39 | //Get orders by ID 40 | app.get("/service/orders/:id", (req, res) => 41 | res.json(orders.find((order) => order.id === req.params.id)) 42 | ); 43 | 44 | //Client side routing fix on page refresh or direct browsing to non-root directory 45 | app.get("/*", (req, res) => { 46 | res.sendFile(path.join(__dirname, "..", "public", "index.html"), (err) => { 47 | if (err) { 48 | res.status(500).send(err); 49 | } 50 | }); 51 | }); 52 | 53 | //Start the server 54 | app.listen(port, () => console.log(`Monolith listening on port ${port}!`)); 55 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "lockfileVersion": 1 3 | } 4 | -------------------------------------------------------------------------------- /react-app/.env: -------------------------------------------------------------------------------- 1 | REACT_APP_ORDERS_URL=http://localhost:8081/api/orders 2 | REACT_APP_PRODUCTS_URL=http://localhost:8082/api/products -------------------------------------------------------------------------------- /react-app/.env.monolith: -------------------------------------------------------------------------------- 1 | REACT_APP_ORDERS_URL=/service/orders 2 | REACT_APP_PRODUCTS_URL=/service/products -------------------------------------------------------------------------------- /react-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.development.local 17 | .env.test.local 18 | .env.production.local 19 | 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | -------------------------------------------------------------------------------- /react-app/README.md: -------------------------------------------------------------------------------- 1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 2 | 3 | ## Available Scripts 4 | 5 | In the project directory, you can run: 6 | 7 | ### `npm start` 8 | 9 | Runs the app in the development mode.
10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 11 | 12 | The page will reload if you make edits.
13 | You will also see any lint errors in the console. 14 | 15 | ### `npm test` 16 | 17 | Launches the test runner in the interactive watch mode.
18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 19 | 20 | ### `npm run build` 21 | 22 | Builds the app for production to the `build` folder.
23 | It correctly bundles React in production mode and optimizes the build for the best performance. 24 | 25 | The build is minified and the filenames include the hashes.
26 | Your app is ready to be deployed! 27 | 28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 29 | 30 | ### `npm run eject` 31 | 32 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 33 | 34 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 35 | 36 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 37 | 38 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 39 | 40 | ## Learn More 41 | 42 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 43 | 44 | To learn React, check out the [React documentation](https://reactjs.org/). 45 | 46 | ### Code Splitting 47 | 48 | This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting 49 | 50 | ### Analyzing the Bundle Size 51 | 52 | This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size 53 | 54 | ### Making a Progressive Web App 55 | 56 | This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app 57 | 58 | ### Advanced Configuration 59 | 60 | This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration 61 | 62 | ### Deployment 63 | 64 | This section has moved here: https://facebook.github.io/create-react-app/docs/deployment 65 | 66 | ### `npm run build` fails to minify 67 | 68 | This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify 69 | -------------------------------------------------------------------------------- /react-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.7.1", 7 | "@emotion/styled": "^11.6.0", 8 | "@mui/material": "^5.3.1", 9 | "@mui/styles": "^5.3.0", 10 | "env-cmd": "^10.1.0", 11 | "express": "^4.21.0", 12 | "react": "^17.0.2", 13 | "react-dom": "^17.0.2", 14 | "react-router-dom": "^5.3.0", 15 | "react-scripts": "^5.0.0" 16 | }, 17 | "scripts": { 18 | "start": "react-scripts start", 19 | "prebuild": "npm run build:monolith", 20 | "build": "react-scripts build", 21 | "postbuild": "node scripts/post-build.js ./build ../microservices/src/frontend/public", 22 | "build:monolith": "env-cmd -f .env.monolith react-scripts build", 23 | "postbuild:monolith": "node scripts/post-build.js ./build ../monolith/public", 24 | "test": "react-scripts test", 25 | "eject": "react-scripts eject" 26 | }, 27 | "eslintConfig": { 28 | "extends": "react-app" 29 | }, 30 | "browserslist": { 31 | "production": [ 32 | ">0.2%", 33 | "not dead", 34 | "not op_mini all" 35 | ], 36 | "development": [ 37 | "last 1 chrome version", 38 | "last 1 firefox version", 39 | "last 1 safari version" 40 | ] 41 | }, 42 | "devDependencies": { 43 | "ncp": "^2.0.0", 44 | "rimraf": "^3.0.2" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /react-app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | Fancy Store 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /react-app/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /react-app/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /react-app/public/static/img/products/air-plant.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecodelabs/monolith-to-microservices/deeb3099f6a29c0ec8b92a20013fdc94f69f0d47/react-app/public/static/img/products/air-plant.jpg -------------------------------------------------------------------------------- /react-app/public/static/img/products/barista-kit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecodelabs/monolith-to-microservices/deeb3099f6a29c0ec8b92a20013fdc94f69f0d47/react-app/public/static/img/products/barista-kit.jpg -------------------------------------------------------------------------------- /react-app/public/static/img/products/camera-lens.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecodelabs/monolith-to-microservices/deeb3099f6a29c0ec8b92a20013fdc94f69f0d47/react-app/public/static/img/products/camera-lens.jpg -------------------------------------------------------------------------------- /react-app/public/static/img/products/camp-mug.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecodelabs/monolith-to-microservices/deeb3099f6a29c0ec8b92a20013fdc94f69f0d47/react-app/public/static/img/products/camp-mug.jpg -------------------------------------------------------------------------------- /react-app/public/static/img/products/city-bike.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecodelabs/monolith-to-microservices/deeb3099f6a29c0ec8b92a20013fdc94f69f0d47/react-app/public/static/img/products/city-bike.jpg -------------------------------------------------------------------------------- /react-app/public/static/img/products/credits.txt: -------------------------------------------------------------------------------- 1 | film-camera.jpg,CC0 Public Domain,https://pxhere.com/en/photo/829555 2 | camera-lens.jpg,CC0 Public Domain,https://pxhere.com/en/photo/670041 3 | air-plant.jpg,,https://unsplash.com/photos/uUwEAW5jFLE 4 | camp-mug.jpg,,https://unsplash.com/photos/h9VhRlMfVkg 5 | record-player.jpg,,https://unsplash.com/photos/pEEHFSX1vak 6 | city-bike.jpg,,https://unsplash.com/photos/Lpe9u9etwMU 7 | typewriter.jpg,,https://unsplash.com/photos/mk7D-4UCfmg 8 | barista-kit.jpg,,https://unsplash.com/photos/ZiRyGGIpRCw 9 | terrarium.jpg,,https://unsplash.com/photos/E9QYLj0724Y 10 | -------------------------------------------------------------------------------- /react-app/public/static/img/products/film-camera.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecodelabs/monolith-to-microservices/deeb3099f6a29c0ec8b92a20013fdc94f69f0d47/react-app/public/static/img/products/film-camera.jpg -------------------------------------------------------------------------------- /react-app/public/static/img/products/record-player.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecodelabs/monolith-to-microservices/deeb3099f6a29c0ec8b92a20013fdc94f69f0d47/react-app/public/static/img/products/record-player.jpg -------------------------------------------------------------------------------- /react-app/public/static/img/products/terrarium.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecodelabs/monolith-to-microservices/deeb3099f6a29c0ec8b92a20013fdc94f69f0d47/react-app/public/static/img/products/terrarium.jpg -------------------------------------------------------------------------------- /react-app/public/static/img/products/typewriter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlecodelabs/monolith-to-microservices/deeb3099f6a29c0ec8b92a20013fdc94f69f0d47/react-app/public/static/img/products/typewriter.jpg -------------------------------------------------------------------------------- /react-app/scripts/post-build.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | const path = require("path"); 17 | const ncp = require("ncp"); 18 | const rimraf = require("rimraf"); 19 | 20 | if(process.argv.length < 4){ 21 | console.error("Invalid arguments, two arguments are required "); 22 | } 23 | 24 | //const sourceFolder = path.join(__dirname, "..", "build"); 25 | //const destFolder = path.join(__dirname, "..", "..", "..", "monolith", "public"); 26 | 27 | const sourceFolder = process.argv[2]; 28 | const destFolder = process.argv[3]; 29 | 30 | console.log(`Deleting stale folder: ${destFolder}`); 31 | 32 | rimraf(destFolder, err => { 33 | if (err) { 34 | console.log(`Failed to delete stale destination folder: ${destFolder}`); 35 | return; 36 | } 37 | console.log(`Deleted stale destination folder: ${destFolder}`); 38 | 39 | console.log(`Copying files from ${sourceFolder} to ${destFolder}`) 40 | 41 | ncp(sourceFolder, destFolder, err => { 42 | if (err) { 43 | return console.error(`Failed to copy ${sourceFolder} to ${destFolder}!`); 44 | } 45 | console.log(`Copied ${sourceFolder} to ${destFolder} successfully!`); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /react-app/src/App.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | import React from "react"; 18 | 19 | import ClippedDrawer from "./components/ClippedDrawer"; 20 | 21 | function App() { 22 | return ; 23 | } 24 | 25 | export default App; 26 | -------------------------------------------------------------------------------- /react-app/src/components/ClippedDrawer/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | import React from "react"; 17 | import { 18 | Drawer, 19 | AppBar, 20 | CssBaseline, 21 | Toolbar, 22 | List, 23 | Typography, 24 | ListItem, 25 | ListItemText, 26 | Box, 27 | } from "@mui/material"; 28 | 29 | import { 30 | BrowserRouter as Router, 31 | Route, 32 | Switch, 33 | NavLink, 34 | } from "react-router-dom"; 35 | 36 | //Import Pages 37 | import Home from "../../pages/Home"; 38 | import Products from "../../pages/Products"; 39 | import Orders from "../../pages/Orders"; 40 | import OrderDetails from "../../pages/OrderDetails"; 41 | import NotFound from "../../pages/NotFound"; 42 | 43 | const drawerWidth = 200; 44 | 45 | export default function ClippedDrawer() { 46 | return ( 47 | 48 | 49 | 50 | theme.zIndex.drawer + 1, 54 | }} 55 | > 56 | 57 | 58 | Fancy Store 59 | 60 | 61 | 62 | 73 | 74 | 75 | 82 | 83 | {" "} 84 | 91 | 92 | {" "} 93 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | ); 126 | } 127 | -------------------------------------------------------------------------------- /react-app/src/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | import React from 'react'; 17 | import ReactDOM from 'react-dom'; 18 | import App from './App'; 19 | 20 | ReactDOM.render(, document.getElementById('root')); -------------------------------------------------------------------------------- /react-app/src/pages/Home/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | import React from "react"; 17 | import { Box, Paper, Typography } from "@mui/material"; 18 | 19 | export default function Home() { 20 | return ( 21 | 22 | theme.spacing(3, 2), 28 | }} 29 | > 30 | Welcome to the Fancy Store! 31 |
32 | 33 | Take a look at our wide variety of products. 34 | 35 |
36 |
37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /react-app/src/pages/Home/index.js.new: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | import React from "react"; 17 | import { Box, Paper, Typography } from "@mui/material"; 18 | 19 | export default function Home() { 20 | return ( 21 | 22 | theme.spacing(3, 2), 28 | }} 29 | > 30 | Fancy Fashion & Style Online 31 |
32 | 33 | Tired of mainstream fashion ideas, popular trends and societal norms? 34 | This line of lifestyle products will help you catch up with the Fancy 35 | trend and express your personal style. Start shopping Fancy items now! 36 | 37 |
38 |
39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /react-app/src/pages/NotFound/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | import React from "react"; 17 | import { Box, Paper, Typography } from "@mui/material"; 18 | 19 | export default function Orders() { 20 | return ( 21 | 22 | theme.spacing(3, 2) }}> 23 | Page not found 24 | 25 | 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /react-app/src/pages/OrderDetails/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | import React, { useState, useEffect } from "react"; 17 | import { useRouteMatch } from "react-router-dom"; 18 | import { Box, Paper, Grid, Typography } from "@mui/material"; 19 | 20 | export default function OrderDetails() { 21 | const match = useRouteMatch(); 22 | 23 | const [hasErrors, setErrors] = useState(false); 24 | const [order, setOrder] = useState({}); 25 | 26 | const orderId = match.params.id; 27 | 28 | async function fetchOrder(orderId) { 29 | try { 30 | const response = await fetch( 31 | `${process.env.REACT_APP_ORDERS_URL}/${orderId}` 32 | ); 33 | const order = await response.json(); 34 | setOrder(order); 35 | } catch (err) { 36 | setErrors(true); 37 | } 38 | } 39 | 40 | useEffect(() => { 41 | fetchOrder(orderId); 42 | }, [orderId]); 43 | 44 | return ( 45 | 46 | {hasErrors && ( 47 | theme.spacing(3, 2), 52 | }} 53 | > 54 | 55 | An error has occurred, please try reloading the page. 56 | 57 | 58 | )} 59 | {!hasErrors && ( 60 | theme.spacing(3, 2), 66 | }} 67 | > 68 | 74 | 75 | {order.id} 76 | 77 | 78 | 79 | Date: 80 | {order.date} 81 | 82 | 83 | Cost: ${order.cost} 84 | 85 | 86 | 87 | 88 | Order Items: 89 | 90 | {order.items && 91 | order.items.map((item) => ( 92 | {item} 93 | ))} 94 | 95 | 96 | 97 | )} 98 | 99 | ); 100 | } 101 | -------------------------------------------------------------------------------- /react-app/src/pages/Orders/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | import React, { useState, useEffect } from "react"; 17 | import { useHistory } from "react-router-dom"; 18 | import { 19 | Box, 20 | Table, 21 | TableBody, 22 | TableCell, 23 | TableHead, 24 | TableRow, 25 | Paper, 26 | Typography, 27 | } from "@mui/material"; 28 | 29 | export default function Orders() { 30 | const history = useHistory(); 31 | 32 | const [hasErrors, setErrors] = useState(false); 33 | const [orders, setOrders] = useState([]); 34 | 35 | async function fetchOrders() { 36 | try { 37 | const response = await fetch(`${process.env.REACT_APP_ORDERS_URL}`); 38 | const orders = await response.json(); 39 | setOrders(orders); 40 | } catch (err) { 41 | setErrors(true); 42 | } 43 | } 44 | 45 | useEffect(() => { 46 | fetchOrders(); 47 | }, []); 48 | 49 | return ( 50 | 51 | {hasErrors && ( 52 | theme.spacing(3, 2), 57 | }} 58 | > 59 | 60 | An error has occurred, please try reloading the page. 61 | 62 | 63 | )} 64 | {!hasErrors && ( 65 | theme.spacing(3, 2), 71 | }} 72 | > 73 | Orders 74 | 75 | 76 | 77 | Order Id 78 | Date 79 | Total Items 80 | Cost 81 | 82 | 83 | 84 | {orders.map((order) => ( 85 | { 90 | history.push(`/orders/${order.id}`); 91 | }} 92 | > 93 | 94 | {order.id} 95 | 96 | {order.date} 97 | 98 | {(order.items && order.items.length) || 0} 99 | 100 | ${order.cost} 101 | 102 | ))} 103 | 104 |
105 |
106 | )} 107 |
108 | ); 109 | } 110 | -------------------------------------------------------------------------------- /react-app/src/pages/Products/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 Google LLC 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | https://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | import React, { useState, useEffect } from "react"; 17 | import { 18 | Box, 19 | Paper, 20 | Card, 21 | CardMedia, 22 | CardContent, 23 | Grid, 24 | Typography, 25 | } from "@mui/material"; 26 | 27 | export default function Products() { 28 | const [hasErrors, setErrors] = useState(false); 29 | const [products, setProducts] = useState([]); 30 | 31 | async function fetchData() { 32 | try { 33 | const response = await fetch(`${process.env.REACT_APP_PRODUCTS_URL}`); 34 | const products = await response.json(); 35 | setProducts(products); 36 | } catch (err) { 37 | setErrors(true); 38 | } 39 | } 40 | 41 | useEffect(() => { 42 | fetchData(); 43 | }, []); 44 | 45 | return ( 46 | 47 | {hasErrors && ( 48 | theme.spacing(3, 2), 53 | }} 54 | > 55 | 56 | An error has occurred, please try reloading the page. 57 | 58 | 59 | )} 60 | {!hasErrors && ( 61 | 68 | {products.map((product) => { 69 | return ( 70 | 71 | 72 | 77 | 78 | 79 | {product.name} - ${product.cost} 80 | 81 | 82 | 83 | 84 | ); 85 | })} 86 | 87 | )} 88 | 89 | ); 90 | } 91 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2019 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eEo pipefail 18 | 19 | if [ -z "$CLOUD_SHELL" ]; then 20 | printf "Checking for required npm version...\n" 21 | 22 | npm install -g npm > /dev/null 2>&1 23 | printf "Completed.\n\n" 24 | 25 | printf "Setting up NVM...\n" 26 | export NVM_DIR="/usr/local/nvm" 27 | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm 28 | [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion 29 | printf "Completed.\n\n" 30 | 31 | printf "Updating nodeJS version...\n" 32 | nvm install --lts 33 | printf "Completed.\n\n" 34 | fi 35 | 36 | printf "Installing monolith dependencies...\n" 37 | cd ./monolith 38 | npm install 39 | printf "Completed.\n\n" 40 | 41 | printf "Installing microservices dependencies...\n" 42 | cd ../microservices 43 | npm install 44 | printf "Completed.\n\n" 45 | 46 | printf "Installing React app dependencies...\n" 47 | cd ../react-app 48 | npm install 49 | printf "Completed.\n\n" 50 | 51 | printf "Building React app and placing into sub projects...\n" 52 | npm run build 53 | printf "Completed.\n\n" 54 | 55 | printf "Setup completed successfully!\n" 56 | 57 | if [ -z "$CLOUD_SHELL" ]; then 58 | printf "\n" 59 | printf "###############################################################################\n" 60 | printf "# NOTICE #\n" 61 | printf "# #\n" 62 | printf "# Make sure you have a compatible nodeJS version with the following command: #\n" 63 | printf "# #\n" 64 | printf "# nvm install --lts #\n" 65 | printf "# #\n" 66 | printf "###############################################################################\n" 67 | fi 68 | --------------------------------------------------------------------------------