Compare commits

..

3 Commits

Author SHA1 Message Date
Lauri Võsandi 0c6fbfd924 Switch to Kaniko
continuous-integration/drone Build is passing Details
2022-10-28 07:36:24 +03:00
Erki Aas 939c84c6ab Restore .drone.yml
continuous-integration/drone Build is failing Details
2022-10-11 14:30:29 +00:00
Erki Aas 37117678f0 Delete .drone.yml to force config from develop 2022-10-11 14:28:10 +00:00
46 changed files with 21066 additions and 8690 deletions

View File

@ -1,17 +0,0 @@
.kpt-pipeline/
k8s/
skaffold.yaml
README.md
.git/
node_modules/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.kpt-pipeline

View File

@ -5,12 +5,10 @@ name: default
steps:
- name: backend
image: plugins/docker
image: harbor.k-space.ee/k-space/drone-kaniko
settings:
repo: harbor.k-space.ee/${DRONE_REPO}
repo: ${DRONE_REPO}
registry: harbor.k-space.ee
mtu: 1300
storage_driver: vfs
context: backend/
dockerfile: backend/Dockerfile
username:
@ -18,12 +16,10 @@ steps:
password:
from_secret: docker_password
- name: frontend
image: plugins/docker
image: harbor.k-space.ee/k-space/drone-kaniko
settings:
repo: harbor.k-space.ee/${DRONE_REPO}-frontend
repo: ${DRONE_REPO}-frontend
registry: harbor.k-space.ee
mtu: 1300
storage_driver: vfs
context: frontend/
dockerfile: frontend/Dockerfile
username:

View File

@ -1,5 +1,5 @@
# pull official node image
FROM node AS dev
FROM node
# define /app as working directory
WORKDIR /app
@ -13,8 +13,4 @@ RUN npm install
COPY . /app
# launch node server
ENTRYPOINT npm run dev
# production
FROM dev AS prod
ENTRYPOINT npm run start
ENTRYPOINT node server.js

View File

