diff --git a/package-lock.json b/package-lock.json index 55700cdf..d73aa92b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5217,9 +5217,9 @@ } }, "node_modules/@expo/cli": { - "version": "0.22.23", - "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.22.23.tgz", - "integrity": "sha512-LXFKu2jnk9ClVD+kw0sJCQ89zei01wz2t4EJwc9P7EwYb8gabC8FtPyM/X7NIE5jtrnTLTUtjW5ovxQSBL7pJQ==", + "version": "0.22.24", + "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.22.24.tgz", + "integrity": "sha512-lhdenxBC8/x/vL39j79eXE09mOaqNNLmiSDdY/PblnI+UNzGgsQ48hBTYa/MQhd0ioXXVKurZL2941dLKwcxJw==", "license": "MIT", "optional": true, "peer": true, @@ -5237,12 +5237,12 @@ "@expo/osascript": "^2.1.6", "@expo/package-manager": "^1.7.2", "@expo/plist": "^0.2.2", - "@expo/prebuild-config": "^8.0.30", + "@expo/prebuild-config": "^8.0.31", "@expo/rudder-sdk-node": "^1.1.1", "@expo/spawn-async": "^1.7.2", "@expo/ws-tunnel": "^1.0.1", "@expo/xcpretty": "^4.3.0", - "@react-native/dev-middleware": "0.76.8", + "@react-native/dev-middleware": "0.76.9", "@urql/core": "^5.0.6", "@urql/exchange-retry": "^1.3.0", "accepts": "^1.3.8", @@ -6638,9 +6638,9 @@ } }, "node_modules/@expo/prebuild-config": { - "version": "8.0.30", - "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-8.0.30.tgz", - "integrity": "sha512-xNHWGh0xLZjxBXwVbDW+TPeexuQ95FZX2ZRrzJkALxhQiwYQswQSFE7CVUFMC2USIKVklCcgfEvtqnguTBQVxQ==", + "version": "8.0.31", + "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-8.0.31.tgz", + "integrity": "sha512-YTuS5ic9KolD/WA3GqgLcZytHQU1dpitlZ/cbDq8ZqkY+1ae5YWX+GkYEZf2VyECPaWnHYuDGddaTQVw5miTRg==", "license": "MIT", "optional": true, "peer": true, @@ -6650,7 +6650,7 @@ "@expo/config-types": "^52.0.5", "@expo/image-utils": "^0.6.5", "@expo/json-file": "^9.0.2", - "@react-native/normalize-colors": "0.76.8", + "@react-native/normalize-colors": "0.76.9", "debug": "^4.3.1", "fs-extra": "^9.0.0", "resolve-from": "^5.0.0", @@ -8046,23 +8046,23 @@ } }, "node_modules/@react-native/babel-plugin-codegen": { - "version": "0.76.8", - "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.76.8.tgz", - "integrity": "sha512-84RUEhDZS+q7vPtxKi0iMZLd5/W0VN7NOyqX5f+burV3xMYpUhpF5TDJ2Ysol7dJrvEZHm6ISAriO85++V8YDw==", + "version": "0.76.9", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.76.9.tgz", + "integrity": "sha512-vxL/vtDEIYHfWKm5oTaEmwcnNGsua/i9OjIxBDBFiJDu5i5RU3bpmDiXQm/bJxrJNPRp5lW0I0kpGihVhnMAIQ==", "license": "MIT", "optional": true, "peer": true, "dependencies": { - "@react-native/codegen": "0.76.8" + "@react-native/codegen": "0.76.9" }, "engines": { "node": ">=18" } }, "node_modules/@react-native/babel-preset": { - "version": "0.76.8", - "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.76.8.tgz", - "integrity": "sha512-xrP+r3orRzzxtC2TrfGIP6IYi1f4AiWlnSiWf4zxEdMFzKrYdmxhD0FPtAZb77B0DqFIW5AcBFlm4grfL/VgfA==", + "version": "0.76.9", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.76.9.tgz", + "integrity": "sha512-TbSeCplCM6WhL3hR2MjC/E1a9cRnMLz7i767T7mP90oWkklEjyPxWl+0GGoVGnJ8FC/jLUupg/HvREKjjif6lw==", "license": "MIT", "optional": true, "peer": true, @@ -8108,7 +8108,7 @@ "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", - "@react-native/babel-plugin-codegen": "0.76.8", + "@react-native/babel-plugin-codegen": "0.76.9", "babel-plugin-syntax-hermes-parser": "^0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" @@ -8121,9 +8121,9 @@ } }, "node_modules/@react-native/codegen": { - "version": "0.76.8", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.76.8.tgz", - "integrity": "sha512-qvKhcYBkRHJFkeWrYm66kEomQOTVXWiHBkZ8VF9oC/71OJkLszpTpVOuPIyyib6fqhjy9l7mHYGYenSpfYI5Ww==", + "version": "0.76.9", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.76.9.tgz", + "integrity": "sha512-AzlCHMTKrAVC2709V4ZGtBXmGVtWTpWm3Ruv5vXcd3/anH4mGucfJ4rjbWKdaYQJMpXa3ytGomQrsIsT/s8kgA==", "license": "MIT", "optional": true, "peer": true, @@ -8260,9 +8260,9 @@ } }, "node_modules/@react-native/debugger-frontend": { - "version": "0.76.8", - "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.76.8.tgz", - "integrity": "sha512-kSukBw2C++5ENLUCAp/1uEeiFgiHi/MBa71Wgym3UD5qwu2vOSPOTSKRX7q2Jb676MUzTcrIaJBZ/r2qk25u7Q==", + "version": "0.76.9", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.76.9.tgz", + "integrity": "sha512-0Ru72Bm066xmxFuOXhhvrryxvb57uI79yDSFf+hxRpktkC98NMuRenlJhslMrbJ6WjCu1vOe/9UjWNYyxXTRTA==", "license": "BSD-3-Clause", "optional": true, "peer": true, @@ -8271,15 +8271,15 @@ } }, "node_modules/@react-native/dev-middleware": { - "version": "0.76.8", - "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.76.8.tgz", - "integrity": "sha512-KYx7hFME2uYQRCDCqb19ghw51TAdh48PZ5EMpoU2kPA1SKKO9c1bUbpsKRhVZ0bv1QqEX6fjox3c4/WYRozHQA==", + "version": "0.76.9", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.76.9.tgz", + "integrity": "sha512-xkd3C3dRcmZLjFTEAOvC14q3apMLouIvJViCZY/p1EfCMrNND31dgE1dYrLTiI045WAWMt5bD15i6f7dE2/QWA==", "license": "MIT", "optional": true, "peer": true, "dependencies": { "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.76.8", + "@react-native/debugger-frontend": "0.76.9", "chrome-launcher": "^0.15.2", "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", @@ -8607,9 +8607,9 @@ } }, "node_modules/@react-native/normalize-colors": { - "version": "0.76.8", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.76.8.tgz", - "integrity": "sha512-FRjRvs7RgsXjkbGSOjYSxhX5V70c0IzA/jy3HXeYpATMwD9fOR1DbveLW497QGsVdCa0vThbJUtR8rIzAfpHQA==", + "version": "0.76.9", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.76.9.tgz", + "integrity": "sha512-TUdMG2JGk72M9d8DYbubdOlrzTYjw+YMe/xOnLU4viDgWRHsCbtRS9x0IAxRjs3amj/7zmK3Atm8jUPvdAc8qw==", "license": "MIT", "optional": true, "peer": true @@ -9791,9 +9791,9 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "license": "MIT", "optional": true, "peer": true, @@ -9977,9 +9977,9 @@ } }, "node_modules/@types/luxon": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.6.0.tgz", - "integrity": "sha512-RtEj20xRyG7cRp142MkQpV3GRF8Wo2MtDkKLz65MQs7rM1Lh8bz+HtfPXCCJEYpnDFu6VwAq/Iv2Ikyp9Jw/hw==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.6.2.tgz", + "integrity": "sha512-R/BdP7OxEMc44l2Ex5lSXHoIXTB2JLNa3y2QISIbr58U/YcsffyQrYW//hZSdrfxrjRZj3GcUoxMPGdO8gSYuw==", "dev": true, "license": "MIT" }, @@ -12383,9 +12383,9 @@ } }, "node_modules/babel-preset-expo": { - "version": "12.0.10", - "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-12.0.10.tgz", - "integrity": "sha512-6QE52Bxsp5XRE8t0taKRFTFsmTG0ThQE+PTgCgLY9s8v2Aeh8R+E+riXhSHX6hP+diDmBFBdvLCUTq7kroJb1Q==", + "version": "12.0.11", + "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-12.0.11.tgz", + "integrity": "sha512-4m6D92nKEieg+7DXa8uSvpr0GjfuRfM/G0t0I/Q5hF8HleEv5ms3z4dJ+p52qXSJsm760tMqLdO93Ywuoi7cCQ==", "license": "MIT", "optional": true, "peer": true, @@ -12396,7 +12396,7 @@ "@babel/plugin-transform-parameters": "^7.22.15", "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.23.0", - "@react-native/babel-preset": "0.76.8", + "@react-native/babel-preset": "0.76.9", "babel-plugin-react-native-web": "~0.19.13", "react-refresh": "^0.14.2" }, @@ -12610,9 +12610,9 @@ } }, "node_modules/bignumber.js": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", - "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.2.0.tgz", + "integrity": "sha512-JocpCSOixzy5XFJi2ub6IMmV/G9i8Lrm2lZvwBv9xPdglmZM0ufDVBbjbrfU/zuLvBfD7Bv2eYxz9i+OHTgkew==", "license": "MIT", "engines": { "node": "*" @@ -12641,54 +12641,42 @@ } }, "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.8.2.tgz", + "integrity": "sha512-pfqikmByp+lifZCS0p6j6KreV6kNU6Apzpm2nKOk+94cZb/jvle55+JxWiByUQ0Wo/+XnDXEy5MxxKMb6r0VIw==", + "dev": true, "license": "MIT", "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "readable-stream": "~1.0.26" } }, - "node_modules/bl/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } + "node_modules/bl/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true, + "license": "MIT" }, "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, + "node_modules/bl/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "dev": true, + "license": "MIT" + }, "node_modules/blakejs": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", @@ -12871,20 +12859,6 @@ "node": ">= 0.12" } }, - "node_modules/browserify-sign/node_modules/hash-base": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", - "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/browserify-sign/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -14883,20 +14857,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/crypto-browserify/node_modules/hash-base": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", - "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/crypto-js": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", @@ -15971,9 +15931,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.130", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.130.tgz", - "integrity": "sha512-Ou2u7L9j2XLZbhqzyX0jWDj6gA8D3jIfVzt4rikLf3cGBa0VdReuFimBKS9tQJA4+XpeCxj1NoWlfBXzbMa9IA==", + "version": "1.5.131", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.131.tgz", + "integrity": "sha512-fJFRYXVEJgDCiqFOgRGJm8XR97hZ13tw7FXI9k2yC5hgY+nyzC2tMO8baq1cQR7Ur58iCkASx2zrkZPZUnfzPg==", "devOptional": true, "license": "ISC" }, @@ -17024,21 +16984,21 @@ } }, "node_modules/expo": { - "version": "52.0.42", - "resolved": "https://registry.npmjs.org/expo/-/expo-52.0.42.tgz", - "integrity": "sha512-t+PRYIzzPFAlF99OVJOjZwM1glLhN85XGD6vmeg6uwpADDILl9yw4dfy0DXL4hot5GJkAGaZ+uOHUljV4kC2Bg==", + "version": "52.0.44", + "resolved": "https://registry.npmjs.org/expo/-/expo-52.0.44.tgz", + "integrity": "sha512-qj3+MWxmqLyBaYQ8jDOvVLEgSqNplH3cf+nDhxCo4C1cpTPD1u/HGh1foibtaeuCYLHsE5km1lrcOpRbFJ4luQ==", "license": "MIT", "optional": true, "peer": true, "dependencies": { "@babel/runtime": "^7.20.0", - "@expo/cli": "0.22.23", + "@expo/cli": "0.22.24", "@expo/config": "~10.0.11", "@expo/config-plugins": "~9.0.17", "@expo/fingerprint": "0.11.11", "@expo/metro-config": "0.19.12", "@expo/vector-icons": "^14.0.0", - "babel-preset-expo": "~12.0.10", + "babel-preset-expo": "~12.0.11", "expo-asset": "~11.0.5", "expo-constants": "~17.0.8", "expo-file-system": "~18.0.12", @@ -18183,6 +18143,16 @@ "xtend": "~4.0.1" } }, + "node_modules/get-pkg-repo/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/get-pkg-repo/node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", @@ -18696,31 +18666,16 @@ "license": "ISC" }, "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", "license": "MIT", "dependencies": { "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash-base/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "safe-buffer": "^5.2.1" }, "engines": { - "node": ">= 6" + "node": ">= 0.10" } }, "node_modules/hash.js": { @@ -20859,15 +20814,6 @@ "xtend": "^2.2.0" } }, - "node_modules/level-filesystem/node_modules/xtend": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.2.0.tgz", - "integrity": "sha512-SLt5uylT+4aoXxXuwtQp5ZnMMzhDb1Xkg4pEqc00WUJCQifPfV9Ub1VrNhp9kXkrjZD2I2Hl8WnjP37jzZLPZw==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, "node_modules/level-fix-range": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/level-fix-range/-/level-fix-range-1.0.2.tgz", @@ -21005,16 +20951,6 @@ "xtend": "~3.0.0" } }, - "node_modules/levelup/node_modules/bl": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-0.8.2.tgz", - "integrity": "sha512-pfqikmByp+lifZCS0p6j6KreV6kNU6Apzpm2nKOk+94cZb/jvle55+JxWiByUQ0Wo/+XnDXEy5MxxKMb6r0VIw==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "~1.0.26" - } - }, "node_modules/levelup/node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -24775,6 +24711,58 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ora/node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/ora/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/ora/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -24950,20 +24938,6 @@ "dev": true, "license": "MIT" }, - "node_modules/parse-asn1/node_modules/hash-base": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", - "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/parse-entities": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", @@ -29314,6 +29288,16 @@ "node": ">= 6" } }, + "node_modules/stream-http/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/streamx": { "version": "2.22.0", "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz", @@ -29859,6 +29843,41 @@ "node": ">=6" } }, + "node_modules/tar-stream/node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/tar-stream/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/tar-stream/node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -30583,24 +30602,24 @@ "license": "MIT" }, "node_modules/typeorm": { - "version": "0.3.21", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.21.tgz", - "integrity": "sha512-lh4rUWl1liZGjyPTWpwcK8RNI5x4ekln+/JJOox1wCd7xbucYDOXWD+1cSzTN3L0wbTGxxOtloM5JlxbOxEufA==", + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.22.tgz", + "integrity": "sha512-P/Tsz3UpJ9+K0oryC0twK5PO27zejLYYwMsE8SISfZc1lVHX+ajigiOyWsKbuXpEFMjD9z7UjLzY3+ElVOMMDA==", "license": "MIT", "dependencies": { "@sqltools/formatter": "^1.2.5", - "ansis": "^3.9.0", + "ansis": "^3.17.0", "app-root-path": "^3.1.0", "buffer": "^6.0.3", - "dayjs": "^1.11.9", - "debug": "^4.3.4", - "dotenv": "^16.0.3", + "dayjs": "^1.11.13", + "debug": "^4.4.0", + "dotenv": "^16.4.7", "glob": "^10.4.5", "sha.js": "^2.4.11", "sql-highlight": "^6.0.0", - "tslib": "^2.5.0", - "uuid": "^11.0.5", - "yargs": "^17.6.2" + "tslib": "^2.8.1", + "uuid": "^11.1.0", + "yargs": "^17.7.2" }, "bin": { "typeorm": "cli.js", @@ -30614,12 +30633,12 @@ "url": "https://opencollective.com/typeorm" }, "peerDependencies": { - "@google-cloud/spanner": "^5.18.0", + "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0", "@sap/hana-client": "^2.12.25", "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0", "hdb-pool": "^0.1.6", "ioredis": "^5.0.4", - "mongodb": "^5.8.0", + "mongodb": "^5.8.0 || ^6.0.0", "mssql": "^9.1.1 || ^10.0.1 || ^11.0.1", "mysql2": "^2.2.5 || ^3.0.1", "oracledb": "^6.3.0", @@ -30631,7 +30650,7 @@ "sql.js": "^1.4.0", "sqlite3": "^5.0.3", "ts-node": "^10.7.0", - "typeorm-aurora-data-api-driver": "^2.0.0" + "typeorm-aurora-data-api-driver": "^2.0.0 || ^3.0.0" }, "peerDependenciesMeta": { "@google-cloud/spanner": { @@ -30687,6 +30706,23 @@ } } }, + "node_modules/typeorm/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/typeorm/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -30722,6 +30758,18 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/typeorm/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==", + "license": "MIT" + }, + "node_modules/typeorm/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/typeorm/node_modules/uuid": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", @@ -31210,9 +31258,9 @@ } }, "node_modules/vite": { - "version": "5.4.16", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.16.tgz", - "integrity": "sha512-Y5gnfp4NemVfgOTDQAunSD4346fal44L9mszGGY/e+qxsRT5y1sMlS/8tiQ8AFAp+MFgYNSINdfEchJiPm41vQ==", + "version": "5.4.17", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.17.tgz", + "integrity": "sha512-5+VqZryDj4wgCs55o9Lp+p8GE78TLVg0lasCH5xFZ4jacZjtqZa6JUw9/p0WeAojaOfncSM6v77InkFPGnvPvg==", "dev": true, "license": "MIT", "dependencies": { @@ -32417,11 +32465,10 @@ } }, "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.2.0.tgz", + "integrity": "sha512-SLt5uylT+4aoXxXuwtQp5ZnMMzhDb1Xkg4pEqc00WUJCQifPfV9Ub1VrNhp9kXkrjZD2I2Hl8WnjP37jzZLPZw==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.4" } diff --git a/src/components/EntityIcon.vue b/src/components/EntityIcon.vue index ae451265..2c1b50f9 100644 --- a/src/components/EntityIcon.vue +++ b/src/components/EntityIcon.vue @@ -9,12 +9,26 @@ :height="iconSize" @click="handleClick" /> -
+
+ + + + + + +
@@ -32,7 +46,9 @@ export default class EntityIcon extends Vue { @Prop iconSize = 0; @Prop profileImageUrl = ""; // overridden by contact.profileImageUrl - private identiconSvg = ""; + private avatarPaths: string[] = []; + private blankSquareUrl = + import.meta.env.VITE_BASE_URL + "assets/blank-square.svg"; get imageUrl(): string { return this.contact?.profileImageUrl || this.profileImageUrl; @@ -42,38 +58,43 @@ export default class EntityIcon extends Vue { return !!this.imageUrl; } + get identifier(): string | undefined { + return this.contact?.did || this.entityId; + } + handleClick() { try { // Emit a simple event without passing the event object - this.$emit('click'); + this.$emit("click"); } catch (error) { - logger.error('Error handling click event:', error); + logger.error("Error handling click event:", error); } } - generateIdenticon(): string { - const identifier = this.contact?.did || this.entityId; - if (!identifier) { - const baseUrl = import.meta.env.VITE_BASE_URL || '/'; - return ``; - } - // https://api.dicebear.com/8.x/avataaars/svg?seed= - // ... does not render things with the same seed as this library. - // "did:ethr:0x222BB77E6Ff3774d34c751f3c1260866357B677b" yields a girl with flowers in her hair and a lightning earring - // ... which looks similar to '' at the dicebear site but which is different. + generateAvatarPaths(): string[] { + if (!this.identifier) return []; + const options: StyleOptions = { - seed: identifier || "", + seed: this.identifier, size: this.iconSize, }; const avatar = createAvatar(avataaars, options); - return avatar.toString(); + const svgString = avatar.toString(); + + // Extract paths from SVG string + const parser = new DOMParser(); + const doc = parser.parseFromString(svgString, "image/svg+xml"); + const paths = Array.from(doc.querySelectorAll("path")).map( + (path) => path.getAttribute("d") || "", + ); + return paths; } mounted() { - this.identiconSvg = this.generateIdenticon(); - logger.log('EntityIcon mounted, profileImageUrl:', this.profileImageUrl); - logger.log('EntityIcon mounted, entityId:', this.entityId); - logger.log('EntityIcon mounted, iconSize:', this.iconSize); + this.avatarPaths = this.generateAvatarPaths(); + logger.log("EntityIcon mounted, profileImageUrl:", this.profileImageUrl); + logger.log("EntityIcon mounted, entityId:", this.entityId); + logger.log("EntityIcon mounted, iconSize:", this.iconSize); } } diff --git a/src/db/index.ts b/src/db/index.ts index 5f9645a5..7a3b8e3c 100644 --- a/src/db/index.ts +++ b/src/db/index.ts @@ -1,7 +1,8 @@ import BaseDexie, { Table } from "dexie"; import { encrypted, Encryption } from "@pvermeer/dexie-encrypted-addon"; -import { exportDB } from "dexie-export-import"; +import { exportDB, ExportOptions } from "dexie-export-import"; import * as R from "ramda"; +import Dexie from "dexie"; import { Account, AccountsSchema } from "./tables/accounts"; import { Contact, ContactSchema } from "./tables/contacts"; @@ -27,9 +28,14 @@ type NonsensitiveTables = { }; // Using 'unknown' instead of 'any' for stricter typing and to avoid TypeScript warnings -export type SecretDexie = BaseDexie & T & { export: (options?: any) => Promise }; -export type SensitiveDexie = BaseDexie & T & { export: (options?: any) => Promise }; -export type NonsensitiveDexie = BaseDexie & T & { export: (options?: any) => Promise }; +export type SecretDexie = SecretTable> = + BaseDexie & T & { export: (options?: ExportOptions) => Promise }; +export type SensitiveDexie< + T extends Record = SensitiveTables, +> = BaseDexie & T & { export: (options?: ExportOptions) => Promise }; +export type NonsensitiveDexie< + T extends Record = NonsensitiveTables, +> = BaseDexie & T & { export: (options?: ExportOptions) => Promise }; //// Initialize the DBs, starting with the sensitive ones. diff --git a/src/platforms/capacitor/DatabaseBackupService.ts b/src/platforms/capacitor/DatabaseBackupService.ts index 09326a75..1f3e966c 100644 --- a/src/platforms/capacitor/DatabaseBackupService.ts +++ b/src/platforms/capacitor/DatabaseBackupService.ts @@ -1,69 +1,82 @@ /** * @file DatabaseBackupService.ts - * @description Capacitor-specific implementation of DatabaseBackupService + * @description Capacitor-specific implementation of database backup service * - * This implementation handles database backup operations specifically for Capacitor - * platforms (Android/iOS). It uses the Filesystem and Share plugins to save and - * share the backup file. + * This service handles database backup operations on Capacitor platforms (Android/iOS) + * using the Filesystem and Share plugins. It creates a temporary backup file, + * writes the backup data to it, and shares the file using the platform's share sheet. */ -import { DatabaseBackupService as BaseDatabaseBackupService } from "../../services/DatabaseBackupService"; import { Filesystem, Directory } from "@capacitor/filesystem"; import { Share } from "@capacitor/share"; +import { DatabaseBackupService as BaseDatabaseBackupService } from "../../services/DatabaseBackupService"; import { log, error } from "../../utils/logger"; export class DatabaseBackupService extends BaseDatabaseBackupService { /** * Handles the backup process for Capacitor platforms - * + * * @param base64Data - Backup data in base64 format * @param arrayBuffer - Backup data as ArrayBuffer * @param blob - Backup data as Blob */ protected async handleBackup( base64Data: string, - arrayBuffer: ArrayBuffer, - blob: Blob + _arrayBuffer: ArrayBuffer, + _blob: Blob, ): Promise { try { - log("Starting Capacitor backup process"); - - // Create a temporary file - const fileName = `timesafari-backup-${new Date().toISOString()}.json`; - const filePath = `backups/${fileName}`; - - log("Writing backup file"); - const result = await Filesystem.writeFile({ - path: filePath, + log("Starting backup process for Capacitor platform"); + + // Create a timestamped backup file name + const timestamp = new Date().toISOString().replace(/[:.]/g, "-"); + const backupFileName = `timesafari-backup-${timestamp}.json`; + const backupFilePath = `backups/${backupFileName}`; + + log("Creating backup file:", { + fileName: backupFileName, + path: backupFilePath, + }); + + // Write the backup file + const writeResult = (await Filesystem.writeFile({ + path: backupFilePath, data: base64Data, directory: Directory.Cache, - recursive: true - }); - - log("Getting file path"); - const fileInfo = await Filesystem.stat({ - path: filePath, - directory: Directory.Cache - }); - + recursive: true, + })) as unknown as { uri: string }; + + if (!writeResult.uri) { + throw new Error("Failed to write backup file: No URI returned"); + } + + log("Backup file written successfully:", { uri: writeResult.uri }); + + // Share the backup file log("Sharing backup file"); await Share.share({ title: "TimeSafari Backup", text: "Your TimeSafari backup file", - url: fileInfo.uri, - dialogTitle: "Share TimeSafari Backup" + url: writeResult.uri, + dialogTitle: "Share TimeSafari Backup", }); - + log("Backup shared successfully"); // Clean up the temporary file - await Filesystem.deleteFile({ - path: filePath, - directory: Directory.Cache - }); + try { + await Filesystem.deleteFile({ + path: backupFilePath, + directory: Directory.Cache, + }); + log("Temporary backup file cleaned up"); + } catch (cleanupError) { + error("Failed to clean up temporary backup file:", cleanupError); + // Don't throw here as the backup was successful + } } catch (err) { - error("Error during Capacitor backup:", err); + error("Error during backup process:", err); throw err; } } -} \ No newline at end of file +} diff --git a/src/services/DatabaseBackupService.ts b/src/services/DatabaseBackupService.ts index e0867d89..22169887 100644 --- a/src/services/DatabaseBackupService.ts +++ b/src/services/DatabaseBackupService.ts @@ -65,23 +65,23 @@ export class DatabaseBackupService { public static async createAndShareBackup( base64Data: string, arrayBuffer: ArrayBuffer, - blob: Blob + blob: Blob, ): Promise { try { - log('Creating platform-specific backup service'); + log("Creating platform-specific backup service"); const backupService = await this.getPlatformSpecificBackupService(); - log('Backup service created successfully'); + log("Backup service created successfully"); - log('Executing platform-specific backup'); + log("Executing platform-specific backup"); await backupService.handleBackup(base64Data, arrayBuffer, blob); - log('Backup completed successfully'); + log("Backup completed successfully"); } catch (err) { - error('Error during backup creation:', err); + error("Error during backup creation:", err); if (err instanceof Error) { - error('Error details:', { + error("Error details:", { name: err.name, message: err.message, - stack: err.stack + stack: err.stack, }); } throw err; diff --git a/src/services/PlatformServiceFactory.ts b/src/services/PlatformServiceFactory.ts index 003da054..c0073e06 100644 --- a/src/services/PlatformServiceFactory.ts +++ b/src/services/PlatformServiceFactory.ts @@ -131,10 +131,12 @@ export class PlatformServiceFactory { public async createDatabaseBackupService(): Promise { // List of supported platforms for web builds const webSupportedPlatforms = ["web", "mobile"]; - + // Return stub implementation for unsupported platforms if (!webSupportedPlatforms.includes(this.platform)) { - logger.log(`Using stub implementation for unsupported platform: ${this.platform}`); + logger.log( + `Using stub implementation for unsupported platform: ${this.platform}`, + ); return new StubDatabaseBackupService(); } @@ -145,15 +147,15 @@ export class PlatformServiceFactory { /* @vite-ignore */ `./platforms/${this.platform}/DatabaseBackupService.ts` ); - logger.log('Platform service loaded successfully'); + logger.log("Platform service loaded successfully"); return new module.DatabaseBackupService(); } catch (error) { logger.error( `[TimeSafari] Failed to load platform-specific service for ${this.platform}:`, - error + error, ); // Fallback to stub implementation on error - logger.log('Falling back to stub implementation'); + logger.log("Falling back to stub implementation"); return new StubDatabaseBackupService(); } } diff --git a/src/services/RateLimitsService.ts b/src/services/RateLimitsService.ts index 6a95c156..87cca689 100644 --- a/src/services/RateLimitsService.ts +++ b/src/services/RateLimitsService.ts @@ -17,31 +17,45 @@ export class RateLimitsService { * @param did - The user's DID * @returns Promise */ - static async fetchRateLimits(apiServer: string, did: string): Promise { - logger.log('Fetching rate limits for DID:', did); - logger.log('Using API server:', apiServer); - + static async fetchRateLimits( + apiServer: string, + did: string, + ): Promise { + logger.log("Fetching rate limits for DID:", did); + logger.log("Using API server:", apiServer); + try { const headers = await getHeaders(did); - const response = await axios.get(`${apiServer}/api/v2/rate-limits/${did}`, { headers }); - logger.log('Rate limits response:', response.data); + const response = await axios.get( + `${apiServer}/api/v2/rate-limits/${did}`, + { headers }, + ); + logger.log("Rate limits response:", response.data); return response.data; } catch (error) { - if (axios.isAxiosError(error) && (error.response?.status === 400 || error.response?.status === 404)) { - const errorData = error.response.data as { error?: { message?: string, code?: string } }; - if (errorData.error?.code === 'UNREGISTERED_USER' || error.response?.status === 404) { - logger.log('User is not registered, returning default limits'); + if ( + axios.isAxiosError(error) && + (error.response?.status === 400 || error.response?.status === 404) + ) { + const errorData = error.response.data as { + error?: { message?: string; code?: string }; + }; + if ( + errorData.error?.code === "UNREGISTERED_USER" || + error.response?.status === 404 + ) { + logger.log("User is not registered, returning default limits"); return { doneClaimsThisWeek: "0", maxClaimsPerWeek: "0", nextWeekBeginDateTime: new Date().toISOString(), doneRegistrationsThisMonth: "0", maxRegistrationsPerMonth: "0", - nextMonthBeginDateTime: new Date().toISOString() + nextMonthBeginDateTime: new Date().toISOString(), }; } } - logger.error('Error fetching rate limits:', error); + logger.error("Error fetching rate limits:", error); throw error; } } diff --git a/src/services/platforms/empty.ts b/src/services/platforms/empty.ts index 321b0036..5d02c5b8 100644 --- a/src/services/platforms/empty.ts +++ b/src/services/platforms/empty.ts @@ -17,4 +17,4 @@ export default class StubDatabaseBackupService extends DatabaseBackupService { } } -export { StubDatabaseBackupService as DatabaseBackupService }; \ No newline at end of file +export { StubDatabaseBackupService as DatabaseBackupService }; diff --git a/src/services/platforms/web/DatabaseBackupService.ts b/src/services/platforms/web/DatabaseBackupService.ts index 4da346dd..314ddd2d 100644 --- a/src/services/platforms/web/DatabaseBackupService.ts +++ b/src/services/platforms/web/DatabaseBackupService.ts @@ -12,10 +12,10 @@ export default class WebDatabaseBackupService extends DatabaseBackupService { protected async handleBackup( _base64Data: string, _arrayBuffer: ArrayBuffer, - blob: Blob + blob: Blob, ): Promise { try { - log('Starting web platform backup'); + log("Starting web platform backup"); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; @@ -24,9 +24,9 @@ export default class WebDatabaseBackupService extends DatabaseBackupService { a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); - log('Web platform backup completed'); + log("Web platform backup completed"); } catch (err) { - error('Error during web platform backup:', err); + error("Error during web platform backup:", err); throw err; } } diff --git a/src/types/interfaces.ts b/src/types/interfaces.ts index 950d65d8..93897ff9 100644 --- a/src/types/interfaces.ts +++ b/src/types/interfaces.ts @@ -1,29 +1,29 @@ /** * @file interfaces.ts * @description Core type declarations for the TimeSafari application - * + * * This module defines the core interfaces and types used throughout the application. * It serves as the central location for type definitions that are shared across * multiple components and services. - * + * * Architecture: * 1. DID (Decentralized Identifier) Types: * - IIdentifier: Core DID structure * - IKey: Cryptographic key information * - IService: Service endpoints and capabilities - * + * * 2. Verifiable Credential Types: * - GenericCredWrapper: Base wrapper for all credentials * - GiveVerifiableCredential: Gift-related credentials * - OfferVerifiableCredential: Offer-related credentials * - RegisterVerifiableCredential: Registration credentials - * + * * 3. Service Types: * - EndorserService: Claims and endorsements * - PushNotificationService: Web push notifications * - ProfileService: User profiles * - BackupService: Data backup - * + * * @see src/interfaces/identifier.ts * @see src/interfaces/claims.ts * @see src/interfaces/limits.ts @@ -33,11 +33,11 @@ import { GiveVerifiableCredential } from "../interfaces"; /** * Interface for a Decentralized Identifier (DID) - * + * * This interface defines the structure of a DID, which is a unique identifier * that can be used to look up a DID document containing information associated * with the DID, such as public keys and service endpoints. - * + * * @example * ```typescript * const identifier: IIdentifier = { @@ -102,7 +102,29 @@ export interface IIdentifier { /** * Optional metadata about the key */ - meta?: any; + meta?: { + /** + * HD wallet derivation path + * @example "m/44'/60'/0'/0/0" + */ + derivationPath?: string; + + /** + * Key usage or purpose + * @example "signing", "encryption" + */ + usage?: string; + + /** + * Key creation timestamp + */ + createdAt?: number; + + /** + * Additional key metadata + */ + [key: string]: unknown; + }; }>; /** @@ -132,15 +154,41 @@ export interface IIdentifier { */ description?: string; }>; + + /** + * Optional metadata about the identifier + */ + meta?: { + /** + * DID method-specific metadata + * @example { network: "mainnet", chainId: 1 } for ethr + */ + method?: Record; + + /** + * Identifier creation timestamp + */ + createdAt?: number; + + /** + * Last update timestamp + */ + updatedAt?: number; + + /** + * Additional identifier metadata + */ + [key: string]: unknown; + }; } /** * Interface for a cryptographic key - * + * * This interface defines the structure of a cryptographic key used in the * DID system. It includes both public and private key information, along * with metadata about the key's purpose and derivation. - * + * * @example * ```typescript * const key: IKey = { @@ -203,6 +251,17 @@ export interface IKey { */ derivationPath?: string; + /** + * Key usage or purpose + * @example "signing", "encryption" + */ + usage?: string; + + /** + * Key creation timestamp + */ + createdAt?: number; + /** * Additional key metadata */ @@ -212,11 +271,11 @@ export interface IKey { /** * Interface for a service endpoint - * + * * This interface defines the structure of a service endpoint that can be * associated with a DID. Services provide additional functionality and * endpoints for DID operations. - * + * * @example * ```typescript * const service: IService = { @@ -352,3 +411,20 @@ export interface GiveRecordWithContactInfo { recipientProjectName?: string; image?: string; } + +export interface TimeSafariError extends Error { + /** + * User-friendly error message + */ + userMessage?: string; + + /** + * Error code for programmatic handling + */ + code?: string; + + /** + * Additional error context + */ + context?: Record; +} diff --git a/src/utils/logger.ts b/src/utils/logger.ts index f081b055..e37fcca8 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -20,7 +20,7 @@ function safeStringify(obj: unknown) { } function formatMessage(message: string, ...args: unknown[]): string { - const prefix = '[TimeSafari]'; + const prefix = "[TimeSafari]"; const argsString = args.length > 0 ? " - " + safeStringify(args) : ""; return `${prefix} ${message}${argsString}`; } @@ -29,6 +29,7 @@ export const logger = { log: (message: string, ...args: unknown[]) => { if (process.env.NODE_ENV !== "production") { const formattedMessage = formatMessage(message, ...args); + // eslint-disable-next-line no-console console.log(formattedMessage); logToDb(message + (args.length > 0 ? " - " + safeStringify(args) : "")); } @@ -36,38 +37,45 @@ export const logger = { warn: (message: string, ...args: unknown[]) => { if (process.env.NODE_ENV !== "production") { const formattedMessage = formatMessage(message, ...args); + // eslint-disable-next-line no-console console.warn(formattedMessage); logToDb(message + (args.length > 0 ? " - " + safeStringify(args) : "")); } }, error: (message: string, ...args: unknown[]) => { const formattedMessage = formatMessage(message, ...args); + // eslint-disable-next-line no-console console.error(formattedMessage); logToDb(message + (args.length > 0 ? " - " + safeStringify(args) : "")); }, }; -export function log(...args: any[]) { - const message = formatMessage(args[0], ...args.slice(1)); - console.log(message); +export function log(message: string, ...args: unknown[]): void { + const formattedMessage = formatMessage(message, ...args); + // eslint-disable-next-line no-console + console.log(formattedMessage); } -export function error(...args: any[]) { - const message = formatMessage(args[0], ...args.slice(1)); - console.error(message); +export function error(message: string, ...args: unknown[]): void { + const formattedMessage = formatMessage(message, ...args); + // eslint-disable-next-line no-console + console.error(formattedMessage); } -export function warn(...args: any[]) { - const message = formatMessage(args[0], ...args.slice(1)); - console.warn(message); +export function warn(message: string, ...args: unknown[]): void { + const formattedMessage = formatMessage(message, ...args); + // eslint-disable-next-line no-console + console.warn(formattedMessage); } -export function info(...args: any[]) { - const message = formatMessage(args[0], ...args.slice(1)); - console.info(message); +export function info(message: string, ...args: unknown[]): void { + const formattedMessage = formatMessage(message, ...args); + // eslint-disable-next-line no-console + console.info(formattedMessage); } -export function debug(...args: any[]) { - const message = formatMessage(args[0], ...args.slice(1)); - console.debug(message); +export function debug(message: string, ...args: unknown[]): void { + const formattedMessage = formatMessage(message, ...args); + // eslint-disable-next-line no-console + console.debug(formattedMessage); } diff --git a/src/views/AccountViewView.vue b/src/views/AccountViewView.vue index 2b21010d..5b2f1ab0 100644 --- a/src/views/AccountViewView.vue +++ b/src/views/AccountViewView.vue @@ -836,7 +836,6 @@ import "leaflet/dist/leaflet.css"; import { AxiosError } from "axios"; import { Buffer } from "buffer/"; import Dexie from "dexie"; -import { exportDB } from "dexie-export-import"; import * as R from "ramda"; import type { IIdentifier, UserProfile } from "@/types/interfaces"; import { ref } from "vue"; @@ -889,7 +888,6 @@ import { DatabaseBackupService } from "../services/DatabaseBackupService"; import { ProfileService } from "../services/ProfileService"; import { RateLimitsService } from "../services/RateLimitsService"; import ProfileSection from "../components/ProfileSection.vue"; -import { log, error } from '../utils/logger'; const inputImportFileNameRef = ref(); @@ -1404,12 +1402,12 @@ export default class AccountViewView extends Vue { async exportDatabase() { try { logger.log("Starting database export process"); - + const db = await this.getDatabase(); logger.log("Database instance:", { name: db.name, version: db.verno, - tables: db.tables.map((t: { name: string }) => t.name) + tables: db.tables.map((t: { name: string }) => t.name), }); if (!db.export) { @@ -1421,7 +1419,7 @@ export default class AccountViewView extends Vue { const blob = await db.export(); logger.log("Blob created:", { type: blob.type, - size: blob.size + size: blob.size, }); logger.log("Converting blob to base64"); @@ -1445,8 +1443,16 @@ export default class AccountViewView extends Vue { } } - async createAndShareBackup(base64Data: string, arrayBuffer: ArrayBuffer, blob: Blob) { - await DatabaseBackupService.createAndShareBackup(base64Data, arrayBuffer, blob); + async createAndShareBackup( + base64Data: string, + arrayBuffer: ArrayBuffer, + blob: Blob, + ) { + await DatabaseBackupService.createAndShareBackup( + base64Data, + arrayBuffer, + blob, + ); } async uploadImportFile(event: Event) { diff --git a/src/views/ClaimCertificateView.vue b/src/views/ClaimCertificateView.vue index 3b012574..c0270650 100644 --- a/src/views/ClaimCertificateView.vue +++ b/src/views/ClaimCertificateView.vue @@ -24,8 +24,8 @@