Merge branch 'prismaHealth' into 'main'
add health check rest service See merge request v3/service/auth!30
This commit is contained in:
		
						commit
						49e7027987
					
				| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
# SERVICE
 | 
			
		||||
SERVICE_URL=0.0.0.0
 | 
			
		||||
SERVICE_PORT=5002
 | 
			
		||||
HEALTH_SERVICE_PORT=6002
 | 
			
		||||
 | 
			
		||||
# PRISMA
 | 
			
		||||
DATABASE_URL="postgresql://mobicoop:mobicoop@v3-db:5432/mobicoop?schema=auth"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,7 @@ services:
 | 
			
		|||
    command: npm run start:dev
 | 
			
		||||
    ports:
 | 
			
		||||
      - ${SERVICE_PORT:-5002}:${SERVICE_PORT:-5002}
 | 
			
		||||
      - ${HEALTH_SERVICE_PORT:-6002}:${HEALTH_SERVICE_PORT:-6002}
 | 
			
		||||
    networks:
 | 
			
		||||
      v3-network:
 | 
			
		||||
        aliases:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@
 | 
			
		|||
        "@nestjs/cqrs": "^9.0.1",
 | 
			
		||||
        "@nestjs/microservices": "^9.2.1",
 | 
			
		||||
        "@nestjs/platform-express": "^9.0.0",
 | 
			
		||||
        "@nestjs/terminus": "^9.2.2",
 | 
			
		||||
        "@prisma/client": "^4.7.1",
 | 
			
		||||
        "axios": "^1.2.2",
 | 
			
		||||
        "bcrypt": "^5.1.0",
 | 
			
		||||