@ -13,9 +13,6 @@
"express": "^4.17.2",
"minio": "^7.0.26",
"mongodb": "^4.3.1"
},
"devDependencies": {
"nodemon": "^2.0.20"
}
},
"node_modules/@types/node": {
@ -43,12 +40,6 @@
"integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==",
"optional": true
},
"node_modules/abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"dev": true
},
"node_modules/accepts": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
@ -61,19 +52,6 @@
"node": ">= 0.6"
}
},
"node_modules/anymatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
"dev": true,
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
@ -111,12 +89,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@ -136,15 +108,6 @@
}
]
},
"node_modules/binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/block-stream2": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/block-stream2/-/block-stream2-2.1.0.tgz",
@ -178,28 +141,6 @@
"node": ">= 0.8"
}
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"dependencies": {
"fill-range": "^7.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/brorand": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
@ -328,33 +269,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
],
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"engines": {
"node": ">= 8.10.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/cipher-base": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
@ -364,12 +278,6 @@
"safe-buffer": "^5.0.1"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
},
"node_modules/content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
@ -701,18 +609,6 @@
"url": "https://paypal.me/naturalintelligence"
}
},
"node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/finalhandler": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
@ -751,20 +647,6 @@
"node": ">= 0.6"
}
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@ -798,18 +680,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
@ -829,15 +699,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
"dev": true,
"engines": {
"node": ">=4"
}
},
"node_modules/has-symbols": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
@ -940,12 +801,6 @@
}
]
},
"node_modules/ignore-by-default": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
"dev": true
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
@ -1003,18 +858,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"dependencies": {
"binary-extensions": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/is-boolean-object": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
@ -1055,15 +898,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-generator-function": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
@ -1078,18 +912,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"dependencies": {
"is-extglob": "^2.1.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-negative-zero": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
@ -1101,15 +923,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/is-number-object": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz",
@ -1308,18 +1121,6 @@
"resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
"integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
@ -1409,73 +1210,6 @@
"node": ">= 0.6"
}
},
"node_modules/nodemon": {
"version": "2.0.20",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz",
"integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==",
"dev": true,
"dependencies": {
"chokidar": "^3.5.2",
"debug": "^3.2.7",
"ignore-by-default": "^1.0.1",
"minimatch": "^3.1.2",
"pstree.remy": "^1.1.8",
"semver": "^5.7.1",
"simple-update-notifier": "^1.0.7",
"supports-color": "^5.5.0",
"touch": "^3.1.0",
"undefsafe": "^2.0.5"
},
"bin": {
"nodemon": "bin/nodemon.js"
},
"engines": {
"node": ">=8.10.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/nodemon"
}
},
"node_modules/nodemon/node_modules/debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"dependencies": {
"ms": "^2.1.1"
}
},
"node_modules/nodemon/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
"node_modules/nopt": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
"integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
"dev": true,
"dependencies": {
"abbrev": "1"
},
"bin": {
"nopt": "bin/nopt.js"
},
"engines": {
"node": "*"
}
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@ -1568,18 +1302,6 @@
"node": ">=0.12"
}
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@ -1592,12 +1314,6 @@
"node": ">= 0.10"
}
},
"node_modules/pstree.remy": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
"integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
"dev": true
},
"node_modules/public-encrypt": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
@ -1696,18 +1412,6 @@
"node": ">= 6"
}
},
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"dependencies": {
"picomatch": "^2.2.1"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/ripemd160": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
@ -1758,15 +1462,6 @@
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
"node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true,
"bin": {
"semver": "bin/semver"
}
},
"node_modules/send": {
"version": "0.17.2",
"resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz",
@ -1839,27 +1534,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/simple-update-notifier": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz",
"integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==",
"dev": true,
"dependencies": {
"semver": "~7.0.0"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/simple-update-notifier/node_modules/semver": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
"integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
@ -1936,18 +1610,6 @@
"resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
"integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
},
"node_modules/supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"dependencies": {
"has-flag": "^3.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/through2": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz",
@ -1957,18 +1619,6 @@
"readable-stream": "2 || 3"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
@ -1977,18 +1627,6 @@
"node": ">=0.6"
}
},
"node_modules/touch": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
"integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
"dev": true,
"dependencies": {
"nopt": "~1.0.10"
},
"bin": {
"nodetouch": "bin/nodetouch.js"
}
},
"node_modules/tr46": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
@ -2026,12 +1664,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/undefsafe": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
"dev": true
},
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
@ -2191,12 +1823,6 @@
"integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==",
"optional": true
},
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"dev": true
},
"accepts": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
@ -2206,16 +1832,6 @@
"negotiator": "0.6.2"
}
},
"anymatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
"dev": true,
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
}
},
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
@ -2249,23 +1865,11 @@
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw=="
},
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
},
"binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"dev": true
},
"block-stream2": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/block-stream2/-/block-stream2-2.1.0.tgz",
@ -2296,25 +1900,6 @@
"type-is": "~1.6.18"
}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"requires": {
"fill-range": "^7.0.1"
}
},
"brorand": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
@ -2420,22 +2005,6 @@
"get-intrinsic": "^1.0.2"
}
},
"chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
"dev": true,
"requires": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"fsevents": "~2.3.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
}
},
"cipher-base": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
@ -2445,12 +2014,6 @@
"safe-buffer": "^5.0.1"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
},
"content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
@ -2736,15 +2299,6 @@
"strnum": "^1.0.4"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"requires": {
"to-regex-range": "^5.0.1"
}
},
"finalhandler": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
@ -2774,13 +2328,6 @@
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"optional": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@ -2805,15 +2352,6 @@
"get-intrinsic": "^1.1.1"
}
},
"glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
}
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
@ -2827,12 +2365,6 @@
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
"integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA=="
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
"dev": true
},
"has-symbols": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
@ -2900,12 +2432,6 @@
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
},
"ignore-by-default": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
"dev": true
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
@ -2948,15 +2474,6 @@
"has-bigints": "^1.0.1"
}
},
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"requires": {
"binary-extensions": "^2.0.0"
}
},
"is-boolean-object": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
@ -2979,12 +2496,6 @@
"has-tostringtag": "^1.0.0"
}
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true
},
"is-generator-function": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
@ -2993,26 +2504,11 @@
"has-tostringtag": "^1.0.0"
}
},
"is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"requires": {
"is-extglob": "^2.1.1"
}
},
"is-negative-zero": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
"integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA=="
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true
},
"is-number-object": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz",
@ -3156,15 +2652,6 @@
"resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
"integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
},
"minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
@ -3239,56 +2726,6 @@
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"nodemon": {
"version": "2.0.20",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz",
"integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==",
"dev": true,
"requires": {
"chokidar": "^3.5.2",
"debug": "^3.2.7",
"ignore-by-default": "^1.0.1",
"minimatch": "^3.1.2",
"pstree.remy": "^1.1.8",
"semver": "^5.7.1",
"simple-update-notifier": "^1.0.7",
"supports-color": "^5.5.0",
"touch": "^3.1.0",
"undefsafe": "^2.0.5"
},
"dependencies": {
"debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
}
}
},
"nopt": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
"integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
"dev": true,
"requires": {
"abbrev": "1"
}
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@ -3357,12 +2794,6 @@
"sha.js": "^2.4.8"
}
},
"picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true
},
"proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@ -3372,12 +2803,6 @@
"ipaddr.js": "1.9.1"
}
},
"pstree.remy": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
"integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
"dev": true
},
"public-encrypt": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
@ -3456,15 +2881,6 @@
"util-deprecate": "^1.0.1"
}
},
"readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"requires": {
"picomatch": "^2.2.1"
}
},
"ripemd160": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
@ -3498,12 +2914,6 @@
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
},
"send": {
"version": "0.17.2",
"resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz",
@ -3566,23 +2976,6 @@
"object-inspect": "^1.9.0"
}
},
"simple-update-notifier": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz",
"integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==",
"dev": true,
"requires": {
"semver": "~7.0.0"
},
"dependencies": {
"semver": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
"integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
"dev": true
}
}
},
"smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
@ -3642,15 +3035,6 @@
"resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
"integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
},
"through2": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz",
@ -3660,29 +3044,11 @@
"readable-stream": "2 || 3"
}
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"requires": {
"is-number": "^7.0.0"
}
},
"toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
},
"touch": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
"integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
"dev": true,
"requires": {
"nopt": "~1.0.10"
}
},
"tr46": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
@ -3711,12 +3077,6 @@
"which-boxed-primitive": "^1.0.2"
}
},
"undefsafe": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
"dev": true
},
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",

