├── .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 |
--------------------------------------------------------------------------------