| 
						 | 
				
			
			@ -2052,6 +2053,71 @@
 | 
			
		|||
      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@nestjs/terminus": {
 | 
			
		||||
      "version": "9.2.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@nestjs/terminus/-/terminus-9.2.2.tgz",
 | 
			
		||||
      "integrity": "sha512-AWUA8XLcgxWUjUFYHDqi42M7CZn2e+DEWxP+MqNAbMzz4ybB5jGcFK5Fy8qwaNBoWg6KMF1JiXOOygGXgk9ydg==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "boxen": "5.1.2",
 | 
			
		||||
        "check-disk-space": "3.3.1"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "@grpc/grpc-js": "*",
 | 
			
		||||
        "@grpc/proto-loader": "*",
 | 
			
		||||
        "@mikro-orm/core": "*",
 | 
			
		||||
        "@mikro-orm/nestjs": "*",
 | 
			
		||||
        "@nestjs/axios": "*",
 | 
			
		||||
        "@nestjs/common": "9.x",
 | 
			
		||||
        "@nestjs/core": "9.x",
 | 
			
		||||
        "@nestjs/microservices": "*",
 | 
			
		||||
        "@nestjs/mongoose": "*",
 | 
			
		||||
        "@nestjs/sequelize": "*",
 | 
			
		||||
        "@nestjs/typeorm": "*",
 | 
			
		||||
        "mongoose": "*",
 | 
			
		||||
        "reflect-metadata": "0.1.x",
 | 
			
		||||
        "rxjs": "7.x",
 | 
			
		||||
        "sequelize": "*",
 | 
			
		||||
        "typeorm": "*"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependenciesMeta": {
 | 
			
		||||
        "@grpc/grpc-js": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "@grpc/proto-loader": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "@mikro-orm/core": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "@mikro-orm/nestjs": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "@nestjs/axios": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "@nestjs/microservices": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "@nestjs/mongoose": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "@nestjs/sequelize": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "@nestjs/typeorm": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "mongoose": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "sequelize": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "typeorm": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@nestjs/testing": {
 | 
			
		||||
      "version": "9.2.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-9.2.1.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -3057,6 +3123,14 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
 | 
			
		||||
      "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/ansi-align": {
 | 
			
		||||
      "version": "3.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
 | 
			
		||||
      "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "string-width": "^4.1.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/ansi-colors": {
 | 
			
		||||
      "version": "4.1.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -3461,6 +3535,53 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/boxen": {
 | 
			
		||||
      "version": "5.1.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz",
 | 
			
		||||
      "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "ansi-align": "^3.0.0",
 | 
			
		||||
        "camelcase": "^6.2.0",
 | 
			
		||||
        "chalk": "^4.1.0",
 | 
			
		||||
        "cli-boxes": "^2.2.1",
 | 
			
		||||
        "string-width": "^4.2.2",
 | 
			
		||||
        "type-fest": "^0.20.2",
 | 
			
		||||
        "widest-line": "^3.1.0",
 | 
			
		||||
        "wrap-ansi": "^7.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=10"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "url": "https://github.com/sponsors/sindresorhus"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/boxen/node_modules/camelcase": {
 | 
			
		||||
      "version": "6.3.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=10"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "url": "https://github.com/sponsors/sindresorhus"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/boxen/node_modules/chalk": {
 | 
			
		||||
      "version": "4.1.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
 | 
			
		||||
      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "ansi-styles": "^4.1.0",
 | 
			
		||||
        "supports-color": "^7.1.0"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=10"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "url": "https://github.com/chalk/chalk?sponsor=1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/brace-expansion": {
 | 
			
		||||
      "version": "1.1.11",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -3658,6 +3779,14 @@
 | 
			
		|||
      "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/check-disk-space": {
 | 
			
		||||
      "version": "3.3.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/check-disk-space/-/check-disk-space-3.3.1.tgz",
 | 
			
		||||
      "integrity": "sha512-iOrT8yCZjSnyNZ43476FE2rnssvgw5hnuwOM0hm8Nj1qa0v4ieUUEbCyxxsEliaoDUb/75yCOL71zkDiDBLbMQ==",
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=12"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/chokidar": {
 | 
			
		||||
      "version": "3.5.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -3732,6 +3861,17 @@
 | 
			
		|||
        "validator": "^13.7.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/cli-boxes": {
 | 
			
		||||
      "version": "2.2.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz",
 | 
			
		||||
      "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==",
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=6"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "url": "https://github.com/sponsors/sindresorhus"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/cli-cursor": {
 | 
			
		||||
      "version": "3.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -8845,7 +8985,6 @@
 | 
			
		|||
      "version": "0.20.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
 | 
			
		||||
      "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=10"
 | 
			
		||||
      },
 | 
			
		||||
| 
						 | 
				
			
			@ -9135,6 +9274,17 @@
 | 
			
		|||
        "string-width": "^1.0.2 || 2 || 3 || 4"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/widest-line": {
 | 
			
		||||
      "version": "3.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
 | 
			
		||||
      "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "string-width": "^4.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=8"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/windows-release": {
 | 
			
		||||
      "version": "4.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-4.0.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -10788,6 +10938,15 @@
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@nestjs/terminus": {
 | 
			
		||||
      "version": "9.2.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@nestjs/terminus/-/terminus-9.2.2.tgz",
 | 
			
		||||
      "integrity": "sha512-AWUA8XLcgxWUjUFYHDqi42M7CZn2e+DEWxP+MqNAbMzz4ybB5jGcFK5Fy8qwaNBoWg6KMF1JiXOOygGXgk9ydg==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "boxen": "5.1.2",
 | 
			
		||||
        "check-disk-space": "3.3.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@nestjs/testing": {
 | 
			
		||||
      "version": "9.2.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-9.2.1.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -11614,6 +11773,14 @@
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "ansi-align": {
 | 
			
		||||
      "version": "3.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
 | 
			
		||||
      "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "string-width": "^4.1.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "ansi-colors": {
 | 
			
		||||
      "version": "4.1.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -11936,6 +12103,37 @@
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "boxen": {
 | 
			
		||||
      "version": "5.1.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz",
 | 
			
		||||
      "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "ansi-align": "^3.0.0",
 | 
			
		||||
        "camelcase": "^6.2.0",
 | 
			
		||||
        "chalk": "^4.1.0",
 | 
			
		||||
        "cli-boxes": "^2.2.1",
 | 
			
		||||
        "string-width": "^4.2.2",
 | 
			
		||||
        "type-fest": "^0.20.2",
 | 
			
		||||
        "widest-line": "^3.1.0",
 | 
			
		||||
        "wrap-ansi": "^7.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "camelcase": {
 | 
			
		||||
          "version": "6.3.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
 | 
			
		||||
          "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="
 | 
			
		||||
        },
 | 
			
		||||
        "chalk": {
 | 
			
		||||
          "version": "4.1.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
 | 
			
		||||
          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "ansi-styles": "^4.1.0",
 | 
			
		||||
            "supports-color": "^7.1.0"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "brace-expansion": {
 | 
			
		||||
      "version": "1.1.11",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -12066,6 +12264,11 @@
 | 
			
		|||
      "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "check-disk-space": {
 | 
			
		||||
      "version": "3.3.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/check-disk-space/-/check-disk-space-3.3.1.tgz",
 | 
			
		||||
      "integrity": "sha512-iOrT8yCZjSnyNZ43476FE2rnssvgw5hnuwOM0hm8Nj1qa0v4ieUUEbCyxxsEliaoDUb/75yCOL71zkDiDBLbMQ=="
 | 
			
		||||
    },
 | 
			
		||||
    "chokidar": {
 | 
			
		||||
      "version": "3.5.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -12120,6 +12323,11 @@
 | 
			
		|||
        "validator": "^13.7.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "cli-boxes": {
 | 
			
		||||
      "version": "2.2.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz",
 | 
			
		||||
      "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw=="
 | 
			
		||||
    },
 | 
			
		||||
    "cli-cursor": {
 | 
			
		||||
      "version": "3.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -15901,8 +16109,7 @@
 | 
			
		|||
    "type-fest": {
 | 
			
		||||
      "version": "0.20.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
 | 
			
		||||
      "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
      "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="
 | 
			
		||||
    },
 | 
			
		||||
    "type-is": {
 | 
			
		||||
      "version": "1.6.18",
 | 
			
		||||
| 
						 | 
				
			
			@ -16109,6 +16316,14 @@
 | 
			
		|||
        "string-width": "^1.0.2 || 2 || 3 || 4"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "widest-line": {
 | 
			
		||||
      "version": "3.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
 | 
			
		||||
      "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "string-width": "^4.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "windows-release": {
 | 
			
		||||
      "version": "4.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-4.0.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,6 +43,7 @@
 | 
			
		|||
    "@nestjs/cqrs": "^9.0.1",
 | 
			
		||||
    "@nestjs/microservices": "^9.2.1",
 | 
			
		||||
    "@nestjs/platform-express": "^9.0.0",
 | 
			
		||||
    "@nestjs/terminus": "^9.2.2",
 | 
			
		||||
    "@prisma/client": "^4.7.1",
 | 
			
		||||
    "axios": "^1.2.2",
 | 
			
		||||
    "bcrypt": "^5.1.0",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										46
									
								
								src/main.ts
								
								
								
								
							
							
						
						
									
										46
									
								
								src/main.ts
								
								
								
								
							| 
						 | 
				
			
			@ -4,28 +4,30 @@ import { join } from 'path';
 | 
			
		|||
import { AppModule } from './app.module';
 | 
			
		||||
 | 
			
		||||
async function bootstrap() {
 | 
			
		||||
  const app = await NestFactory.createMicroservice<MicroserviceOptions>(
 | 
			
		||||
    AppModule,
 | 
			
		||||
    {
 | 
			
		||||
      transport: Transport.GRPC,
 | 
			
		||||
      options: {
 | 
			
		||||
        package: ['authentication', 'authorization', 'health'],
 | 
			
		||||
        protoPath: [
 | 
			
		||||
          join(
 | 
			
		||||
            __dirname,
 | 
			
		||||
            'modules/authentication/adapters/primaries/authentication.proto',
 | 
			
		||||
          ),
 | 
			
		||||
          join(
 | 
			
		||||
            __dirname,
 | 
			
		||||
            'modules/authorization/adapters/primaries/authorization.proto',
 | 
			
		||||
          ),
 | 
			
		||||
          join(__dirname, 'modules/health/adapters/primaries/health.proto'),
 | 
			
		||||
        ],
 | 
			
		||||
        url: process.env.SERVICE_URL + ':' + process.env.SERVICE_PORT,
 | 
			
		||||
        loader: { keepCase: true, enums: String },
 | 
			
		||||
      },
 | 
			
		||||
  const app = await NestFactory.create(AppModule);
 | 
			
		||||
  app.connectMicroservice<MicroserviceOptions>({
 | 
			
		||||
    transport: Transport.TCP,
 | 
			
		||||
  });
 | 
			
		||||
  app.connectMicroservice<MicroserviceOptions>({
 | 
			
		||||
    transport: Transport.GRPC,
 | 
			
		||||
    options: {
 | 
			
		||||
      package: ['authentication', 'authorization', 'health'],
 | 
			
		||||
      protoPath: [
 | 
			
		||||
        join(
 | 
			
		||||
          __dirname,
 | 
			
		||||
          'modules/authentication/adapters/primaries/authentication.proto',
 | 
			
		||||
        ),
 | 
			
		||||
        join(
 | 
			
		||||
          __dirname,
 | 
			
		||||
          'modules/authorization/adapters/primaries/authorization.proto',
 | 
			
		||||
        ),
 | 
			
		||||
        join(__dirname, 'modules/health/adapters/primaries/health.proto'),
 | 
			
		||||
      ],
 | 
			
		||||
      url: process.env.SERVICE_URL + ':' + process.env.SERVICE_PORT,
 | 
			
		||||
      loader: { keepCase: true, enums: String },
 | 
			
		||||
    },
 | 
			
		||||
  );
 | 
			
		||||
  await app.listen();
 | 
			
		||||
  });
 | 
			
		||||
  await app.startAllMicroservices();
 | 
			
		||||
  await app.listen(process.env.HEALTH_SERVICE_PORT);
 | 
			
		||||
}
 | 
			
		||||
bootstrap();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -180,4 +180,21 @@ export abstract class PrismaRepository<T> implements IRepository<T> {
 | 
			
		|||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async healthCheck(): Promise<boolean> {
 | 
			
		||||
    try {
 | 
			
		||||
      await this._prisma.$queryRaw`SELECT 1`;
 | 
			
		||||
      return true;
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      if (e instanceof PrismaClientKnownRequestError) {
 | 
			
		||||
        throw new DatabaseException(
 | 
			
		||||
          PrismaClientKnownRequestError.name,
 | 
			
		||||
          e.code,
 | 
			
		||||
          e.message,
 | 
			
		||||
        );
 | 
			
		||||
      } else {
 | 
			
		||||
        throw new DatabaseException();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,6 +57,23 @@ const mockPrismaService = {
 | 
			
		|||
 | 
			
		||||
    return Promise.resolve([fakeEntities, fakeEntities.length]);
 | 
			
		||||
  }),
 | 
			
		||||
  $queryRaw: jest
 | 
			
		||||
    .fn()
 | 
			
		||||
    .mockImplementationOnce(() => {
 | 
			
		||||
      throw new PrismaClientKnownRequestError('unknown request', {
 | 
			
		||||
        code: 'code',
 | 
			
		||||
        clientVersion: 'version',
 | 
			
		||||
      });
 | 
			
		||||
    })
 | 
			
		||||
    .mockImplementationOnce(() => {
 | 
			
		||||
      return true;
 | 
			
		||||
    })
 | 
			
		||||
    .mockImplementation(() => {
 | 
			
		||||
      throw new PrismaClientKnownRequestError('Database unavailable', {
 | 
			
		||||
        code: 'code',
 | 
			
		||||
        clientVersion: 'version',
 | 
			
		||||
      });
 | 
			
		||||
    }),
 | 
			
		||||
  fake: {
 | 
			
		||||
    create: jest
 | 
			
		||||
      .fn()
 | 
			
		||||
| 
						 | 
				
			
			@ -422,4 +439,23 @@ describe('PrismaRepository', () => {
 | 
			
		|||
      ).rejects.toBeInstanceOf(DatabaseException);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('healthCheck', () => {
 | 
			
		||||
    it('should throw a DatabaseException for client error', async () => {
 | 
			
		||||
      await expect(fakeRepository.healthCheck()).rejects.toBeInstanceOf(
 | 
			
		||||
        DatabaseException,
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should return a healthy result', async () => {
 | 
			
		||||
      const res = await fakeRepository.healthCheck();
 | 
			
		||||
      expect(res).toBeTruthy();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should throw an exception if database is not available', async () => {
 | 
			
		||||
      await expect(fakeRepository.healthCheck()).rejects.toBeInstanceOf(
 | 
			
		||||
        DatabaseException,
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
import { Controller } from '@nestjs/common';
 | 
			
		||||
import { GrpcMethod } from '@nestjs/microservices';
 | 
			
		||||
import { PrismaHealthIndicatorUseCase } from '../../domain/usecases/prisma.health-indicator.usecase';
 | 
			
		||||
 | 
			
		||||
enum ServingStatus {
 | 
			
		||||
  UNKNOWN = 0,
 | 
			
		||||
  SERVING = 1,
 | 
			
		||||
  NOT_SERVING = 2,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface HealthCheckRequest {
 | 
			
		||||
  service: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface HealthCheckResponse {
 | 
			
		||||
  status: ServingStatus;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// this controller responds to gRPC health check service
 | 
			
		||||
@Controller()
 | 
			
		||||
export class HealthServerController {
 | 
			
		||||
  constructor(
 | 
			
		||||
    private readonly _prismaHealthIndicatorUseCase: PrismaHealthIndicatorUseCase,
 | 
			
		||||
  ) {}
 | 
			
		||||
 | 
			
		||||
  @GrpcMethod('Health', 'Check')
 | 
			
		||||
  async check(
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | 
			
		||||
    data: HealthCheckRequest,
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | 
			
		||||
    metadata: any,
 | 
			
		||||
  ): Promise<HealthCheckResponse> {
 | 
			
		||||
    const healthCheck = await this._prismaHealthIndicatorUseCase.isHealthy(
 | 
			
		||||
      'prisma',
 | 
			
		||||
    );
 | 
			
		||||
    return {
 | 
			
		||||
      status:
 | 
			
		||||
        healthCheck['prisma'].status == 'up'
 | 
			
		||||
          ? ServingStatus.SERVING
 | 
			
		||||
          : ServingStatus.NOT_SERVING,
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,27 +1,35 @@
 | 
			
		|||
import { Controller } from '@nestjs/common';
 | 
			
		||||
import { GrpcMethod } from '@nestjs/microservices';
 | 
			
		||||
import { Controller, Get } from '@nestjs/common';
 | 
			
		||||
import {
 | 
			
		||||
  HealthCheckService,
 | 
			
		||||
  HealthCheck,
 | 
			
		||||
  HealthCheckResult,
 | 
			
		||||
} from '@nestjs/terminus';
 | 
			
		||||
import { Messager } from '../secondaries/messager';
 | 
			
		||||
import { PrismaHealthIndicatorUseCase } from '../../domain/usecases/prisma.health-indicator.usecase';
 | 
			
		||||
 | 
			
		||||
enum ServingStatus {
 | 
			
		||||
  UNKNOWN = 0,
 | 
			
		||||
  SERVING = 1,
 | 
			
		||||
  NOT_SERVING = 2,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface HealthCheckRequest {
 | 
			
		||||
  service: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface HealthCheckResponse {
 | 
			
		||||
  status: ServingStatus;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Controller()
 | 
			
		||||
// this controller responds to rest GET /health
 | 
			
		||||
@Controller('health')
 | 
			
		||||
export class HealthController {
 | 
			
		||||
  @GrpcMethod('Health', 'Check')
 | 
			
		||||
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | 
			
		||||
  check(data: HealthCheckRequest, metadata: any): HealthCheckResponse {
 | 
			
		||||
    return {
 | 
			
		||||
      status: ServingStatus.SERVING,
 | 
			
		||||
    };
 | 
			
		||||
  constructor(
 | 
			
		||||
    private readonly _prismaHealthIndicatorUseCase: PrismaHealthIndicatorUseCase,
 | 
			
		||||
    private _healthCheckService: HealthCheckService,
 | 
			
		||||
    private _messager: Messager,
 | 
			
		||||
  ) {}
 | 
			
		||||
 | 
			
		||||
  @Get()
 | 
			
		||||
  @HealthCheck()
 | 
			
		||||
  async check() {
 | 
			
		||||
    try {
 | 
			
		||||
      return await this._healthCheckService.check([
 | 
			
		||||
        async () => this._prismaHealthIndicatorUseCase.isHealthy('prisma'),
 | 
			
		||||
      ]);
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      const healthCheckResult: HealthCheckResult = error.response;
 | 
			
		||||
      this._messager.publish(
 | 
			
		||||
        'logging.auth.health.crit',
 | 
			
		||||
        JSON.stringify(healthCheckResult.error),
 | 
			
		||||
      );
 | 
			
		||||
      throw error;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
import { Injectable } from '@nestjs/common';
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export abstract class IMessageBroker {
 | 
			
		||||
  exchange: string;
 | 
			
		||||
 | 
			
		||||
  constructor(exchange: string) {
 | 
			
		||||
    this.exchange = exchange;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  abstract publish(routingKey: string, message: string): void;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
 | 
			
		||||
import { Injectable } from '@nestjs/common';
 | 
			
		||||
import { ConfigService } from '@nestjs/config';
 | 
			
		||||
import { IMessageBroker } from './message-broker';
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class Messager extends IMessageBroker {
 | 
			
		||||
  constructor(
 | 
			
		||||
    private readonly _amqpConnection: AmqpConnection,
 | 
			
		||||
    configService: ConfigService,
 | 
			
		||||
  ) {
 | 
			
		||||
    super(configService.get<string>('RMQ_EXCHANGE'));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  publish(routingKey: string, message: string): void {
 | 
			
		||||
    this._amqpConnection.publish(this.exchange, routingKey, message);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
import { Injectable } from '@nestjs/common';
 | 
			
		||||
import {
 | 
			
		||||
  HealthCheckError,
 | 
			
		||||
  HealthIndicator,
 | 
			
		||||
  HealthIndicatorResult,
 | 
			
		||||
} from '@nestjs/terminus';
 | 
			
		||||
import { AuthenticationRepository } from '../../../authentication/adapters/secondaries/authentication.repository';
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class PrismaHealthIndicatorUseCase extends HealthIndicator {
 | 
			
		||||
  constructor(private readonly _repository: AuthenticationRepository) {
 | 
			
		||||
    super();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async isHealthy(key: string): Promise<HealthIndicatorResult> {
 | 
			
		||||
    try {
 | 
			
		||||
      await this._repository.healthCheck();
 | 
			
		||||
      return this.getStatus(key, true);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      throw new HealthCheckError('Prisma', {
 | 
			
		||||
        prisma: e.message,
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,34 @@
 | 
			
		|||
import { Module } from '@nestjs/common';
 | 
			
		||||
import { HealthServerController } from './adapters/primaries/health-server.controller';
 | 
			
		||||
import { PrismaHealthIndicatorUseCase } from './domain/usecases/prisma.health-indicator.usecase';
 | 
			
		||||
import { AuthenticationRepository } from '../authentication/adapters/secondaries/authentication.repository';
 | 
			
		||||
import { DatabaseModule } from '../database/database.module';
 | 
			
		||||
import { HealthController } from './adapters/primaries/health.controller';
 | 
			
		||||
import { TerminusModule } from '@nestjs/terminus';
 | 
			
		||||
import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq';
 | 
			
		||||
import { ConfigModule, ConfigService } from '@nestjs/config';
 | 
			
		||||
import { Messager } from './adapters/secondaries/messager';
 | 
			
		||||
 | 
			
		||||
@Module({
 | 
			
		||||
  controllers: [HealthController],
 | 
			
		||||
  imports: [
 | 
			
		||||
    TerminusModule,
 | 
			
		||||
    RabbitMQModule.forRootAsync(RabbitMQModule, {
 | 
			
		||||
      imports: [ConfigModule],
 | 
			
		||||
      useFactory: async (configService: ConfigService) => ({
 | 
			
		||||
        exchanges: [
 | 
			
		||||
          {
 | 
			
		||||
            name: configService.get<string>('RMQ_EXCHANGE'),
 | 
			
		||||
            type: 'topic',
 | 
			
		||||
          },
 | 
			
		||||
        ],
 | 
			
		||||
        uri: configService.get<string>('RMQ_URI'),
 | 
			
		||||
        connectionInitOptions: { wait: false },
 | 
			
		||||
      }),
 | 
			
		||||
      inject: [ConfigService],
 | 
			
		||||
    }),
 | 
			
		||||
    DatabaseModule,
 | 
			
		||||
  ],
 | 
			
		||||
  controllers: [HealthServerController, HealthController],
 | 
			
		||||
  providers: [PrismaHealthIndicatorUseCase, AuthenticationRepository, Messager],
 | 
			
		||||
})
 | 
			
		||||
export class HealthModule {}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
 | 
			
		||||
import { ConfigService } from '@nestjs/config';
 | 
			
		||||
import { Test, TestingModule } from '@nestjs/testing';
 | 
			
		||||
import { Messager } from '../../adapters/secondaries/messager';
 | 
			
		||||
 | 
			
		||||
const mockAmqpConnection = {
 | 
			
		||||
  publish: jest.fn().mockImplementation(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const mockConfigService = {
 | 
			
		||||
  get: jest.fn().mockResolvedValue({
 | 
			
		||||
    RMQ_EXCHANGE: 'mobicoop',
 | 
			
		||||
  }),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
describe('Messager', () => {
 | 
			
		||||
  let messager: Messager;
 | 
			
		||||
 | 
			
		||||
  beforeAll(async () => {
 | 
			
		||||
    const module: TestingModule = await Test.createTestingModule({
 | 
			
		||||
      imports: [],
 | 
			
		||||
      providers: [
 | 
			
		||||
        Messager,
 | 
			
		||||
        {
 | 
			
		||||
          provide: AmqpConnection,
 | 
			
		||||
          useValue: mockAmqpConnection,
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          provide: ConfigService,
 | 
			
		||||
          useValue: mockConfigService,
 | 
			
		||||
        },
 | 
			
		||||
      ],
 | 
			
		||||
    }).compile();
 | 
			
		||||
 | 
			
		||||
    messager = module.get<Messager>(Messager);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should be defined', () => {
 | 
			
		||||
    expect(messager).toBeDefined();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should publish a message', async () => {
 | 
			
		||||
    jest.spyOn(mockAmqpConnection, 'publish');
 | 
			
		||||
    messager.publish('test.create.info', 'my-test');
 | 
			
		||||
    expect(mockAmqpConnection.publish).toHaveBeenCalledTimes(1);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,58 @@
 | 
			
		|||
import { Test, TestingModule } from '@nestjs/testing';
 | 
			
		||||
import { PrismaHealthIndicatorUseCase } from '../../domain/usecases/prisma.health-indicator.usecase';
 | 
			
		||||
import { AuthenticationRepository } from '../../../authentication/adapters/secondaries/authentication.repository';
 | 
			
		||||
import { PrismaClientKnownRequestError } from '@prisma/client/runtime';
 | 
			
		||||
import { HealthCheckError, HealthIndicatorResult } from '@nestjs/terminus';
 | 
			
		||||
 | 
			
		||||
const mockAuthenticationRepository = {
 | 
			
		||||
  healthCheck: jest
 | 
			
		||||
    .fn()
 | 
			
		||||
    .mockImplementationOnce(() => {
 | 
			
		||||
      return Promise.resolve(true);
 | 
			
		||||
    })
 | 
			
		||||
    .mockImplementation(() => {
 | 
			
		||||
      throw new PrismaClientKnownRequestError('Service unavailable', {
 | 
			
		||||
        code: 'code',
 | 
			
		||||
        clientVersion: 'version',
 | 
			
		||||
      });
 | 
			
		||||
    }),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
describe('PrismaHealthIndicatorUseCase', () => {
 | 
			
		||||
  let prismaHealthIndicatorUseCase: PrismaHealthIndicatorUseCase;
 | 
			
		||||
 | 
			
		||||
  beforeAll(async () => {
 | 
			
		||||
    const module: TestingModule = await Test.createTestingModule({
 | 
			
		||||
      providers: [
 | 
			
		||||
        {
 | 
			
		||||
          provide: AuthenticationRepository,
 | 
			
		||||
          useValue: mockAuthenticationRepository,
 | 
			
		||||
        },
 | 
			
		||||
        PrismaHealthIndicatorUseCase,
 | 
			
		||||
      ],
 | 
			
		||||
    }).compile();
 | 
			
		||||
 | 
			
		||||
    prismaHealthIndicatorUseCase = module.get<PrismaHealthIndicatorUseCase>(
 | 
			
		||||
      PrismaHealthIndicatorUseCase,
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should be defined', () => {
 | 
			
		||||
    expect(prismaHealthIndicatorUseCase).toBeDefined();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('execute', () => {
 | 
			
		||||
    it('should check health successfully', async () => {
 | 
			
		||||
      const healthIndicatorResult: HealthIndicatorResult =
 | 
			
		||||
        await prismaHealthIndicatorUseCase.isHealthy('prisma');
 | 
			
		||||
 | 
			
		||||
      expect(healthIndicatorResult['prisma'].status).toBe('up');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('should throw an error if database is unavailable', async () => {
 | 
			
		||||
      await expect(
 | 
			
		||||
        prismaHealthIndicatorUseCase.isHealthy('prisma'),
 | 
			
		||||
      ).rejects.toBeInstanceOf(HealthCheckError);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
		Loading…
	
		Reference in New Issue