View File

@ -5,8 +5,8 @@
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "nodemon server.js -e ejs,js,css,html,jpg,png,scss",
"prod": "node.js server.js"
"start": "node server.js",
"build": "cd frontend && npm install && npm run build"
},
"keywords": [],
"author": "",
@ -16,8 +16,5 @@
"express": "^4.17.2",
"minio": "^7.0.26",
"mongodb": "^4.3.1"
},
"devDependencies": {
"nodemon": "^2.0.20"
}
}

View File

@ -1,12 +1,21 @@
const { MongoClient, MongoClientOptions } = require("mongodb");
const { MongoClient } = require("mongodb");
const express = require('express');
const minio = require('minio');
/*============== VARIABLE DECLARATION ==============*/
// Mongo set-up variables
const mongoCollection = process.env.MONGO_COLLECTION || 'log';
const mongoUri = process.env.MONGODB_HOST || 'mongodb://127.0.0.1:27017/default?replicaSet=rs0';
const mongoCollection = process.env.MONGO_COLLECTION || 'eventlog';
const mongoUri = process.env.MONGO_URI || 'mongodb://127.0.0.1:27017/default?replicaSet=rs0';
const historyNumber = parseInt(process.env.HISTORY_AMOUNT) || 50;
// Minio set-up variables
const minioAccessKey = process.env.MINIO_ACCESS_KEY || 'kspace-mugshot';
const minioSecretKey = process.env.MINIO_SECRET_KEY || '2mSI6HdbJ8';
const minioHostname = process.env.MINIO_HOSTNAME || '127.0.0.1';
const minioPort = process.env.MINIO_PORT || 9000;
const minioScheme = process.env.MINIO_SCHEME || 'http';
const minioBucket = process.env.MINIO_BUCKET || 'kspace-mugshot';
console.info("Using bucket:", minioBucket);
const historyNumber = parseInt(process.env.HISTORY_AMOUNT) || 10;
// Stream set-up variables
let changeStream;
@ -15,10 +24,8 @@ const pipeline = [];
const PORT = process.env.PORT || 3002;
// Create Mongo client
const mongoOptions = {
readPreference: 'secondaryPreferred'
}
const mongoClient = new MongoClient(mongoUri, mongoOptions);
const mongoClient = new MongoClient(mongoUri);
/*============== CODE ==============*/
async function run() {
@ -31,47 +38,63 @@ async function run() {
changeStream = collection.watch(pipeline, options);
console.log("Started watching changes in database");
const filterOptions = {
'kubernetes.namespace': await collection.distinct('kubernetes.namespace'),
'kubernetes.pod.name': await collection.distinct('kubernetes.pod.name'),
'kubernetes.container.name': await collection.distinct('kubernetes.container.name')
}
const writeMessage = (response, blob) => {
const id = blob._id || null
const message = `id: ${id}\nevent: message\ndata: ${JSON.stringify(blob)}\n\n`
response.write(message)
}
console.log("Minio hostname:", minioHostname);
console.log("Minio port:", minioPort);
console.log("Minio protocol:", minioScheme);
// Triggers on GET at /event route
app.get('/events', async function (request, response) {
let minioClient = new minio.Client({
endPoint: minioHostname,
port: parseInt(minioPort),
useSSL: minioScheme == 'https',
accessKey: minioAccessKey,
secretKey: minioSecretKey
});
// Notify SSE to React
async function wrapEvent(doc) {
let arr = [];
let blob;
if (doc && doc.screenshot_count) {
for (let i = 1; i <= doc.screenshot_count ; i++) {
arr.push({
url: await minioClient.presignedUrl('GET', minioBucket,
`${doc.camera}/${doc._id}/${i}.jpg`, 60 * 60)
});
}
} else if (doc && doc.screenshots) {
for (let j = 0; j < doc.screenshots.length; j++) {
let path = doc.screenshots[j];
arr.push({
url: await minioClient.presignedUrl('GET', minioBucket,
`thumb/${path}`, 60 * 60),
orig: await minioClient.presignedUrl('GET', minioBucket,
`${path}`, 60 * 60)
});
}
};
if (arr.length > 0) {
blob = JSON.stringify({...doc, screenshots: [...arr]});
} else {
blob = JSON.stringify({...doc});
}
return `event: log-entry\ndata: ${blob}\n\n`
}
// Notify SSE to React
const header = { 'Content-Type': 'text/event-stream', 'Connection': 'keep-alive' };
response.writeHead(200, "OK", header);
const message = `id: 1\nevent: filters\ndata: ${JSON.stringify(filterOptions)}\n\n`
response.write(message)
const historyCursor = collection.find().sort({$natural:-1}).limit(historyNumber);
const historyCursor = collection.find()
.sort({$natural:-1})
.limit(historyNumber).toArray().then((res) => {
res.reverse().forEach((document) => {
writeMessage(response, document)
})
});
const changeListener = async (change) => {
// Ignore events without fullDocument, e.g. deletes.
if (change.fullDocument) {
writeMessage(response, change.fullDocument)
}
}
changeStream.on("change", changeListener);
response.on('close', () => {
changeStream.removeListener("change", changeListener)
historyCursor.forEach(async (document) => {
response.write(await wrapEvent(document));
})
changeStream.on("change", async(data) => {
response.write(await wrapEvent(data.fullDocument));
});
});
app.listen(PORT);

View File

@ -1,17 +1,5 @@
.kpt-pipeline/
k8s/
skaffold.yaml
README.md
.git/
node_modules/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.kpt-pipeline
./node_modules
./build
.git
*.md
.gitignore

29
frontend/.gitignore vendored
View File

@ -1,29 +0,0 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.kpt-pipeline

View File

@ -1,22 +1,39 @@
FROM node AS dev
# pull official base image
FROM node AS builder
# set working directory
WORKDIR /app
EXPOSE 8080
COPY package* ./
RUN npm install
COPY . .
ENTRYPOINT ["npm", "run", "dev"]
# install app dependencies
#copies package.json and package-lock.json to Docker environment
COPY package.json ./
# builder
FROM dev AS builder
# Installs all node packages
RUN npm install
# Copies everything over to Docker environment
COPY . ./
RUN npm run build
# serve
FROM nginx AS prod
#Stage 2
#######################################
#pull the official nginx:1.19.0 base image
FROM nginx
#copies React to the container directory
# Set working directory to nginx resources directory
WORKDIR /usr/share/nginx/html
# Remove default nginx static resources
RUN rm -rf ./*
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/dist .
ENTRYPOINT ["nginx", "-g", "daemon off;"]
RUN apt-get install bash
# Copies configuration files
COPY ./default.conf /etc/nginx/conf.d/default.conf
# Copies static resources from builder stage
COPY --from=builder /app/build .
# Containers run nginx with global directives and daemon off
ENTRYPOINT ["nginx", "-g", "daemon off;"]

View File

@ -1,67 +0,0 @@
# log-viewer microfrontend (WIP)
This is an experimental microfrontend to view logs coming from camtiler, testing microfrontends concept and developing
Javascript/Node application directly on Kubernetes cluster using Skaffold (hot-reloading source files works!)
Currently the application itself is a really minimalistic frontend based on Vue.js 3 framework.
## Getting started
0. Have access with kubectl to desired Kubernetes cluster
0. Have local Docker daemon ready along with access to your image registry (building in-cluster with Kaniko is currently not tested)
1. Get Skaffold 2.0.0-beta*: https://github.com/GoogleContainerTools/skaffold/releases
2. Run `skaffold dev --namespace {desired K8S namespace}`
And you should be good to go. Skaffold would create a deployment, build the container and upload it to your registry
and deploy it.
## Good to know
### Skaffold
All Skaffold configuration is in skaffold.yml. There we have:
1. App/deployment name (metadata)
2. Build artifacts - artifact that Skaffold would build and use, either in case of development or also actual deploy
3. Profiles - similar to `npm` commands/profiles, you can have many different actions (run `skaffold {action}`).
We only have `dev` which will build and deploy the `log-viewer-frontend` container
(in manner how it's defined in Kubernetes manifest), and then enable `manual sync`, which defines which
changed files will be copied to the container when it's running - change in everything else will trigger
rebuilding the container.
### Hot-reload vs rebuilding the container
Currently the files that will be copied are fine-tuned as they are known to work well with Vue.js hot-reload feature
(eg actual frontend code). Other files, such as framework configuration files (`vite.config.js`, `vue.config.js`)
will trigger rebuilding and more importantly, restarting the container, to provide stability. It might not be necessary
to restart the container, this is just testing at this point. You can try it by introducing less explicit `sync`
config in `skaffold.yml`.
Change in `packages*` files will also trigger rebuilding and restarting the container, with the difference of
caching the result of the `npm install` command - `node_modules` directory. So in case of changing framework config,
the container will be quickly rebuilt and restarted, but when changing packages in `package.json`, `npm install`
will also be ran when re-building the container.
### Dockerfile
This is a really simple Dockerfile based on the official Node Docker image.
Only extra stuff it does is:
1. exposing the port for reference
2. changing workdir(?)
3. running `npm install` on-demand
4. copying other code into the container
5. defining the run command (important!)
We also have the `.dockerignore` to filter out files that never need to make into the container, such as IDE
metadata directories, Git, readme etc.
With the current config, your local Docker daemon will be used to build the image and upload it to your image registry.
Building in-cluster with Kaniko should be supported (https://skaffold.dev/docs/pipeline-stages/builders/docker/)
but currently not tested.
### Kubernetes
The Kubernetes manifest(s) are supposed to be in the `k8s/` directory.
Skaffold will pick them up automatically from there, apply them (also cleaning up after itself),
and match the container images from it's manifest and Kubernetes manifest, so it knows when to make the Kubernetes
redeploy the image.
Here we have a simple deployment, where `https://playground.k-space.ee/` takes us to the (development) frontend
container and `https://playground.k-space.ee/events` gets data from the `camtiler log-backend`.
The actual production usage may vary a lot in case of frontend - one would usually not run a
Node.js server to serve frontend assets, unless it's a SSR frontend (Nuxt, Next frameworks).
But for Node.js backends, it's pretty close to the standard.

16
frontend/default.conf Normal file
View File

@ -0,0 +1,16 @@
server {
listen 3003;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /events {
proxy_buffering off;
proxy_pass http://127.0.0.1:3002/events;
}
}

View File

@ -1,13 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Log Viewer</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

View File

@ -1,9 +0,0 @@
server {
listen 8080;
server_name _;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}

27783
frontend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,31 +1,40 @@
{
"name": "@k-space/log-viewer",
"version": "0.0.0",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vite build",
"dev": "vite --port 8080 --host",
"preview": "vite preview --port 3003"
},
"name": "frontend",
"version": "0.1.0",
"private": true,
"dependencies": {
"@ag-grid-community/core": "^28.2.0",
"@mdi/font": "5.9.55",
"@vue/cli-service": "^5.0.8",
"ag-grid-vue3": "^28.2.0",
"core-js": "^3.25.1",
"event-hooks-webpack-plugin": "^2.2.0",
"pinia": "^2.0.21",
"roboto-fontface": "*",
"single-spa-vue": "^2.5.1",
"systemjs-webpack-interop": "^2.3.7",
"vue": "^3.2.39",
"vuetify": "^3.0.0-beta.0",
"webfontloader": "^1.0.0"
"@testing-library/jest-dom": "^5.16.1",
"@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-hooks-sse": "^2.0.0",
"react-scripts": "5.0.0",
"web-vitals": "^2.1.3"
},
"devDependencies": {
"@vitejs/plugin-vue": "^3.0.3",
"vite": "^3.0.9",
"vue-cli-plugin-vuetify": "~2.5.8",
"webpack-plugin-vuetify": "^2.0.0-alpha.0"
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"proxy": "http://localhost:3002",
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="Event logging"
content="Web site created using create-react-app"
/>
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Event log</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

BIN
frontend/public/logo192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
frontend/public/logo512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

View File

@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View File

@ -1,15 +0,0 @@
<script setup>
import LogViewer from './components/LogViewer.vue'
</script>
<template>
<LogViewer />
</template>
<script>
export default {
name: 'app1',
}
</script>
<style scoped>
</style>

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69" xmlns:v="https://vecta.io/nano"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>

Before

Width:  |  Height:  |  Size: 308 B

View File

@ -1,15 +0,0 @@
div#app {
width: 100%;
height: 100vh;
}
.screenshots-drawer {
position: fixed;
display: flex;
flex-direction: column;
}
.ag-theme-material {
--ag-value-change-value-highlight-background-color: #f9ff99;
}

View File

@ -1,29 +0,0 @@
export default {
template: `
<select v-model="filter" class="v-select">
<option value=""> </option>
<option v-for="option in params.options" :value="option">
{{ option }}
</option>
</select>
`,
data: function () {
return {
filter: '',
};
},
methods: {
updateFilter() {
this.params.filterChangedCallback();
},
doesFilterPass(params) {
const value = this.params.field.split('.').reduce((a, b) => a[b], params.data);
return value === this.filter;
},
isFilterActive() {
return this.filter !== ''
},
},
};

View File

@ -1,83 +0,0 @@
<template>
<v-dialog
v-model="examineLog"
width="50wv"
>
<v-card>
<v-card-text style="height: 70vh">
<ag-grid-vue
style="width: 100%; height: 100%;"
class="ag-theme-material"
@grid-ready="onGridReady"
:columnDefs="columnDefs"
:row-data="examineLogContent"
:supress-horisontal-scroll="true"
:enable-scrolling="true"
:enableCellTextSelection="true"
:ensureDomOrder="true"
></ag-grid-vue>
</v-card-text>
<v-card-actions>
<v-btn color="primary" block @click="closeModal">Close</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
import { AgGridVue } from "ag-grid-vue3";
import "ag-grid-community/styles//ag-grid.css";
import "ag-grid-community/styles//ag-theme-material.css";
import ScreenshotCell from "./ScreenshotCell.js";
import { VCard, VCardText, VCardActions } from 'vuetify/components/VCard'
import { VDialog } from 'vuetify/components/VDialog'
import { VBtn } from 'vuetify/components/VBtn'
import { VTable } from 'vuetify/components/VTable'
export default {
components: {
AgGridVue,
VCard,
VCardText,
VCardActions,
VBtn,
VDialog,
VTable,
ScreenshotCell: ScreenshotCell
},
data() {
return {
columnDefs: [
{
field: 'key',
sortable: true,
filter: 'agTextColumnFilter',
resizable: true
},
{
field: 'value',
sortable: true,
filter: 'agTextColumnFilter',
resizable: true
},
]
}
},
props: {
examineLogContent: Array,
closeModal: Function
},
computed: {
examineLog() {
return !!this.examineLogContent
}
},
methods: {
onGridReady(params) {
params.api.sizeColumnsToFit()
},
}
}
</script>

View File

@ -1,173 +0,0 @@
<template>
<div style="height: 100%; width: 100%">
<ag-grid-vue
style="width: 100%; height: 100%;"
class="ag-theme-material"
@grid-ready="onGridReady"
:defaultColDef="defaultColDef"
:columnDefs="columnDefs"
:pagination="true"
:paginationAutoPageSize=true
:row-data="null"
row-selection="single"
:onRowSelected="openExamineLog"
:supress-horisontal-scroll="true"
:enable-scrolling="true"
></ag-grid-vue>
<ExamineLogModal :examine-log-content="examineLogContent" :close-modal="closeExamineLog" />
</div>
</template>
<script>
import { AgGridVue } from "ag-grid-vue3";
import "ag-grid-community/styles//ag-grid.css";
import "ag-grid-community/styles//ag-theme-material.css";
import ScreenshotCell from "./ScreenshotCell.js";
import ExamineLogModal from "./ExamineLogModal.vue";
import ComboboxFilter from "./ComboboxFilter.js";
export default {
components: {
ExamineLogModal,
AgGridVue,
ComboboxFilter,
ScreenshotCell: ScreenshotCell
},
data() {
return {
examineLogContent: null,
gridApi: null,
gridColumnApi: null,
defaultColDef: {
width: 50,
initialPinned: true,
resizable: true,
enableCellChangeFlash: true
},
currentRowCount: 0,
comboBoxOptions: {},
viewRowCount: 20,
}
},
computed: {
columnDefs() {
return [
{
field: '@timestamp',
width: 70,
sortable: true
},
{
field: 'kubernetes.namespace',
headerName: 'namespace',
tooltipValueGetter: (params) => params.value,
filter: ComboboxFilter,
filterParams: {
options: this.comboBoxOptions['kubernetes.namespace'],
field: 'kubernetes.namespace',
}
},
{
field: 'kubernetes.pod.name',
headerName: 'pod',
tooltipValueGetter: (params) => params.value,
filter: ComboboxFilter,
filterParams: {
options: this.comboBoxOptions['kubernetes.pod.name'],
field: 'kubernetes.pod.name',
}
},
{
field: 'kubernetes.container.name',
headerName: 'container',
tooltipValueGetter: (params) => params.value,
filter: ComboboxFilter,
filterParams: {
options: this.comboBoxOptions['kubernetes.container.name'],
field: 'kubernetes.container.name',
}
},
{
field: 'message',
tooltipValueGetter: (params) => params.value,
width: 500,
},
{
field: 'stream',
},
];
}
},
created() {
this.setupStream()
},
methods: {
setupStream() {
let es = new EventSource('/events');
es.onmessage = (e) => this.handleReceiveMessage(e)
es.addEventListener("filters", (e) => this.handleReceiveFilters(e))
},
onGridReady(params) {
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
},
handleReceiveMessage (event) {
const eventData = this.parseEventData(event.data);
const res = this.gridApi.applyTransaction({
add: [eventData]
});
const rowNode = res.add[0]
this.gridApi.flashCells({ rowNodes: [rowNode]});
this.gridApi.sizeColumnsToFit()
},
handleReceiveFilters (event) {
this.comboBoxOptions = this.parseEventData(event.data);
},
parseEventData (eventData) {
try {
let json = JSON.parse(eventData)
if (!json.message) {
json.message = JSON.stringify(json.json)
}
return json
} catch (e) {
console.error(e, eventData)
}
},
openExamineLog (row) {
const selectedRow = row.data
row.node.setSelected(false)
this.examineLog = true
const flattened = flattenObj(selectedRow)
const pairs = [];
Object.keys(flattened).map((key) => {
pairs.push({
key: key,
value: flattened[key]
})
})
this.examineLogContent = pairs
},
closeExamineLog () {
this.examineLogContent = null
}
},
}
const flattenObj = (ob) => {
let result = {};
for (const i in ob) {
if ((typeof ob[i]) === 'object' && !Array.isArray(ob[i])) {
const temp = flattenObj(ob[i]);
for (const j in temp) {
result[i + '.' + j] = temp[j];
}
}
else {
result[i] = ob[i];
}
}
return result;
};
</script>

View File

@ -1,30 +0,0 @@
export default {
template: `<div>
<a @click="openDrawer">View screenshots</a>
<div v-if="drawerOpen" class="screenshots-drawer">
<img v-for="screenshot in screenshots" :src="screenshot.orig"/>
</div>
</div>`,
data: function () {
return {
screenshots: [],
drawerOpen: false,
};
},
beforeMount() {
this.updateImage(this.params);
this.updateImage(this.params);
},
methods: {
updateImage(params) {
this.screenshots = params.value
this.value = params.value;
},
refresh(params) {
this.updateImage(params);
},
openDrawer () {
this.drawerOpen = true
}
},
};

View File

@ -0,0 +1,3 @@
body {
background-color: #eafaf9;
}

View File

@ -0,0 +1,47 @@
import React, { useState, useEffect } from 'react';
import { useSSE, SSEProvider } from 'react-hooks-sse';
import './App.css';
import EventList from '../eventList/EventList.js';
import './App.css';
const Component = () => {
const event = useSSE('log-entry')
const [events, setEvents] = useState([])
useEffect(() =>{
console.info(event);
if (event) {
for (var j = 0; j < events.length; j++) {
if (events[j].timestamp <= event.timestamp) {
if (events[j]._id == event._id) {
setEvents([...events.slice(0, j), event, ...events.slice(j+1)]);
return;
} else {
setEvents([...events.slice(0, j), event, ...events.slice(j)]);
return;
}
}
}
setEvents([event, ...events]);
}
}, [event])
return <EventList data={events} />
}
function App() {
return (
<SSEProvider endpoint="/events" >
<Component />
</SSEProvider>
)
}
export default App;

View File

@ -0,0 +1,18 @@
.eventDiv {
background-color: aliceblue;
border: 2px solid #26A69A;
border-radius: 15px;
text-align: left;
padding: 5px;
max-width: fit-content;
font-family: apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
color: #092a26;
margin: 7px 0px;
}
.eventPic {
border-radius: 15px;
border: 1px groove #d5f6f2;
max-width:100%;
max-height:100%;
}

View File

@ -0,0 +1,23 @@
import React from "react";
import "./Event.css";
function Event(props) {
let imgArray = [];
if (props.data.hasOwnProperty('screenshots')) {
props.data.screenshots.forEach(element => {
imgArray = [...imgArray, (<a href={element.orig} target="_blank"><img src={element.url} className="eventPic"></img></a>)]
});
}
return (
<div className="eventDiv">
{JSON.stringify(props.data.source)}
<br></br>
{[...imgArray]}
</div>
);
}
export default Event;

View File

@ -0,0 +1,11 @@
.eventListUl {
background-color: #c1f1ec;
max-width: 75%;
padding: 5px;
border: 5px solid #26A69A;
border-radius: 5px;
}
.eventListLi {
list-style: none;
}

View File

@ -0,0 +1,15 @@
import React from 'react';
import Event from '../event/Event.js';
import './EventList.css';
function EventList(props) {
return (
<ul className="eventListUl">
{props.data.map((event) => {
return <li className="eventListLi"><Event data={event} /></li>
})}
</ul>
)
}
export default EventList;

3
frontend/src/index.css Normal file
View File

@ -0,0 +1,3 @@
body {
}

17
frontend/src/index.js Normal file
View File

@ -0,0 +1,17 @@
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/app/App.js';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

View File

@ -1,10 +0,0 @@
import { createApp } from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify'
import { loadFonts } from './plugins/webfontloader'
import './assets/main.css'
loadFonts()
createApp(App)
.use(vuetify)
.mount('#app')

View File

@ -0,0 +1,13 @@
const reportWebVitals = onPerfEntry => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;

View File

@ -1,3 +0,0 @@
import { setPublicPath } from "systemjs-webpack-interop";
setPublicPath("app1");

View File

@ -0,0 +1,5 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';

View File

@ -1,14 +0,0 @@
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})

View File

@ -1,26 +0,0 @@
import vue from '@vitejs/plugin-vue'
export default {
resolve: {
alias: {
vue: 'vue/dist/vue.esm-bundler.js'
}
},
rollupOptions: {
input: 'src/main.js',
format: 'system',
preserveEntrySignatures: true
},
plugins: [vue({
template: {
transformAssetUrls: {
base: '/src'
}
}
})],
pluginOptions: {
vuetify: {
// https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vuetify-loader
}
}
}

View File

@ -1,43 +0,0 @@
const path = require('path');
const fs = require('fs');
const EventHooksPlugin = require('event-hooks-webpack-plugin');
module.exports = {
publicPath: '/logs',
chainWebpack: (config) => {
config.devServer.headers({
'Access-Control-Allow-Origin': '*',
});
config.devServer.set('port', 8080);
config.devServer.set('hot', true);
config.output.filename('[name].js');
config.output.publicPath('/logs');
config.externals([
'vue',
'vue-router'
]);
},
lintOnSave: true,
filenameHashing: false,
configureWebpack: {
plugins: [
new EventHooksPlugin({
done: () => {
if (process.env.NODE_ENV !== 'development') {
const buildDir = path.join(__dirname, '/dist');
fs.unlinkSync(`${buildDir}/index.html`);
}
},
}),
],
},
pluginOptions: {
vuetify: {
// https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vuetify-loader
}
}
};

View File

@ -1,102 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: playground
annotations:
kubernetes.io/ingress.class: traefik
cert-manager.io/cluster-issuer: default
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.middlewares: traefik-sso@kubernetescrd
traefik.ingress.kubernetes.io/router.tls: "true"
external-dns.alpha.kubernetes.io/target: traefik.k-space.ee
spec:
rules:
- host: playground.k-space.ee
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: log-viewer-frontend
port:
number: 8080
- pathType: Prefix
path: "/events"
backend:
service:
name: log-viewer-backend
port:
number: 3002
tls:
- hosts:
- playground.k-space.ee
secretName: playground-tls
---
apiVersion: v1
kind: Service
metadata:
name: log-viewer-frontend
spec:
type: ClusterIP
selector:
app: log-viewer-frontend
ports:
- protocol: TCP
port: 8080
---
apiVersion: v1
kind: Service
metadata:
name: log-viewer-backend
spec:
type: ClusterIP
selector:
app: log-viewer-backend
ports:
- protocol: TCP
port: 3002
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: log-viewer-frontend
spec:
selector:
matchLabels:
app: log-viewer-frontend
template:
metadata:
labels:
app: log-viewer-frontend
spec:
containers:
- name: log-viewer-frontend
image: harbor.k-space.ee/playground/log-viewer-frontend
ports:
- containerPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: log-viewer-backend
spec:
selector:
matchLabels:
app: log-viewer-backend
template:
metadata:
labels:
app: log-viewer-backend
spec:
containers:
- name: log-viewer-backend
image: harbor.k-space.ee/playground/log-viewer-backend
ports:
- containerPort: 3002
env:
- name: MONGODB_HOST
valueFrom:
secretKeyRef:
name: mongodb-application-readwrite
key: connectionString.standard

View File

@ -1,102 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: playground
annotations:
kubernetes.io/ingress.class: traefik
cert-manager.io/cluster-issuer: default
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.middlewares: traefik-sso@kubernetescrd
traefik.ingress.kubernetes.io/router.tls: "true"
external-dns.alpha.kubernetes.io/target: traefik.k-space.ee
spec:
rules:
- host: playground.k-space.ee
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: log-viewer-frontend
port:
number: 8080
- pathType: Prefix
path: "/events"
backend:
service:
name: log-viewer-backend
port:
number: 3002
tls:
- hosts:
- playground.k-space.ee
secretName: playground-tls
---
apiVersion: v1
kind: Service
metadata:
name: log-viewer-frontend
spec:
type: ClusterIP
selector:
app: log-viewer-frontend
ports:
- protocol: TCP
port: 8080
---
apiVersion: v1
kind: Service
metadata:
name: log-viewer-backend
spec:
type: ClusterIP
selector:
app: log-viewer-backend
ports:
- protocol: TCP
port: 3002
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: log-viewer-frontend
spec:
selector:
matchLabels:
app: log-viewer-frontend
template:
metadata:
labels:
app: log-viewer-frontend
spec:
containers:
- name: log-viewer-frontend
image: harbor.k-space.ee/playground/log-viewer-frontend
ports:
- containerPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: log-viewer-backend
spec:
selector:
matchLabels:
app: log-viewer-backend
template:
metadata:
labels:
app: log-viewer-backend
spec:
containers:
- name: log-viewer-backend
image: harbor.k-space.ee/playground/log-viewer-backend
ports:
- containerPort: 3002
env:
- name: MONGODB_HOST
valueFrom:
secretKeyRef:
name: mongodb-application-readwrite
key: connectionString.standard

View File

@ -1,56 +0,0 @@
apiVersion: skaffold/v3alpha1
kind: Config
metadata:
name: log-viewer-backend
build:
artifacts:
- image: harbor.k-space.ee/playground/log-viewer-backend
context: backend
docker:
dockerfile: Dockerfile
- image: harbor.k-space.ee/playground/log-viewer-frontend
context: frontend
docker:
dockerfile: Dockerfile
deploy:
kubectl: {}
manifests:
rawYaml:
- k8s/staging/deployment.yaml
profiles:
- name: dev
activation:
- command: dev
build:
artifacts:
- image: harbor.k-space.ee/playground/log-viewer-backend
context: backend
docker:
target: dev
sync:
manual:
- src: '**/*.js'
dest: .
- image: harbor.k-space.ee/playground/log-viewer-frontend
context: frontend
docker:
target: dev
sync:
manual:
- src: 'src/**/*.vue'
dest: .
- src: 'src/**/*.js'
dest: .
- src: 'src/**/*.css'
dest: .
- src: 'src/**/*.svg'
dest: .
- src: 'index.html'
dest: .
manifests:
rawYaml:
- k8s/dev/deployment.yaml