revamp kener 2.0

This commit is contained in:
Raj Nandan Sharma
2024-11-08 22:56:35 +05:30
parent 3941cc4e9b
commit c0332fe035
56 changed files with 9904 additions and 457 deletions

View File

View File

@@ -1 +0,0 @@
I am Empty File

View File

@@ -51,7 +51,11 @@
"status_no_data": "No Data",
"status_ok": "Status OK",
"am": "am",
"pm": "pm"
"pm": "pm",
"standard": "Standard",
"pinging": "Pinging",
"status_svg": "Status SVG",
"status_svg_desc": "Get a SVG dot for this monitor"
},
"numbers": ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
}

261
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "kener",
"version": "0.0.14",
"version": "0.0.15",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "kener",
"version": "0.0.14",
"version": "0.0.15",
"license": "MIT",
"dependencies": {
"axios": "^1.6.2",
@@ -20,6 +20,7 @@
"js-yaml": "^4.1.0",
"lucide-svelte": "^0.292.0",
"marked": "^11.1.1",
"mode-watcher": "^0.4.1",
"moment": "^2.29.4",
"moment-timezone": "^0.5.43",
"node-cache": "^5.1.2",
@@ -975,21 +976,23 @@
}
},
"node_modules/axios": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz",
"integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==",
"version": "1.7.7",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
"integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.0",
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axobject-query": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
"integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==",
"dependencies": {
"dequal": "^2.0.3"
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
"integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
"license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/badge-maker": {
@@ -1039,9 +1042,10 @@
}
},
"node_modules/body-parser": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
"version": "1.20.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
"integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.5",
@@ -1051,7 +1055,7 @@
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.11.0",
"qs": "6.13.0",
"raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
@@ -1065,6 +1069,7 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
@@ -1072,7 +1077,8 @@
"node_modules/body-parser/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
"node_modules/brace-expansion": {
"version": "2.0.1",
@@ -1084,11 +1090,12 @@
}
},
"node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"license": "MIT",
"dependencies": {
"fill-range": "^7.0.1"
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
@@ -1151,6 +1158,7 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -1159,6 +1167,7 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
@@ -1412,6 +1421,7 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -1559,6 +1569,7 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
@@ -1583,6 +1594,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -1599,6 +1611,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
"license": "MIT",
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
@@ -1644,7 +1657,8 @@
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
"license": "MIT"
},
"node_modules/electron-to-chromium": {
"version": "1.4.601",
@@ -1659,9 +1673,10 @@
"dev": true
},
"node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -1670,6 +1685,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
"license": "MIT",
"dependencies": {
"get-intrinsic": "^1.2.4"
},
@@ -1681,6 +1697,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
@@ -1740,7 +1757,8 @@
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"license": "MIT"
},
"node_modules/esm-env": {
"version": "1.0.0",
@@ -1758,41 +1776,43 @@
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/express": {
"version": "4.19.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
"license": "MIT",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
"body-parser": "1.20.2",
"body-parser": "1.20.3",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
"cookie": "0.6.0",
"cookie": "0.7.1",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
"encodeurl": "~1.0.2",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "1.2.0",
"finalhandler": "1.3.1",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"merge-descriptors": "1.0.1",
"merge-descriptors": "1.0.3",
"methods": "~1.1.2",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.7",
"path-to-regexp": "0.1.10",
"proxy-addr": "~2.0.7",
"qs": "6.11.0",
"qs": "6.13.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "0.18.0",
"serve-static": "1.15.0",
"send": "0.19.0",
"serve-static": "1.16.2",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"type-is": "~1.6.18",
@@ -1804,9 +1824,10 @@
}
},
"node_modules/express/node_modules/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
"integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -1848,9 +1869,10 @@
}
},
"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==",
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
},
@@ -1859,12 +1881,13 @@
}
},
"node_modules/finalhandler": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
"integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
"integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"encodeurl": "~1.0.2",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
@@ -1879,6 +1902,7 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
@@ -1886,7 +1910,8 @@
"node_modules/finalhandler/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
"node_modules/focus-trap": {
"version": "7.5.4",
@@ -1953,6 +1978,7 @@
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -2009,6 +2035,7 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
@@ -2069,6 +2096,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"license": "MIT",
"dependencies": {
"get-intrinsic": "^1.1.3"
},
@@ -2094,6 +2122,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0"
},
@@ -2105,6 +2134,7 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -2116,6 +2146,7 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -2138,6 +2169,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
"license": "MIT",
"dependencies": {
"depd": "2.0.0",
"inherits": "2.0.4",
@@ -2153,6 +2185,7 @@
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
@@ -2283,6 +2316,7 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"license": "MIT",
"engines": {
"node": ">=0.12.0"
}
@@ -2422,14 +2456,19 @@
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
"integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/merge2": {
"version": "1.4.1",
@@ -2448,11 +2487,12 @@
}
},
"node_modules/micromatch": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"license": "MIT",
"dependencies": {
"braces": "^3.0.2",
"braces": "^3.0.3",
"picomatch": "^2.3.1"
},
"engines": {
@@ -2463,6 +2503,7 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"license": "MIT",
"bin": {
"mime": "cli.js"
},
@@ -2531,6 +2572,15 @@
"mkdirp": "bin/cmd.js"
}
},
"node_modules/mode-watcher": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/mode-watcher/-/mode-watcher-0.4.1.tgz",
"integrity": "sha512-bNC+1NXmwEFZtziCdZSgP7HFQTpqJPcQn9GwwJQGSf6SBF3neEPYV1uRwkYuAQwbsvsXIYtzaqgedDzJ7D1mhg==",
"license": "MIT",
"peerDependencies": {
"svelte": "^4.0.0 || ^5.0.0-next.1"
}
},
"node_modules/moment": {
"version": "2.29.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
@@ -2660,9 +2710,13 @@
}
},
"node_modules/object-inspect": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
"integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -2671,6 +2725,7 @@
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
"license": "MIT",
"dependencies": {
"ee-first": "1.1.1"
},
@@ -2702,6 +2757,7 @@
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -2729,9 +2785,10 @@
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
},
"node_modules/path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
"integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
"license": "MIT"
},
"node_modules/periscopic": {
"version": "3.1.0",
@@ -3063,11 +3120,12 @@
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/qs": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.0.4"
"side-channel": "^1.0.6"
},
"engines": {
"node": ">=0.6"
@@ -3123,6 +3181,7 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -3131,6 +3190,7 @@
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
@@ -3263,10 +3323,11 @@
}
},
"node_modules/rollup": {
"version": "3.29.4",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz",
"integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==",
"version": "3.29.5",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz",
"integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==",
"dev": true,
"license": "MIT",
"bin": {
"rollup": "dist/bin/rollup"
},
@@ -3343,7 +3404,8 @@
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/sander": {
"version": "0.5.1",
@@ -3358,9 +3420,10 @@
}
},
"node_modules/send": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
"integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
@@ -3384,6 +3447,7 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
@@ -3391,22 +3455,34 @@
"node_modules/send/node_modules/debug/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
"node_modules/send/node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/send/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=="
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/serve-static": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
"integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
"version": "1.16.2",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
"integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
"license": "MIT",
"dependencies": {
"encodeurl": "~1.0.2",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
"send": "0.18.0"
"send": "0.19.0"
},
"engines": {
"node": ">= 0.8.0"
@@ -3422,6 +3498,7 @@
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"license": "MIT",
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
@@ -3437,7 +3514,8 @@
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
"license": "ISC"
},
"node_modules/shebang-command": {
"version": "2.0.0",
@@ -3473,6 +3551,7 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.7",
"es-errors": "^1.3.0",
@@ -3533,6 +3612,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -3662,16 +3742,18 @@
}
},
"node_modules/svelte": {
"version": "4.2.8",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.8.tgz",
"integrity": "sha512-hU6dh1MPl8gh6klQZwK/n73GiAHiR95IkFsesLPbMeEZi36ydaXL/ZAb4g9sayT0MXzpxyZjR28yderJHxcmYA==",
"version": "4.2.19",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.19.tgz",
"integrity": "sha512-IY1rnGr6izd10B0A8LqsBfmlT5OILVuZ7XsI0vdGPEvuonFV7NYEUK4dAkm9Zg2q0Um92kYjTpS1CAP3Nh/KWw==",
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.2.1",
"@jridgewell/sourcemap-codec": "^1.4.15",
"@jridgewell/trace-mapping": "^0.3.18",
"@types/estree": "^1.0.1",
"acorn": "^8.9.0",
"aria-query": "^5.3.0",
"axobject-query": "^3.2.1",
"axobject-query": "^4.0.0",
"code-red": "^1.0.3",
"css-tree": "^2.3.1",
"estree-walker": "^3.0.3",
@@ -3937,6 +4019,7 @@
"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==",
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
},
@@ -3948,6 +4031,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"license": "MIT",
"engines": {
"node": ">=0.6"
}
@@ -3984,6 +4068,7 @@
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"license": "MIT",
"dependencies": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
@@ -4029,6 +4114,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -4085,10 +4171,11 @@
}
},
"node_modules/vite": {
"version": "4.5.3",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz",
"integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==",
"version": "4.5.5",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.5.5.tgz",
"integrity": "sha512-ifW3Lb2sMdX+WU91s3R0FyQlAyLxOzCSCP37ujw0+r5POeHPwe6udWVIElKQq8gk3t7b8rkmvqC6IHBpCff4GQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "^0.18.10",
"postcss": "^8.4.27",

View File

@@ -29,6 +29,7 @@
"scripts": {
"build": "node scripts/check.js && vite build",
"serve": "node prod.js",
"dev": "vite dev",
"kener:dev": "cross-env NODE_ENV=development PUBLIC_KENER_FOLDER=./static/kener node scripts/check.js && concurrently \"cross-env NODE_ENV=development PUBLIC_KENER_FOLDER=./static/kener node dev.js\" \"cross-env NODE_ENV=development PUBLIC_KENER_FOLDER=./static/kener vite dev\"",
"kener:dev-monitor": "cross-env NODE_ENV=development PUBLIC_KENER_FOLDER=./static/kener node dev.js",
"kener:build": "cross-env NODE_ENV=production node scripts/check.js && cross-env NODE_ENV=production vite build",
@@ -67,6 +68,7 @@
"js-yaml": "^4.1.0",
"lucide-svelte": "^0.292.0",
"marked": "^11.1.1",
"mode-watcher": "^0.4.1",
"moment": "^2.29.4",
"moment-timezone": "^0.5.43",
"node-cache": "^5.1.2",

View File

@@ -1,12 +0,0 @@
import { GetMinuteStartNowTimestampUTC, GetDayStartWithOffset, BeginningOfDay } from "./tool.js";
let tzOffset = -330;
let ts = GetMinuteStartNowTimestampUTC();
console.log("GetMinuteStartNowTimestampUTC India 12AM: " + ts);
let tm = GetDayStartWithOffset(GetMinuteStartNowTimestampUTC(), tzOffset);
console.log("GetMinuteStartTimestampUTC India 12AM: should be 18:30PM " + tm);
console.log(
`getUTCTimestampAtStartOfDayForOffset(${GetMinuteStartNowTimestampUTC()}, ${tzOffset})`
);
console.log(BeginningOfDay({ timeZone: "GMT" }));
console.log(BeginningOfDay({ timeZone: "Asia/Kolkata", date: new Date(1703223388000) }));

View File

@@ -3,6 +3,8 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
%sveltekit.head%
</head>

8
src/hooks.server.js Normal file
View File

@@ -0,0 +1,8 @@
// src/routes/+server.js
import { Startup } from "$lib/server/startup.js";
import { STATUS_OK } from "$lib/server/check.js";
(async () => {
console.log("Starting server...");
console.log("Server started with status: " + STATUS_OK);
await Startup();
})();

View File

@@ -1,5 +1,6 @@
/*one is the class for dotted background*/
.one {
.dots-pattern {
position: absolute;
top: 0px;
left: 0;
@@ -12,7 +13,7 @@
clip-path: polygon(0 0, 100% 0, 100% 54%, 0% 100%);
}
.one::after {
.dots-pattern::after {
content: "";
position: absolute;
background-image: radial-gradient(rgba(0, 0, 0, 0) 1.5px, var(--background-kener) 1px);
@@ -24,6 +25,55 @@
left: 0;
}
.squares-pattern {
position: absolute;
top: 0;
left: 0;
width: 100%;
z-index: 0;
background-repeat: no-repeat;
background-size: 100%;
height: 100svh;
clip-path: polygon(0 0, 100% 0, 100% 54%, 0% 100%);
transform: blur(3px);
}
.squares-pattern::after {
content: "";
position: absolute;
background-image: linear-gradient(#444cf7 1px, transparent 1px),
linear-gradient(to right, #444cf7 1px, var(--background-kener) 1px);
-webkit-mask-image: linear-gradient(
to bottom,
rgba(0, 0, 0, 1) 0%,
rgba(0, 0, 0, 0.8) 20%,
rgba(0, 0, 0, 0.6) 40%,
rgba(0, 0, 0, 0.4) 60%,
rgba(0, 0, 0, 0.2) 80%,
rgba(0, 0, 0, 0) 100%
);
mask-image: linear-gradient(
180deg,
rgba(0, 0, 0, 0.2) 0%,
rgba(0, 0, 0, 0.1) 20%,
rgba(0, 0, 0, 0.05) 40%,
rgba(0, 0, 0, 0.025) 60%,
rgba(0, 0, 0, 0.0125) 80%,
rgba(0, 0, 0, 0) 100%
);
background-size: 32px 32px;
width: 100%;
height: 100vh;
top: 0;
left: 0;
}
.dark .squares-pattern::after {
background-image: linear-gradient(#677489 1px, transparent 1px),
linear-gradient(to right, #677489 1px, var(--background-kener) 1px);
}
/*Needed to overlay content on top of dotted bg*/
section {
position: relative;
@@ -78,7 +128,7 @@ section {
/*Needed to show monitor stacked properly*/
.monitors-card .monitor {
padding: 1.3em 1em;
padding: 1.2em 3.4em 0.875em 3.4em;
border-bottom: 1px solid;
border-color: hsl(var(--border) / var(--tw-border-opacity));
}

View File

@@ -46,45 +46,60 @@
let copiedEmbed = false;
let copiedBadgeStatus = false;
let copiedBadgeUptime = false;
let copiedBadgeDotStandard = false;
let copiedBadgeDotPing = false;
let protocol;
let domain;
let pathMonitorLink;
function copyLinkToClipboard() {
//get domain with port number
let domain = window.location.host;
//get protocol
let protocol = window.location.protocol;
let path = `${base}/monitor-${monitor.tag}`;
navigator.clipboard.writeText(protocol + "//" + domain + path);
navigator.clipboard.writeText(pathMonitorLink);
copiedLink = true;
setTimeout(function () {
copiedLink = false;
}, 1500);
}
let pathMonitorBadgeUptime;
function copyUptimeBadge() {
let domain = window.location.host;
let protocol = window.location.protocol;
let path = `${base}/badge/${monitor.tag}/uptime`;
navigator.clipboard.writeText(protocol + "//" + domain + path);
navigator.clipboard.writeText(pathMonitorBadgeUptime);
copiedBadgeUptime = true;
setTimeout(function () {
copiedBadgeUptime = false;
}, 1500);
}
let pathMonitorBadgeStatus;
function copyStatusBadge() {
let domain = window.location.host;
let protocol = window.location.protocol;
let path = `${base}/badge/${monitor.tag}/status`;
navigator.clipboard.writeText(protocol + "//" + domain + path);
navigator.clipboard.writeText(pathMonitorBadgeStatus);
copiedBadgeStatus = true;
setTimeout(function () {
copiedBadgeStatus = false;
}, 1500);
}
let pathMonitorBadgeDot;
function copyDotStandard() {
navigator.clipboard.writeText(pathMonitorBadgeDot);
copiedBadgeDotStandard = true;
setTimeout(function () {
copiedBadgeDotStandard = false;
}, 1500);
}
let pathMonitorBadgeDotPing;
function copyDotPing() {
navigator.clipboard.writeText(pathMonitorBadgeDotPing);
copiedBadgeDotPing = true;
setTimeout(function () {
copiedBadgeDotPing = false;
}, 1500);
}
function copyScriptTagToClipboard() {
//get domain with port number
let domain = window.location.host;
//get protocol
let protocol = window.location.protocol;
let path = `${base}/embed-${monitor.tag}`;
let scriptTag =
`<script async src="${protocol + "//" + domain + path}/js?theme=${theme}&monitor=${protocol + "//" + domain + path}"><` +
@@ -138,102 +153,98 @@
}
onMount(async () => {
//getToday();
//for each div with class 90daygrid scroll to right most
//for each div with class 90daygrid scroll to right most for mobile view needed
scrollToRight();
protocol = window.location.protocol;
domain = window.location.host;
pathMonitorLink = `${protocol}//${domain}${base}/monitor-${monitor.tag}`;
pathMonitorBadgeUptime = `${protocol}//${domain}${base}/badge/${monitor.tag}/uptime`;
pathMonitorBadgeStatus = `${protocol}//${domain}${base}/badge/${monitor.tag}/status`;
pathMonitorBadgeDot = `${protocol}//${domain}${base}/badge/${monitor.tag}/dot`;
pathMonitorBadgeDotPing = `${protocol}//${domain}${base}/badge/${monitor.tag}/dot?animate=ping`;
});
afterUpdate(() => {
dispatch("heightChange", {});
});
</script>
<div class="monitor grid w-full grid-cols-12 gap-4 pb-4 md:w-[890px]">
{#if monitor.embed === undefined}
<div class="col-span-12 md:col-span-4">
<div class="pt-1">
<div class="scroll-m-20 text-2xl font-semibold tracking-tight">
{#if monitor.image}
<img
src={monitor.image}
class="inline h-6 w-6"
alt={monitor.name}
srcset=""
/>
<div class="monitor relative grid w-full grid-cols-12 gap-2 pb-2 md:w-[655px]">
<div class="col-span-12 md:w-[546px]">
<div class="pt-0">
<div class=" scroll-m-20 pr-5 text-xl font-medium tracking-tight">
{#if monitor.image}
<img
src={monitor.image}
class="absolute left-6 top-6 inline h-5 w-5"
alt={monitor.name}
srcset=""
/>
{/if}
<p class="overflow-hidden text-ellipsis whitespace-nowrap">
{monitor.name}
</p>
<p class="mt-1 text-xs font-medium text-muted-foreground">
{#if !!monitor.description}
{@html monitor.description}
{/if}
<span> {monitor.name} </span>
<br />
{#if monitor.description}
<Popover.Root>
<Popover.Trigger>
<span
class="menu-monitor pb-0 pl-1 pr-0 pt-0 {buttonVariants({
variant: 'link'
})}"
>
<Info size={12} class="text-muted-foreground" />
</span>
</Popover.Trigger>
<Popover.Content class="text-sm">
<h2 class="mb-2 text-lg font-semibold">
{monitor.name}
</h2>
<span class="text-sm text-muted-foreground">
{@html monitor.description}
</span>
</Popover.Content>
</Popover.Root>
{/if}
<Popover.Root>
<Popover.Trigger>
<span
class="menu-monitor pb-0 pl-1 pr-0 pt-0 {buttonVariants({
variant: 'link'
})}"
>
<Share2 size={12} class="text-muted-foreground" />
</span>
</Popover.Trigger>
<Popover.Content class="w-[375px] max-w-full pb-1 pl-1 pr-1">
<h2 class="mb-1 px-2 text-lg font-semibold">
</p>
<Popover.Root>
<Popover.Trigger class="absolute right-14 top-5 h-5 w-5 p-0">
<Button class="h-5 p-0" variant="link">
<Share2 class="h-4 w-4 text-muted-foreground" />
</Button>
</Popover.Trigger>
<Popover.Content class="w-[375px] max-w-full p-0">
<div class="p-4">
<h2 class="mb-1 text-sm font-semibold">
{l(lang, "monitor.share")}
</h2>
<p class="mb-2 pl-2 text-sm text-muted-foreground">
<p class="mb-2 text-xs text-muted-foreground">
{l(lang, "monitor.share_desc")}
</p>
<Button class="ml-2" variant="secondary" on:click={copyLinkToClipboard}>
<Button
class="h-8 text-xs"
variant="secondary"
on:click={copyLinkToClipboard}
>
{#if !copiedLink}
<Link class="mr-2 inline" size={12} />
<span class="text-sm font-medium">
<span class="font-medium">
{l(lang, "monitor.cp_link")}
</span>
{:else}
<CopyCheck class="mr-2 inline" size={12} />
<span class="text-sm font-medium">
<span class="font-medium">
{l(lang, "monitor.cpd_link")}
</span>
{/if}
</Button>
<h2 class="mb-2 mt-4 px-2 text-lg font-semibold">
</div>
<hr />
<div class="p-4">
<h2 class="mb-1 text-sm font-semibold">
{l(lang, "monitor.embed")}
</h2>
<p class="mb-2 pl-2 text-sm text-muted-foreground">
<p class="mb-1 text-xs text-muted-foreground">
{l(lang, "monitor.embed_desc")}
</p>
<div class="grid grid-cols-2 gap-2">
<div class="col-span-1 pl-4">
<h3 class="mb-2 text-sm text-muted-foreground">
<div class="mb-4 grid grid-cols-2 gap-2">
<div class="col-span-1">
<h3 class="mb-2 text-xs">
{l(lang, "monitor.theme")}
</h3>
<RadioGroup.Root bind:value={theme}>
<RadioGroup.Root bind:value={theme} class=" flex">
<div class="flex items-center space-x-2">
<RadioGroup.Item value="light" id="light-theme" />
<Label for="light-theme"
<Label class="text-xs" for="light-theme"
>{l(lang, "monitor.theme_light")}</Label
>
</div>
<div class="flex items-center space-x-2">
<RadioGroup.Item value="dark" id="dark-theme" />
<Label for="dark-theme"
<Label class="text-xs" for="dark-theme"
>{l(lang, "monitor.theme_dark")}</Label
>
</div>
@@ -241,107 +252,144 @@
</RadioGroup.Root>
</div>
<div class="col-span-1 pl-2">
<h3 class="mb-2 text-sm text-muted-foreground">
<h3 class="mb-2 text-xs">
{l(lang, "monitor.mode")}
</h3>
<RadioGroup.Root bind:value={embedType}>
<RadioGroup.Root bind:value={embedType} class="flex">
<div class="flex items-center space-x-2">
<RadioGroup.Item value="js" id="js-embed" />
<Label for="js-embed">&#x3C;script&#x3E;</Label>
<Label class="text-xs" for="js-embed"
>&#x3C;script&#x3E;</Label
>
</div>
<div class="flex items-center space-x-2">
<RadioGroup.Item value="iframe" id="iframe-embed" />
<Label for="iframe-embed">&#x3C;iframe&#x3E;</Label>
<Label class="text-xs" for="iframe-embed"
>&#x3C;iframe&#x3E;</Label
>
</div>
<RadioGroup.Input name="embed" />
</RadioGroup.Root>
</div>
</div>
<Button
class="mb-2 ml-2 mt-4"
class="h-8 px-2 text-xs"
variant="secondary"
on:click={copyScriptTagToClipboard}
>
{#if !copiedEmbed}
<Code class="mr-2 inline" size={12} />
<span class="text-sm font-medium">
<span class=" font-medium">
{l(lang, "monitor.cp_code")}
</span>
{:else}
<CopyCheck class="mr-2 inline" size={12} />
<span class="text-sm font-medium">
<span class="font-medium">
{l(lang, "monitor.cpd_code")}
</span>
{/if}
</Button>
<h2 class="mb-2 mt-2 px-2 text-lg font-semibold">
</div>
<hr />
<div class="p-4">
<h2 class="mb-1 text-sm font-semibold">
{l(lang, "monitor.badge")}
</h2>
<p class="mb-2 pl-2 text-sm text-muted-foreground">
<p class="mb-2 text-xs text-muted-foreground">
{l(lang, "monitor.badge_desc")}
</p>
<Button
class="mb-2 ml-2 mt-2"
class="h-8 px-2 text-xs"
variant="secondary"
on:click={copyStatusBadge}
>
{#if !copiedBadgeStatus}
<TrendingUp class="mr-2 inline" size={12} />
<span class="text-sm font-medium">
<span class="font-medium">
{l(lang, "monitor.status")}
{l(lang, "monitor.badge")}</span
>
{:else}
<CopyCheck class="mr-2 inline" size={12} />
<span class="text-sm font-medium">
<span class="font-medium">
{l(lang, "monitor.copied")}
{l(lang, "monitor.badge")}
</span>
{/if}
</Button>
<Button
class="mb-2 ml-2 mt-2"
class="h-8 px-2 text-xs"
variant="secondary"
on:click={copyUptimeBadge}
>
{#if !copiedBadgeUptime}
<Percent class="mr-2 inline" size={12} />
<span class="text-sm font-medium">
<span class="font-medium">
{l(lang, "monitor.uptime")}
{l(lang, "monitor.badge")}
</span>
{:else}
<CopyCheck class="mr-2 inline" size={12} />
<span class="text-sm font-medium">
<span class="font-medium">
{l(lang, "monitor.copied")}
{l(lang, "monitor.badge")}
</span>
{/if}
</Button>
</Popover.Content>
</Popover.Root>
</div>
</div>
<div class="">
<div class="grid grid-cols-2 gap-0">
<div class="col-span-1 -mt-2">
<a
href="{base}/incident/{monitor.folderName}#past_incident"
class="pb-0 pl-0 pt-0 text-left text-indigo-500 {buttonVariants({
variant: 'link'
})}"
>
{l(lang, "root.recent_incidents")}
<ArrowRight size={16} />
</a>
</div>
</div>
</div>
<hr />
<div class="p-4">
<h2 class="mb-1 text-sm font-semibold">
{l(lang, "monitor.status_svg")}
</h2>
<p class="mb-2 text-xs text-muted-foreground">
{l(lang, "monitor.status_svg_desc")}
</p>
<Button
class="h-8 px-2 text-xs"
variant="secondary"
on:click={copyDotStandard}
>
{#if !copiedBadgeDotStandard}
<img src={pathMonitorBadgeDot} class="mr-1 inline h-5" />
<span class="font-medium">
{l(lang, "monitor.standard")}
</span>
{:else}
<CopyCheck class="mr-2 inline h-5 w-5" />
<span class="font-medium">
{l(lang, "monitor.standard")}
</span>
{/if}
</Button>
<Button
class="h-8 px-2 text-xs"
variant="secondary"
on:click={copyDotPing}
>
{#if !copiedBadgeDotPing}
<img src={pathMonitorBadgeDotPing} class="mr-1 inline h-5" />
<span class="font-medium">
{l(lang, "monitor.pinging")}
</span>
{:else}
<CopyCheck class="mr-2 inline h-5 w-5" />
<span class="font-medium"> {l(lang, "monitor.pinging")} </span>
{/if}
</Button>
</div>
</Popover.Content>
</Popover.Root>
</div>
</div>
{/if}
</div>
<div
class="col-span-12 md:w-[546px] {monitor.embed === undefined
? 'md:col-span-8'
? 'md:col-span-12'
: 'overflow-hidden'} pt-2"
>
<div class="col-span-12">
@@ -349,36 +397,37 @@
<div
class="{monitor.embed === undefined
? 'col-span-12'
: 'col-span-8'} h-[32px] md:col-span-8"
: 'col-span-8'} md:col-span-8"
>
<button
class="inline-block"
class="inline-block border-r pr-3 text-xs font-semibold {view != '90day'
? 'text-muted-foreground opacity-70'
: 'text-primary'}"
on:click={(e) => {
switchView("90day");
}}
>
<Badge variant={view != "90day" ? "outline" : ""}>
{l(lang, "monitor.90_day")}{n(lang, uptime90Day)}%
</Badge>
{l(lang, "monitor.90_day")}{n(lang, uptime90Day)}%
</button>
<button
class="ml-2 inline-block text-xs font-semibold {view != '0day'
? 'text-muted-foreground opacity-70'
: 'text-primary'}"
on:click={(e) => {
switchView("0day");
}}
>
<Badge variant={view != "0day" ? "outline" : ""}>
{l(lang, "monitor.today")}{n(lang, uptime0Day)}%
</Badge>
{l(lang, "monitor.today")}{n(lang, uptime0Day)}%
</button>
</div>
<div
class="{monitor.embed === undefined
? 'col-span-12'
: 'col-span-4'} h-[32px] text-right md:col-span-4"
: 'col-span-4'} text-right md:col-span-4"
>
{#if _90Day[todayDD]}
<div
class="text-api-up mt-[4px] truncate text-sm font-semibold text-{_90Day[
class="text-api-up mt-[4px] truncate text-xs font-semibold text-{_90Day[
todayDD
].cssClass}"
title={_90Day[todayDD].message}
@@ -398,7 +447,7 @@
></div>
</div>
<div class="show-hover absolute bg-background text-sm">
<div class="text-{bar.cssClass} font-semibold">
<div class="text-{bar.cssClass} pt-1 text-xs font-semibold">
{n(lang, new Date(bar.timestamp * 1000).toLocaleDateString())}
{summaryTime(lang, bar.message)}
</div>
@@ -445,6 +494,14 @@
</div>
</div>
{/if}
<p class="text-right">
<a
href="{base}/incident/{monitor.folderName}#past_incident"
class="text-xs font-semibold text-primary"
>
{l(lang, "root.recent_incidents")}
</a>
</p>
</div>
</div>
</div>

View File

@@ -4,91 +4,55 @@
import { Languages, Menu } from "lucide-svelte";
import { base } from "$app/paths";
export let data;
let defaultLocaleKey = data.selectedLang;
const allLocales = data.site.i18n?.locales;
/**
* @type {string}
*/
let defaultLocaleValue;
if (!allLocales) {
defaultLocaleValue = "English";
} else {
defaultLocaleValue = allLocales[defaultLocaleKey];
}
/**
* @param {string} locale
*/
function setLanguage(locale) {
document.cookie = `localLang=${locale};max-age=${60 * 60 * 24 * 365 * 30}`;
if (locale === defaultLocaleKey) return;
defaultLocaleValue = allLocales[locale];
location.reload();
}
let defaultPattern = data.site?.pattern || "squares";
</script>
<div class="one"></div>
<div class="{defaultPattern}-pattern"></div>
<header class="relative z-50 w-full">
<header class="blurry-bg relative z-50 mx-auto mt-4 max-w-[840px]">
<div class="container flex h-14 items-center">
<a
href={data.site.home ? data.site.home : base}
class="mr-6 flex items-center space-x-2"
>
{#if data.site.logo}
<img src={data.site.logo} class="h-8" alt={data.site.title} srcset="" />
{/if}
{#if data.site.title}
<span class="hidden text-[15px] font-bold md:inline-block lg:text-base">
{data.site.title}
</span>
{/if}
</a>
<div class="blurry-bg flex w-full justify-end">
<a href={data.site.home ? data.site.home : base} class="mr-6 flex items-center space-x-2">
{#if data.site.logo}
<img src={data.site.logo} class="h-8" alt={data.site.title} srcset="" />
{/if}
{#if data.site.siteName}
<span class="hidden text-[15px] font-bold md:inline-block lg:text-base">
{data.site.siteName}
</span>
{/if}
</a>
<div class="flex w-full justify-end">
{#if data.site.nav}
<nav class=" flex-wrap mr-4 items-center space-x-6 text-sm font-medium hidden md:flex">
<nav
class="mr-4 hidden flex-wrap items-center space-x-6 text-sm font-medium md:flex"
>
{#each data.site.nav as navItem}
<a href={navItem.url}> {navItem.name} </a>
<a href={navItem.url} class="flex">
{#if navItem.iconURL}
<img
src={navItem.iconURL}
class="mr-1.5 inline h-4"
alt={navItem.name}
/>
{/if}
<span>{navItem.name}</span>
</a>
{/each}
</nav>
<DropdownMenu.Root class="">
<DropdownMenu.Trigger class="mr-2 flex md:hidden">
<Button variant="outline" size="sm">
<Menu size={14} />
<Menu size={14} />
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
{#each data.site.nav as navItem}
<DropdownMenu.Group>
<DropdownMenu.Group>
<DropdownMenu.Item>
<a href={navItem.url}> {navItem.name} </a>
</DropdownMenu.Item>
</DropdownMenu.Group>
{/each}
</DropdownMenu.Content>
</DropdownMenu.Root>
{/if}
{#if data.site.i18n && data.site.i18n.locales && Object.keys(data.site.i18n.locales).length > 1}
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<Button variant="outline" size="sm">
<Languages size={14} class="mr-2" />
{defaultLocaleValue}
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Group>
{#each Object.entries(allLocales) as [key, value]}
<DropdownMenu.Item
on:click={(e) => {
setLanguage(key);
}}>{value}</DropdownMenu.Item
>
{/each}
</DropdownMenu.Group>
</DropdownMenu.Group>
{/each}
</DropdownMenu.Content>
</DropdownMenu.Root>
{/if}

View File

@@ -1,36 +1,13 @@
import { FOLDER, FOLDER_MONITOR, FOLDER_SITE, ENV } from "./constants.js";
import { IsStringURLSafe } from "./tool.js";
// @ts-nocheck
import { ENV } from "$lib/server/constants.js";
import { IsStringURLSafe } from "$lib/server/tool.js";
import dotenv from "dotenv";
dotenv.config();
import fs from "fs-extra";
let STATUS_OK = false;
if (!!process.env.PUBLIC_KENER_FOLDER) {
console.log(`✅ PUBLIC_KENER_FOLDER is ${process.env.PUBLIC_KENER_FOLDER}`);
} else {
console.log(`❌ process.env.PUBLIC_KENER_FOLDER is not set
Set PUBLIC_KENER_FOLDER as an environment variable. Value should be the path to a directory where kener will store its data.
Example:
export PUBLIC_KENER_FOLDER=${process.cwd()}/static/kener`);
process.exit(1);
}
if (!fs.existsSync(FOLDER)) {
console.log(`❌ Directory does not exist\n\nRun:\nmkdir -p ${FOLDER}`);
process.exit(1);
}
if (!fs.existsSync(FOLDER_SITE)) {
fs.writeFileSync(FOLDER_SITE, JSON.stringify({}));
console.log("✅ site.json file created successfully!");
}
if (!fs.existsSync(FOLDER_MONITOR)) {
fs.writeFileSync(FOLDER_MONITOR, JSON.stringify([]));
console.log("✅ monitors.json file created successfully!");
}
if (ENV === undefined) {
console.log(`❗ process.env.NODE_ENV is not set`);
console.log(`❗ process.env.NODE_ENV is not set. Defaulting to development`);
} else {
console.log(`✅ process.env.NODE_ENV is set. Value is ${ENV}`);
}

View File

@@ -5,6 +5,7 @@
api:
method: GET
url: https://www.google.com/webhp
hideURLForGet: true
- name: Svelte Website
description: Cybernetically enhanced web apps
tag: "svelte-website"
@@ -17,6 +18,7 @@
tag: "earth"
defaultStatus: "UP"
image: "/earth.png"
cron: "*/2 * * * *"
- name: Frogment
description: A free openAPI spec editor and linter that breaks down your spec into fragments to make editing easier and more intuitive. Visit https://www.frogment.com
tag: "frogment"
@@ -24,3 +26,10 @@
api:
method: GET
url: https://www.frogment.com
- name: OkBookmarks
description: Stop forgetting about your bookmarks
tag: "okbookmarks"
image: "https://okbookmarks.com/app/mybookmark.png"
api:
method: GET
url: https://okbookmarks.com/

View File

@@ -1,4 +1,5 @@
title: "Kener"
title: "Kener - Open-Source and Modern looking Node.js Status Page for Effortless Incident Management"
siteName: "Kener.ing"
home: "/"
logo: "/logo.png"
github:
@@ -23,7 +24,11 @@ nav:
- name: "Documentation"
url: "/docs"
- name: "Github"
iconURL: "/github.svg"
url: "https://github.com/rajnandan1/kener"
- name: "Buy me a coffee"
iconURL: "/buymeacoffee.svg"
url: "https://buymeacoffee.com/rajnandan1"
hero:
title: Kener is a Open-Source Status Page System
subtitle: Let your users know what's going on.
@@ -42,3 +47,7 @@ i18n:
ja: "日本語"
vi: "Tiếng Việt"
theme: dark
pattern: "squares"
font:
cssSrc: "https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap"
family: "\"Lato\", sans-serif"

View File

@@ -1,15 +1,13 @@
// @ts-nocheck
// Define your constants
import dotenv from "dotenv";
dotenv.config();
const FOLDER = process.env.PUBLIC_KENER_FOLDER;
const ENV = process.env.NODE_ENV;
const MONITOR = "./config/monitors.yaml";
const SITE = "./config/site.yaml";
const FOLDER_MONITOR = FOLDER + "/monitors.json";
const FOLDER_SITE = FOLDER + "/site.json";
const UP = "UP";
const DOWN = "DOWN";
const DEGRADED = "DEGRADED";
const API_TIMEOUT = 10 * 1000; // 10 seconds
// Export the constants
export { FOLDER, FOLDER_MONITOR, FOLDER_SITE, MONITOR, UP, DOWN, SITE, DEGRADED, API_TIMEOUT, ENV };
export { MONITOR, UP, DOWN, SITE, DEGRADED, API_TIMEOUT, ENV };

View File

@@ -1,19 +1,26 @@
// @ts-nocheck
import axios from "axios";
import ping from "ping";
import fs from "fs-extra";
import { UP, DOWN, DEGRADED } from "./constants.js";
import { UP, DOWN, DEGRADED } from "$lib/server/constants.js";
import {
GetNowTimestampUTC,
GetMinuteStartNowTimestampUTC,
GetMinuteStartTimestampUTC
} from "./tool.js";
import { GetIncidents, GetEndTimeFromBody, GetStartTimeFromBody, CloseIssue } from "./github.js";
} from "$lib/server/tool.js";
import {
GetIncidents,
GetEndTimeFromBody,
GetStartTimeFromBody,
CloseIssue
} from "$lib/server/github.js";
import Randomstring from "randomstring";
import Queue from "queue";
import dotenv from "dotenv";
import path from "path";
dotenv.config();
const Kener_folder = process.env.PUBLIC_KENER_FOLDER;
const Kener_folder = path.resolve("src/lib/server/data");
const apiQueue = new Queue({
concurrency: 10, // Number of tasks that can run concurrently
timeout: 10000, // Timeout in ms after which a task will be considered as failed (optional)
@@ -295,7 +302,9 @@ const updateDayData = async (mergedData, startOfMinute, monitor) => {
};
const Minuter = async (envSecrets, monitor, githubConfig) => {
if (apiQueue.length > 0) console.log("Queue length is " + apiQueue.length);
if (apiQueue.length > 0) {
console.log("Queue length is " + apiQueue.length);
}
let apiData = {};
let pingData = {};
let webhookData = {};

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,94 @@
[
{
"name": "Google Search",
"description": "Search the world's information, including webpages, images, videos and more.",
"tag": "google-search",
"image": "/google.png",
"api": {
"method": "GET",
"url": "https://www.google.com/webhp",
"hideURLForGet": true,
"eval": "(function (statusCode, responseTime, responseData) {\n\tlet statusCodeShort = Math.floor(statusCode/100);\n if(statusCode == 429 || (statusCodeShort >=2 && statusCodeShort <= 3)) {\n return {\n\t\t\tstatus: 'UP',\n\t\t\tlatency: responseTime,\n }\n } \n\treturn {\n\t\tstatus: 'DOWN',\n\t\tlatency: responseTime,\n\t}\n})",
"timeout": 10000
},
"folderName": "google-search",
"dayDegradedMinimumCount": 1,
"dayDownMinimumCount": 1,
"includeDegradedInDowntime": false,
"path0Day": "/Users/rajnandan1/Code/kener/src/lib/server/data/google-search.0day.utc.json",
"path90Day": "/Users/rajnandan1/Code/kener/src/lib/server/data/google-search.90day.utc.json",
"hasAPI": true
},
{
"name": "Svelte Website",
"description": "Cybernetically enhanced web apps <a href=\"https://svelte.dev/\" class=\"font-medium underline underline-offset-4\" target=\"_blank\">https://svelte.dev/</a>",
"tag": "svelte-website",
"api": {
"method": "GET",
"url": "https://svelte.dev/",
"eval": "(function (statusCode, responseTime, responseData) {\n\tlet statusCodeShort = Math.floor(statusCode/100);\n if(statusCode == 429 || (statusCodeShort >=2 && statusCodeShort <= 3)) {\n return {\n\t\t\tstatus: 'UP',\n\t\t\tlatency: responseTime,\n }\n } \n\treturn {\n\t\tstatus: 'DOWN',\n\t\tlatency: responseTime,\n\t}\n})",
"timeout": 10000
},
"image": "/svelte.svg",
"folderName": "svelte-website",
"dayDegradedMinimumCount": 1,
"dayDownMinimumCount": 1,
"includeDegradedInDowntime": false,
"path0Day": "/Users/rajnandan1/Code/kener/src/lib/server/data/svelte-website.0day.utc.json",
"path90Day": "/Users/rajnandan1/Code/kener/src/lib/server/data/svelte-website.90day.utc.json",
"hasAPI": true
},
{
"name": "Earth",
"description": "Our blue planet",
"tag": "earth",
"defaultStatus": "UP",
"image": "/earth.png",
"cron": "*/2 * * * *",
"folderName": "earth",
"dayDegradedMinimumCount": 1,
"dayDownMinimumCount": 1,
"includeDegradedInDowntime": false,
"path0Day": "/Users/rajnandan1/Code/kener/src/lib/server/data/earth.0day.utc.json",
"path90Day": "/Users/rajnandan1/Code/kener/src/lib/server/data/earth.90day.utc.json",
"hasAPI": false
},
{
"name": "Frogment",
"description": "A free openAPI spec editor and linter that breaks down your spec into fragments to make editing easier and more intuitive. Visit https://www.frogment.com <a href=\"https://www.frogment.com\" class=\"font-medium underline underline-offset-4\" target=\"_blank\">https://www.frogment.com</a>",
"tag": "frogment",
"image": "/frogment.png",
"api": {
"method": "GET",
"url": "https://www.frogment.com",
"eval": "(function (statusCode, responseTime, responseData) {\n\tlet statusCodeShort = Math.floor(statusCode/100);\n if(statusCode == 429 || (statusCodeShort >=2 && statusCodeShort <= 3)) {\n return {\n\t\t\tstatus: 'UP',\n\t\t\tlatency: responseTime,\n }\n } \n\treturn {\n\t\tstatus: 'DOWN',\n\t\tlatency: responseTime,\n\t}\n})",
"timeout": 10000
},
"folderName": "frogment",
"dayDegradedMinimumCount": 1,
"dayDownMinimumCount": 1,
"includeDegradedInDowntime": false,
"path0Day": "/Users/rajnandan1/Code/kener/src/lib/server/data/frogment.0day.utc.json",
"path90Day": "/Users/rajnandan1/Code/kener/src/lib/server/data/frogment.90day.utc.json",
"hasAPI": true
},
{
"name": "OkBookmarks",
"description": "Stop forgetting about your bookmarks <a href=\"https://okbookmarks.com/\" class=\"font-medium underline underline-offset-4\" target=\"_blank\">https://okbookmarks.com/</a>",
"tag": "okbookmarks",
"image": "https://okbookmarks.com/app/mybookmark.png",
"api": {
"method": "GET",
"url": "https://okbookmarks.com/",
"eval": "(function (statusCode, responseTime, responseData) {\n\tlet statusCodeShort = Math.floor(statusCode/100);\n if(statusCode == 429 || (statusCodeShort >=2 && statusCodeShort <= 3)) {\n return {\n\t\t\tstatus: 'UP',\n\t\t\tlatency: responseTime,\n }\n } \n\treturn {\n\t\tstatus: 'DOWN',\n\t\tlatency: responseTime,\n\t}\n})",
"timeout": 10000
},
"folderName": "okbookmarks",
"dayDegradedMinimumCount": 1,
"dayDownMinimumCount": 1,
"includeDegradedInDowntime": false,
"path0Day": "/Users/rajnandan1/Code/kener/src/lib/server/data/okbookmarks.0day.utc.json",
"path90Day": "/Users/rajnandan1/Code/kener/src/lib/server/data/okbookmarks.90day.utc.json",
"hasAPI": true
}
]

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,63 @@
{
"title": "Kener - Open-Source and Modern looking Node.js Status Page for Effortless Incident Management",
"siteName": "Kener.ing",
"home": "/",
"logo": "/logo.png",
"github": {
"owner": "rajnandan1",
"repo": "kener",
"incidentSince": 48
},
"metaTags": {
"description": "Kener: Open-source modern looking Node.js status page tool, designed to make service monitoring and incident handling a breeze. It offers a sleek and user-friendly interface that simplifies tracking service outages and improves how we communicate during incidents. And the best part? Kener integrates seamlessly with GitHub, making incident management a team effort—making it easier for us to track and fix issues together in a collaborative and friendly environment.",
"keywords": "Node.js status page, Incident management tool, Service monitoring, Service outage tracking, Real-time status updates, GitHub integration for incidents, Open-source status page, Node.js monitoring application, Service reliability, User-friendly incident management, Collaborative incident resolution, Seamless outage communication, Service disruption tracker, Real-time incident alerts, Node.js status reporting",
"og:description": "Kener: Open-source Node.js status page tool, designed to make service monitoring and incident handling a breeze. It offers a sleek and user-friendly interface that simplifies tracking service outages and improves how we communicate during incidents. And the best part? Kener integrates seamlessly with GitHub, making incident management a team effort—making it easier for us to track and fix issues together in a collaborative and friendly environment.",
"og:image": "https://kener.ing/ss.png",
"og:title": "Kener - Open-Source and Modern looking Node.js Status Page for Effortless Incident Management",
"og:type": "website",
"og:site_name": "Kener",
"twitter:card": "summary_large_image",
"twitter:site": "@_rajnandan_",
"twitter:creator": "@_rajnandan_",
"twitter:image": "https://kener.ing/ss.png",
"twitter:title": "Kener: Open-Source and Modern looking Node.js Status Page for Effortless Incident Management",
"twitter:description": "Kener: Open-source Node.js status page tool, designed to make service monitoring and incident handling a breeze. It offers a sleek and user-friendly interface that simplifies tracking service outages and improves how we communicate during incidents. And the best part? Kener integrates seamlessly with GitHub, making incident management a team effort—making it easier for us to track and fix issues together in a collaborative and friendly environment."
},
"nav": [
{
"name": "Documentation",
"url": "/docs"
},
{
"name": "Github",
"iconURL": "/github.svg",
"url": "https://github.com/rajnandan1/kener"
},
{
"name": "Buy me a coffee",
"iconURL": "/buymeacoffee.svg",
"url": "https://buymeacoffee.com/rajnandan1"
}
],
"hero": {
"title": "Kener is a Open-Source Status Page System",
"subtitle": "Let your users know what's going on."
},
"footerHTML": "Made using \n<a href=\"https://github.com/rajnandan1/kener\" target=\"_blank\" rel=\"noreferrer\" class=\"font-medium underline underline-offset-4\">\n Kener\n</a>\nan open source status page system built with Svelte and TailwindCSS.\n",
"i18n": {
"defaultLocale": "en",
"locales": {
"en": "English",
"hi": "हिन्दी",
"zh-CN": "中文",
"ja": "日本語",
"vi": "Tiếng Việt"
}
},
"theme": "dark",
"pattern": "squares",
"font": {
"cssSrc": "https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap",
"family": "\"Lato\", sans-serif"
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
// @ts-nocheck
import axios from "axios";
import { GetMinuteStartNowTimestampUTC } from "./tool.js";
import { GetMinuteStartNowTimestampUTC } from "$lib/server/tool.js";
import { marked } from "marked";
import { fileURLToPath } from "url";
import { dirname } from "path";

View File

@@ -1,6 +1,7 @@
// @ts-nocheck
import fs from "fs-extra";
import { GetMinuteStartNowTimestampUTC, BeginningOfDay } from "./tool.js";
import { StatusObj, ParseUptime } from "../src/lib/helpers.js";
import { GetMinuteStartNowTimestampUTC, BeginningOfDay } from "$lib/server/tool.js";
import { StatusObj, ParseUptime } from "$lib/helpers.js";
function getDayMessage(type, numOfMinute) {
if (numOfMinute > 59) {

View File

@@ -1,3 +1,4 @@
// @ts-nocheck
/*
The startup js script will
check if monitors.yaml exists
@@ -7,20 +8,25 @@ name of each of these objects need to be unique
*/
import * as dotenv from "dotenv";
import fs from "fs-extra";
import path from "path";
import yaml from "js-yaml";
import { Cron } from "croner";
import { FOLDER, FOLDER_MONITOR, FOLDER_SITE, API_TIMEOUT } from "./constants.js";
import { API_TIMEOUT } from "$lib/server/constants.js";
import siteDataRaw from "$lib/server/config/site.yaml?raw";
import monitorDataRaw from "$lib/server/config/monitors.yaml?raw";
import {
IsValidURL,
IsValidHTTPMethod,
LoadMonitorsPath,
LoadSitePath,
ValidateIpAddress
} from "./tool.js";
import { GetAllGHLabels, CreateGHLabel } from "./github.js";
import { Minuter } from "./cron-minute.js";
} from "$lib/server/tool.js";
import { GetAllGHLabels, CreateGHLabel } from "$lib/server/github.js";
import { Minuter } from "$lib/server/cron-minute.js";
import axios from "axios";
import { Ninety } from "./ninety.js";
import { Ninety } from "$lib/server/ninety.js";
let monitors = [];
let site = {};
const envSecrets = [];
@@ -37,7 +43,6 @@ const defaultEval = `(function (statusCode, responseTime, responseData) {
latency: responseTime,
}
})`;
function checkIfDuplicateExists(arr) {
return new Set(arr).size !== arr.length;
}
@@ -46,20 +51,18 @@ function getWordsStartingWithDollar(text) {
const wordsArray = text.match(regex);
return wordsArray || [];
}
if (!fs.existsSync(FOLDER)) {
fs.mkdirSync(FOLDER);
console.log(".kener folder created successfully!");
}
const Startup = async () => {
try {
const fileContent = fs.readFileSync(LoadMonitorsPath(), "utf8");
site = yaml.load(fs.readFileSync(LoadSitePath(), "utf8"));
monitors = yaml.load(fileContent);
site = yaml.load(siteDataRaw);
monitors = yaml.load(monitorDataRaw);
} catch (error) {
console.log(error);
process.exit(1);
}
const FOLDER = path.resolve("src/lib/server/data");
const FOLDER_SITE = path.resolve(FOLDER + "/site.json");
const FOLDER_MONITOR = path.resolve(FOLDER + "/monitors.json");
// Use the 'monitors' array of JSON objects as needed
//check if each object has name, url, method
@@ -143,6 +146,7 @@ const Startup = async () => {
let evaluator = monitor.api.eval;
let body = monitor.api.body;
let timeout = monitor.api.timeout;
let hideURLForGet = !!monitor.api.hideURLForGet;
//url
if (!!url) {
if (!IsValidURL(url)) {
@@ -168,7 +172,7 @@ const Startup = async () => {
try {
JSON.parse(JSON.stringify(headers));
} catch (error) {
console.log("headers are not valid. Quiting");
console.log("headers are not valid. Quitting");
process.exit(1);
}
}
@@ -213,9 +217,10 @@ const Startup = async () => {
}
//add a description to the monitor if it is website using api.url and method = GET and headers == undefined
//call the it to see if recevied content-type is text/html
//call the it to see if received content-type is text/html
//if yes, append to description
if (
!hideURLForGet &&
(headers === undefined || headers === null) &&
url !== undefined &&
method === "GET"
@@ -260,6 +265,7 @@ const Startup = async () => {
}
}
}
if (
site.github === undefined ||
site.github.owner === undefined ||
@@ -271,6 +277,12 @@ const Startup = async () => {
if (site.github.incidentSince === undefined || site.github.incidentSince === null) {
site.github.incidentSince = 48;
}
if (!!!site.font || !!!site.font.cssSrc || !!!site.font.family) {
site.font = {
cssSrc: "https://fonts.googleapis.com/css2?family=Albert+Sans:ital,wght@0,100..900;1,100..900&display=swap",
family: "Albert Sans"
};
}
if (checkIfDuplicateExists(monitors.map((monitor) => monitor.folderName)) === true) {
console.log("duplicate monitor detected");
process.exit(1);
@@ -345,7 +357,6 @@ const Startup = async () => {
}
}
}
// init monitors
for (let i = 0; i < monitors.length; i++) {
const monitor = monitors[i];
@@ -362,7 +373,6 @@ const Startup = async () => {
await Minuter(envSecrets, monitor, site.github);
await Ninety(monitor);
}
//trigger minute cron
for (let i = 0; i < monitors.length; i++) {

View File

@@ -1,5 +1,5 @@
// @ts-nocheck
import { MONITOR, SITE } from "./constants.js";
import { MONITOR, SITE } from "$lib/server/constants.js";
import dotenv from "dotenv";
dotenv.config();
const IsValidURL = function (url) {

View File

@@ -1,23 +1,24 @@
// @ts-nocheck
import fs from "fs-extra";
import { PUBLIC_KENER_FOLDER } from "$env/static/public";
import monitorJSON from "$lib/server/data/monitors.json?raw";
import { ParseUptime } from "$lib/helpers.js";
import {
GetMinuteStartNowTimestampUTC,
GetNowTimestampUTC,
GetMinuteStartTimestampUTC
} from "../../../scripts/tool.js";
import { GetStartTimeFromBody, GetEndTimeFromBody } from "../../../scripts/github.js";
} from "$lib/server/tool.js";
import { GetStartTimeFromBody, GetEndTimeFromBody } from "$lib/server/github.js";
import Randomstring from "randomstring";
const API_TOKEN = process.env.API_TOKEN;
const API_IP = process.env.API_IP;
const API_IP_REGEX = process.env.API_IP_REGEX;
import path from "path";
const GetAllTags = function () {
let tags = [];
let monitors = [];
try {
monitors = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/monitors.json", "utf8"));
monitors = JSON.parse(monitorJSON);
tags = monitors.map((monitor) => monitor.tag);
} catch (err) {
return [];
@@ -28,7 +29,7 @@ const CheckIfValidTag = function (tag) {
let tags = [];
let monitors = [];
try {
monitors = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/monitors.json", "utf8"));
monitors = JSON.parse(monitorJSON);
tags = monitors.map((monitor) => monitor.tag);
if (tags.indexOf(tag) == -1) {
throw new Error("not a valid tag");
@@ -112,7 +113,7 @@ const store = function (data) {
}
//get the monitor object matching the tag
let monitors = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/monitors.json", "utf8"));
let monitors = JSON.parse(monitorJSON);
const monitor = monitors.find((monitor) => monitor.tag === tag);
//read the monitor.path0Day file
@@ -123,10 +124,10 @@ const store = function (data) {
//create a random string with high cardinlity
//to avoid cache
const Kener_folder = path.resolve("src/lib/server/data");
//write the monitor.path0Day file
fs.writeFileSync(
PUBLIC_KENER_FOLDER + `/${monitor.folderName}.webhook.${Randomstring.generate()}.json`,
Kener_folder + `/${monitor.folderName}.webhook.${Randomstring.generate()}.json`,
JSON.stringify(day0, null, 2)
);
@@ -259,7 +260,7 @@ const GetMonitorStatusByTag = function (tag) {
uptime: null,
lastUpdatedAt: null
};
let monitors = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/monitors.json", "utf8"));
let monitors = JSON.parse(monitorJSON);
const { path0Day } = monitors.find((monitor) => monitor.tag === tag);
const dayData = JSON.parse(fs.readFileSync(path0Day, "utf8"));
const lastUpdatedAt = Object.keys(dayData)[Object.keys(dayData).length - 1];

View File

@@ -1,9 +1,10 @@
// @ts-nocheck
import fs from "fs-extra";
import { PUBLIC_KENER_FOLDER } from "$env/static/public";
import i18n from "$lib/i18n/server";
import siteJSON from "$lib/server/data/site.json?raw";
export async function load({ params, route, url, cookies, request }) {
let site = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/site.json", "utf8"));
let site = JSON.parse(siteJSON);
const headers = request.headers;
const userAgent = headers.get("user-agent");
let localTz = "GMT";

View File

@@ -4,9 +4,55 @@
import Nav from "$lib/components/nav.svelte";
import { onMount } from "svelte";
import { base } from "$app/paths";
import { Button } from "$lib/components/ui/button";
import { ModeWatcher } from "mode-watcher";
import Sun from "lucide-svelte/icons/sun";
import Moon from "lucide-svelte/icons/moon";
import { Languages } from "lucide-svelte";
import * as DropdownMenu from "$lib/components/ui/dropdown-menu";
export let data;
let defaultLocaleKey = data.selectedLang;
let defaultTheme = data.site?.theme || "light";
const allLocales = data.site.i18n?.locales;
function toggleMode(defaultTheme) {
let classList = document.documentElement.classList;
if (classList.contains("dark")) {
classList.remove("dark");
localStorage.setItem("theme", "light");
} else {
classList.add("dark");
localStorage.setItem("theme", "dark");
}
}
let defaultLocaleValue;
if (!allLocales) {
defaultLocaleValue = "English";
} else {
defaultLocaleValue = allLocales[defaultLocaleKey];
}
/**
* @param {string} locale
*/
function setLanguage(locale) {
document.cookie = `localLang=${locale};max-age=${60 * 60 * 24 * 365 * 30}`;
if (locale === defaultLocaleKey) return;
defaultLocaleValue = allLocales[locale];
location.reload();
}
function setTheme() {
let theme = localStorage.getItem("theme") || defaultTheme;
if (theme === "dark") {
document.documentElement.classList.add("dark");
} else {
document.documentElement.classList.remove("dark");
}
}
onMount(() => {
let localTz = Intl.DateTimeFormat().resolvedOptions().timeZone;
if (localTz != data.localTz) {
@@ -15,36 +61,76 @@
location.reload();
}
}
setTheme();
});
</script>
{#if data.showNav}
<Nav {data} />
{/if}
<svelte:head>
<title>{data.site.title}</title>
<link rel="icon" id="kener-app-favicon" href="{base}/logo96.png" />
<link href={data.site.font.cssSrc} rel="stylesheet" />
{#each Object.entries(data.site.metaTags) as [key, value]}
<meta name={key} content={value} />
{/each}
{#if !!data.site.theme && data.site.theme === "dark"}
<script>
document.documentElement.classList.add("dark");
</script>
{/if}
</svelte:head>
<main style="--font-family: {data.site.font.family}">
{#if data.showNav}
<Nav {data} />
{/if}
<div class="min-h-screen">
<slot />
</div>
<slot />
{#if data.showNav && !!data.site.footerHTML}
<footer class="z-10 py-6 md:px-8 md:py-0">
<div
class="container relative flex max-w-[890px] flex-col items-center justify-center gap-4 pl-0 md:h-24 md:flex-row"
>
<div class="flex flex-col items-center gap-4 px-8 md:flex-row md:gap-2 md:px-0">
<p class="text-center text-sm leading-loose text-muted-foreground md:text-left">
{@html data.site.footerHTML}
</p>
{#if data.showNav && !!data.site.footerHTML}
<footer class="z-10 py-6 md:px-8 md:py-0">
<div
class="container relative flex max-w-[840px] flex-col items-center justify-center gap-4 pl-0 md:h-24 md:flex-row"
>
<div class="flex flex-col items-center gap-4 px-8 md:flex-row md:gap-2 md:px-0">
<p class="text-center text-sm leading-loose text-muted-foreground md:text-left">
{@html data.site.footerHTML}
</p>
</div>
</div>
</div>
</footer>
{/if}
</footer>
{/if}
<div class="fixed bottom-4 right-4">
{#if data.site.i18n && data.site.i18n.locales && Object.keys(data.site.i18n.locales).length > 1}
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<Button variant="ghost" size="icon" class="flex">
<Languages class="h-[1.2rem] w-[1.2rem]" />
</Button>
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Group>
{#each Object.entries(allLocales) as [key, value]}
<DropdownMenu.Item
on:click={(e) => {
setLanguage(key);
}}>{value}</DropdownMenu.Item
>
{/each}
</DropdownMenu.Group>
</DropdownMenu.Content>
</DropdownMenu.Root>
{/if}
<Button on:click={toggleMode} variant="ghost" size="icon" class="flex">
<Sun
class="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0"
/>
<Moon
class="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100"
/>
<span class="sr-only">Toggle theme</span>
</Button>
</div>
</main>
<style>
/* Apply the global font family using the CSS variable */
* {
font-family: var(--font-family);
}
</style>

View File

@@ -1,15 +1,12 @@
// @ts-nocheck
import {
Mapper,
GetOpenIncidents,
FilterAndInsertMonitorInIncident
} from "../../scripts/github.js";
import { Mapper, GetOpenIncidents, FilterAndInsertMonitorInIncident } from "$lib/server/github.js";
import { FetchData } from "$lib/server/page";
import { PUBLIC_KENER_FOLDER } from "$env/static/public";
import fs from "fs-extra";
import monitorJSON from "$lib/server/data/monitors.json?raw";
export async function load({ parent }) {
let monitors = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/monitors.json", "utf8"));
let monitors = JSON.parse(monitorJSON);
const parentData = await parent();
const siteData = parentData.site;
const github = siteData.github;

View File

@@ -63,17 +63,17 @@
{/if}
{#if data.monitors.length > 0}
<section
class="mx-auto mb-4 flex w-full max-w-[890px] flex-1 flex-col items-start justify-center bg-transparent"
class="mx-auto mb-2 flex w-full flex-1 flex-col items-start justify-center bg-transparent md:w-[655px]"
id=""
>
<div class="grid w-full grid-cols-2 gap-4">
<div class="col-span-2 text-center md:col-span-1 md:text-left">
<Badge class="" variant="outline">
<Badge class="border-0 pl-0" variant="outline">
{l(data.lang, "root.availability_per_component")}
</Badge>
</div>
<div class="col-span-2 text-center md:col-span-1 md:text-right">
<Badge variant="outline">
<Badge variant="outline" class="border-0 pr-0">
<span class="bg-api-up mr-1 inline-flex h-[8px] w-[8px] rounded-full opacity-75"
></span>
<span class="mr-3">
@@ -90,7 +90,7 @@
<span
class="bg-api-down mr-1 inline-flex h-[8px] w-[8px] rounded-full opacity-75"
></span>
<span class="mr-3">
<span class="">
{l(data.lang, "statuses.DOWN")}
</span>
</Badge>
@@ -98,10 +98,10 @@
</div>
</section>
<section
class="mx-auto mb-8 flex w-full max-w-[890px] flex-1 flex-col items-start justify-center backdrop-blur-[2px]"
class="mx-auto mb-8 flex w-full flex-1 flex-col items-start justify-center backdrop-blur-[2px] md:w-[655px]"
>
<Card.Root>
<Card.Content class="monitors-card p-0">
<Card.Content class="monitors-card p-0">
{#each data.monitors as monitor}
<Monitor {monitor} localTz={data.localTz} lang={data.lang} />
{/each}

View File

@@ -2,8 +2,8 @@
// @ts-ignore
import { json } from "@sveltejs/kit";
import { ParseIncidentPayload, auth, GHIssueToKenerIncident } from "$lib/server/webhook";
import { CreateIssue, SearchIssue } from "../../../../scripts/github";
import { PUBLIC_KENER_FOLDER } from "$env/static/public";
import { CreateIssue, SearchIssue } from "$lib/server/github";
import siteJSON from "$lib/server/data/site.json?raw";
import fs from "fs-extra";
export async function POST({ request }) {
@@ -27,7 +27,7 @@ export async function POST({ request }) {
}
);
}
let site = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/site.json", "utf8"));
let site = JSON.parse(siteJSON);
let github = site.github;
let resp = await CreateIssue(github, title, body, githubLabels);
if (resp === null) {
@@ -74,7 +74,7 @@ export async function GET({ request, url }) {
}
);
}
let site = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/site.json", "utf8"));
let site = JSON.parse(siteJSON);
let github = site.github;
const repo = `${github.owner}/${github.repo}`;
const is = "issue";

View File

@@ -7,8 +7,8 @@ import {
GetStartTimeFromBody,
GetEndTimeFromBody,
UpdateIssue
} from "../../../../../scripts/github";
import { PUBLIC_KENER_FOLDER } from "$env/static/public";
} from "$lib/server/github";
import siteJSON from "$lib/server/data/site.json?raw";
import fs from "fs-extra";
export async function PATCH({ request, params }) {
@@ -41,7 +41,7 @@ export async function PATCH({ request, params }) {
);
}
let site = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/site.json", "utf8"));
let site = JSON.parse(siteJSON);
let github = site.github;
let resp = await UpdateIssue(github, incidentNumber, title, body, githubLabels);
if (resp === null) {
@@ -70,7 +70,7 @@ export async function GET({ request, params }) {
const incidentNumber = params.incidentNumber; //number required
// const headers = await request.headers();
let site = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/site.json", "utf8"));
let site = JSON.parse(siteJSON);
let github = site.github;
let issue = await GetIncidentByNumber(github, incidentNumber);
if (issue === null) {

View File

@@ -2,8 +2,8 @@
// @ts-ignore
import { json } from "@sveltejs/kit";
import { auth } from "$lib/server/webhook";
import { AddComment, GetCommentsForIssue } from "../../../../../../scripts/github";
import { PUBLIC_KENER_FOLDER } from "$env/static/public";
import { AddComment, GetCommentsForIssue } from "$lib/server/github";
import siteJSON from "$lib/server/data/site.json?raw";
import fs from "fs-extra";
export async function GET({ request, params }) {
@@ -27,7 +27,7 @@ export async function GET({ request, params }) {
);
}
let site = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/site.json", "utf8"));
let site = JSON.parse(siteJSON);
let github = site.github;
let resp = await GetCommentsForIssue(incidentNumber, github);
return json(
@@ -75,7 +75,7 @@ export async function POST({ request, params }) {
);
}
let site = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/site.json", "utf8"));
let site = JSON.parse(siteJSON);
let github = site.github;
let resp = await AddComment(github, incidentNumber, body);

View File

@@ -2,8 +2,8 @@
// @ts-ignore
import { json } from "@sveltejs/kit";
import { auth, GHIssueToKenerIncident } from "$lib/server/webhook";
import { UpdateIssueLabels, GetIncidentByNumber } from "../../../../../../scripts/github";
import { PUBLIC_KENER_FOLDER } from "$env/static/public";
import { UpdateIssueLabels, GetIncidentByNumber } from "$lib/server/github";
import siteJSON from "$lib/server/data/site.json?raw";
import fs from "fs-extra";
export async function POST({ request, params }) {
@@ -43,7 +43,7 @@ export async function POST({ request, params }) {
);
}
let site = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/site.json", "utf8"));
let site = JSON.parse(siteJSON);
let github = site.github;
let issue = await GetIncidentByNumber(github, incidentNumber);

View File

@@ -2,7 +2,7 @@
// @ts-ignore
import fs from "fs-extra";
import { json } from "@sveltejs/kit";
import { GetMinuteStartNowTimestampUTC, BeginningOfDay } from "../../../../scripts/tool.js";
import { GetMinuteStartNowTimestampUTC, BeginningOfDay } from "$lib/server/tool.js";
import { StatusObj } from "$lib/helpers.js";
export async function POST({ request }) {

View File

@@ -0,0 +1,49 @@
// @ts-nocheck
import monitorJSON from "$lib/server/data/monitors.json?raw";
import fs from "fs-extra";
import { StatusColor } from "$lib/helpers.js";
import { makeBadge } from "badge-maker";
const monitors = JSON.parse(monitorJSON);
export async function GET({ params, setHeaders, url }) {
// @ts-ignore
const { path0Day, name } = monitors.find((monitor) => monitor.tag === params.tag);
const dayData = JSON.parse(fs.readFileSync(path0Day, "utf8"));
const lastObj = dayData[Object.keys(dayData)[Object.keys(dayData).length - 1]];
//read query params
const query = url.searchParams;
const animate = query.get("animate") || "";
let svg = `
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg">
<circle cx="16" cy="16" r="8" fill="#${StatusColor[lastObj.status]}" />
</svg>
`;
if (animate == "ping") {
svg = `
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg">
<circle cx="16" cy="16" r="8" fill="#${StatusColor[lastObj.status]}" opacity="0.5">
<animate
attributeName="r"
from="8"
to="16"
dur="1s"
repeatCount="indefinite" />
<animate
attributeName="opacity"
from="0.5"
to="0"
dur="1s"
repeatCount="indefinite" />
</circle>
<circle cx="16" cy="16" r="8" fill="#${StatusColor[lastObj.status]}" />
</svg>
`;
}
return new Response(svg, {
headers: {
"Content-Type": "image/svg+xml"
}
});
}

View File

@@ -1,9 +1,9 @@
// @ts-nocheck
import { PUBLIC_KENER_FOLDER } from "$env/static/public";
import monitorJSON from "$lib/server/data/monitors.json?raw";
import fs from "fs-extra";
import { StatusColor } from "$lib/helpers.js";
import { makeBadge } from "badge-maker";
const monitors = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/monitors.json", "utf8"));
const monitors = JSON.parse(monitorJSON);
export async function GET({ params, setHeaders, url }) {
// @ts-ignore
const { path0Day, name } = monitors.find((monitor) => monitor.tag === params.tag);

View File

@@ -1,10 +1,10 @@
// @ts-nocheck
import { PUBLIC_KENER_FOLDER } from "$env/static/public";
import monitorJSON from "$lib/server/data/monitors.json?raw";
import fs from "fs-extra";
import { ParseUptime } from "$lib/helpers.js";
import { makeBadge } from "badge-maker";
const monitors = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/monitors.json", "utf8"));
const monitors = JSON.parse(monitorJSON);
export async function GET({ params, url }) {
// @ts-ignore
const { path0Day, name } = monitors.find((monitor) => monitor.tag === params.tag);

View File

@@ -1,15 +1,11 @@
// @ts-nocheck
import {
Mapper,
GetOpenIncidents,
FilterAndInsertMonitorInIncident
} from "../../../scripts/github.js";
import { Mapper, GetOpenIncidents, FilterAndInsertMonitorInIncident } from "$lib/server/github.js";
import { FetchData } from "$lib/server/page";
import { PUBLIC_KENER_FOLDER } from "$env/static/public";
import monitorJSON from "$lib/server/data/monitors.json?raw";
import fs from "fs-extra";
export async function load({ params, route, url, parent }) {
let monitors = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/monitors.json", "utf8"));
let monitors = JSON.parse(monitorJSON);
const parentData = await parent();
const siteData = parentData.site;
const github = siteData.github;

View File

@@ -1,10 +1,10 @@
// @ts-nocheck
import { FetchData } from "$lib/server/page";
import { PUBLIC_KENER_FOLDER } from "$env/static/public";
import monitorJSON from "$lib/server/data/monitors.json?raw";
import fs from "fs-extra";
export async function load({ params, route, url, parent }) {
let monitors = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/monitors.json", "utf8"));
let monitors = JSON.parse(monitorJSON);
const parentData = await parent();
const monitorsActive = [];

View File

@@ -1,8 +1,8 @@
// @ts-nocheck
// @ts-ignore
import { PUBLIC_KENER_FOLDER } from "$env/static/public";
import siteJSON from "$lib/server/data/site.json?raw";
import fs from "fs-extra";
const siteData = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/site.json", "utf8"));
const siteData = JSON.parse(siteJSON);
export async function GET({ url, params }) {
const { tag } = params;
const query = url.searchParams;

View File

@@ -1,6 +1,6 @@
// @ts-nocheck
import { PUBLIC_KENER_FOLDER } from "$env/static/public";
import { GetIncidents, Mapper } from "../../../../scripts/github.js";
import monitorJSON from "$lib/server/data/monitors.json?raw";
import { GetIncidents, Mapper } from "$lib/server/github.js";
import fs from "fs-extra";
/**
@@ -10,7 +10,7 @@ import fs from "fs-extra";
// @ts-ignore
export async function load({ params, route, url, parent }) {
let monitors = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/monitors.json", "utf8"));
let monitors = JSON.parse(monitorJSON);
const siteData = await parent();
const github = siteData.site.github;
// @ts-ignore

View File

@@ -27,7 +27,7 @@
</div>
</div>
</section>
<section class="mx-auto mb-4 mt-8 flex w-full flex-1 flex-col">
<section class="mx-auto mb-4 mt-8 flex w-full max-w-[840px] flex-1 flex-col">
<div class="container">
<h1 class="mb-4 text-2xl font-bold leading-none">
<Badge variant="outline">
@@ -57,7 +57,7 @@
<Separator class="container mb-4 w-[400px]" />
<section class="mx-auto mb-4 mt-8 flex w-full flex-1 flex-col">
<section class="mx-auto mb-4 mt-8 flex w-full max-w-[840px] flex-1 flex-col">
<div class="container">
<h1 class="mb-4 text-2xl font-bold leading-none">
<Badge variant="outline">

View File

@@ -1,14 +1,14 @@
// @ts-nocheck
// @ts-ignore
import { json } from "@sveltejs/kit";
import { PUBLIC_KENER_FOLDER } from "$env/static/public";
import fs from "fs-extra";
import { GetCommentsForIssue } from "../../../../../scripts/github.js";
import { GetCommentsForIssue } from "$lib/server/github.js";
import { marked } from "marked";
import siteJSON from "$lib/server/data/site.json?raw";
export async function GET({ params }) {
const incidentNumber = params.id;
let siteData = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/site.json", "utf8"));
let siteData = JSON.parse(siteJSON);
let comments = await GetCommentsForIssue(incidentNumber, siteData.github);
comments = comments.map(
(

View File

@@ -1,15 +1,11 @@
// @ts-nocheck
import {
Mapper,
GetOpenIncidents,
FilterAndInsertMonitorInIncident
} from "../../../scripts/github.js";
import { Mapper, GetOpenIncidents, FilterAndInsertMonitorInIncident } from "$lib/server/github.js";
import { FetchData } from "$lib/server/page";
import { PUBLIC_KENER_FOLDER } from "$env/static/public";
import monitorJSON from "$lib/server/data/monitors.json?raw";
import fs from "fs-extra";
export async function load({ params, route, url, parent }) {
let monitors = JSON.parse(fs.readFileSync(PUBLIC_KENER_FOLDER + "/monitors.json", "utf8"));
let monitors = JSON.parse(monitorJSON);
const parentData = await parent();
const siteData = parentData.site;
const github = siteData.github;

View File

@@ -20,7 +20,7 @@
<div class="mt-32"></div>
{#if hasActiveIncidents}
<section
class="mx-auto mb-4 flex w-full max-w-[890px] flex-1 flex-col items-start justify-center bg-transparent"
class="mx-auto mb-4 flex w-full max-w-[840px] flex-1 flex-col items-start justify-center bg-transparent"
id=""
>
<div class="grid w-full grid-cols-2 gap-4">
@@ -32,7 +32,7 @@
</div>
</section>
<section
class="mx-auto mb-8 flex w-full max-w-[890px] flex-1 flex-col items-start justify-center"
class="mx-auto mb-8 flex w-full max-w-[840px] flex-1 flex-col items-start justify-center"
id=""
>
{#each data.openIncidents as incident, i}
@@ -48,16 +48,11 @@
{/if}
{#if data.monitors.length > 0}
<section
class="mx-auto mb-4 flex w-full max-w-[890px] flex-1 flex-col items-start justify-center bg-transparent"
class="mx-auto mb-4 flex w-full max-w-[655px] flex-1 flex-col items-start justify-center bg-transparent"
id=""
>
<div class="grid w-full grid-cols-2 gap-4">
<div class="col-span-2 text-center md:col-span-1 md:text-left">
<Badge class="" variant="outline">
{l(data.lang, "root.availability_per_component")}
</Badge>
</div>
<div class="col-span-2 text-center md:col-span-1 md:text-right">
<div class="grid w-full grid-cols-1 justify-end gap-4">
<div class="col-span-1 text-center md:col-span-1 md:text-right">
<Badge variant="outline">
<span class="bg-api-up mr-1 inline-flex h-[8px] w-[8px] rounded-full opacity-75"
></span>
@@ -83,7 +78,7 @@
</div>
</section>
<section
class="mx-auto mb-8 flex w-full max-w-[890px] flex-1 flex-col items-start justify-center backdrop-blur-[2px]"
class="mx-auto mb-8 flex w-full max-w-[655px] flex-1 flex-col items-start justify-center backdrop-blur-[2px]"
>
<Card.Root class="w-full">
<Card.Content class="monitors-card p-0">

5
static/buymeacoffee.svg Normal file
View File

@@ -0,0 +1,5 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="#bea921">
<title>Buy Me A Coffee</title>
<path
d="M20.216 6.415l-.132-.666c-.119-.598-.388-1.163-1.001-1.379-.197-.069-.42-.098-.57-.241-.152-.143-.196-.366-.231-.572-.065-.378-.125-.756-.192-1.133-.057-.325-.102-.69-.25-.987-.195-.4-.597-.634-.996-.788a5.723 5.723 0 00-.626-.194c-1-.263-2.05-.36-3.077-.416a25.834 25.834 0 00-3.7.062c-.915.083-1.88.184-2.75.5-.318.116-.646.256-.888.501-.297.302-.393.77-.177 1.146.154.267.415.456.692.58.36.162.737.284 1.123.366 1.075.238 2.189.331 3.287.37 1.218.05 2.437.01 3.65-.118.299-.033.598-.073.896-.119.352-.054.578-.513.474-.834-.124-.383-.457-.531-.834-.473-.466.074-.96.108-1.382.146-1.177.08-2.358.082-3.536.006a22.228 22.228 0 01-1.157-.107c-.086-.01-.18-.025-.258-.036-.243-.036-.484-.08-.724-.13-.111-.027-.111-.185 0-.212h.005c.277-.06.557-.108.838-.147h.002c.131-.009.263-.032.394-.048a25.076 25.076 0 013.426-.12c.674.019 1.347.067 2.017.144l.228.031c.267.04.533.088.798.145.392.085.895.113 1.07.542.055.137.08.288.111.431l.319 1.484a.237.237 0 01-.199.284h-.003c-.037.006-.075.01-.112.015a36.704 36.704 0 01-4.743.295 37.059 37.059 0 01-4.699-.304c-.14-.017-.293-.042-.417-.06-.326-.048-.649-.108-.973-.161-.393-.065-.768-.032-1.123.161-.29.16-.527.404-.675.701-.154.316-.199.66-.267 1-.069.34-.176.707-.135 1.056.087.753.613 1.365 1.37 1.502a39.69 39.69 0 0011.343.376.483.483 0 01.535.53l-.071.697-1.018 9.907c-.041.41-.047.832-.125 1.237-.122.637-.553 1.028-1.182 1.171-.577.131-1.165.2-1.756.205-.656.004-1.31-.025-1.966-.022-.699.004-1.556-.06-2.095-.58-.475-.458-.54-1.174-.605-1.793l-.731-7.013-.322-3.094c-.037-.351-.286-.695-.678-.678-.336.015-.718.3-.678.679l.228 2.185.949 9.112c.147 1.344 1.174 2.068 2.446 2.272.742.12 1.503.144 2.257.156.966.016 1.942.053 2.892-.122 1.408-.258 2.465-1.198 2.616-2.657.34-3.332.683-6.663 1.024-9.995l.215-2.087a.484.484 0 01.39-.426c.402-.078.787-.212 1.074-.518.455-.488.546-1.124.385-1.766zm-1.478.772c-.145.137-.363.201-.578.233-2.416.359-4.866.54-7.308.46-1.748-.06-3.477-.254-5.207-.498-.17-.024-.353-.055-.47-.18-.22-.236-.111-.71-.054-.995.052-.26.152-.609.463-.646.484-.057 1.046.148 1.526.22.577.088 1.156.159 1.737.212 2.48.226 5.002.19 7.472-.14.45-.06.899-.13 1.345-.21.399-.072.84-.206 1.08.206.166.281.188.657.162.974a.544.544 0 01-.169.364zm-6.159 3.9c-.862.37-1.84.788-3.109.788a5.884 5.884 0 01-1.569-.217l.877 9.004c.065.78.717 1.38 1.5 1.38 0 0 1.243.065 1.658.065.447 0 1.786-.065 1.786-.065.783 0 1.434-.6 1.499-1.38l.94-9.95a3.996 3.996 0 00-1.322-.238c-.826 0-1.491.284-2.26.613z" />
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

5
static/github.svg Normal file
View File

@@ -0,0 +1,5 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="#2173bf">
<title>GitHub</title>
<path
d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
</svg>

After

Width:  |  Height:  |  Size: 845 B

View File

@@ -1,6 +1,16 @@
// @ts-nocheck
import { sveltekit } from "@sveltejs/kit/vite";
import { defineConfig } from "vite";
import dotenv from "dotenv";
dotenv.config();
const PORT = Number(process.env.PORT) || 3000;
export default defineConfig({
plugins: [sveltekit()]
plugins: [sveltekit()],
server: {
port: PORT,
watch: {
ignored: ["**/src/lib/server/data/**"] // Adjust the path to the file you want to ignore
}
},
assetsInclude: ["**/*.yaml"]
});