diff --git a/.editorconfig b/.editorconfig index 88bf97c50..ebe51d3bf 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,7 +6,7 @@ root = true [*] indent_style = space indent_size = 2 -end_of_line = crlf +end_of_line = lf charset = utf-8 trim_trailing_whitespace = false insert_final_newline = false \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0858885a5..bab2ae64b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,8 @@ jobs: - name: Set environment variable run: | SHORT_SHA_COMMIT=$(git rev-parse --short HEAD) + echo SHORT_SHA_COMMIT=${SHORT_SHA_COMMIT} >> $GITHUB_ENV + echo ENVIRONMENT=${GITHUB_REF_NAME} >> $GITHUB_ENV echo CONTAINER_RELEASE_IMAGE=ghcr.io/aura-nw/explorer-frontend:${GITHUB_REF_NAME}_${SHORT_SHA_COMMIT} >> $GITHUB_ENV echo REPO_MANIFEST_NAME=gitops >> $GITHUB_ENV echo REPO_MANIFEST_URL=github.com/aura-nw/gitops.git >> $GITHUB_ENV diff --git a/.gitignore b/.gitignore index 68714b491..fea2cb0db 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ dist .idea/vcs.xml .idea/workspace.xml .vscode/settings.json -*.orig \ No newline at end of file +*.orig +/src/assets/config/feature-flags.json \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index ffa8f8cc7..67bbb1ed7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,21 @@ FROM node:18-alpine as build-stage + +ARG SHORT_SHA_COMMIT +ARG ENVIRONMENT + RUN mkdir -p /data/app + WORKDIR /data/app COPY . /data/app + +ENV NG_APP_VERSION=$SHORT_SHA_COMMIT + RUN npm install && npm cache clean --force +RUN node scripts/encryptFeatureFlags.mjs $ENVIRONMENT RUN npm run build --aot --output-hashing=all + FROM nginx:1.15 + COPY --from=build-stage /data/app/nginx.conf /etc/nginx/conf.d/default.conf COPY --from=build-stage /data/app/dist/frontend /var/www/tmp COPY --from=build-stage /data/app/dist/frontend/assets/ngsw-worker.js /var/www/tmp/ diff --git a/ci/build.sh b/ci/build.sh index 6417e10fb..e30984c52 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -8,5 +8,5 @@ then echo 'This is main branch' fi #Build and push image -docker build -t ${CONTAINER_RELEASE_IMAGE} -f Dockerfile . +docker build -t ${CONTAINER_RELEASE_IMAGE} --build-arg SHORT_SHA_COMMIT=${SHORT_SHA_COMMIT} --build-arg ENVIRONMENT=${ENVIRONMENT} -f Dockerfile . docker push ${CONTAINER_RELEASE_IMAGE} diff --git a/package-lock.json b/package-lock.json index de280277e..670d69183 100644 --- a/package-lock.json +++ b/package-lock.json @@ -98,6 +98,7 @@ "karma-coverage": "~2.0.3", "karma-jasmine": "~4.0.0", "karma-jasmine-html-reporter": "^1.7.0", + "npm-run-all": "^4.1.5", "prettier": "^3.1.1", "typescript": "~4.9.5" }, @@ -7735,12 +7736,50 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", "dev": true }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -7809,9 +7848,12 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -8514,12 +8556,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9673,6 +9721,57 @@ "node": ">=10" } }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/date-fns": { "version": "2.30.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", @@ -9765,16 +9864,19 @@ } }, "node_modules/define-data-property": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz", - "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==", + "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==", "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-lazy-prop": { @@ -10296,12 +10398,134 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", "dev": true }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/esbuild": { "version": "0.18.17", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.17.tgz", @@ -11194,9 +11418,39 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/gauge": { "version": "4.0.4", @@ -11234,14 +11488,18 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11273,6 +11531,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -11404,10 +11679,20 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", + "dev": true, "engines": { "node": ">= 0.4.0" } }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -11417,20 +11702,20 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -11450,11 +11735,11 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -11491,6 +11776,17 @@ "minimalistic-assert": "^1.0.1" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/hdr-histogram-js": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-2.0.3.tgz", @@ -12021,6 +12317,20 @@ "node": ">=8" } }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ioredis": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.2.tgz", @@ -12082,12 +12392,40 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -12099,6 +12437,22 @@ "node": ">=8" } }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -12122,6 +12476,36 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -12224,6 +12608,18 @@ "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "dev": true }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -12232,8 +12628,23 @@ "node": ">=0.12.0" } }, - "node_modules/is-plain-obj": { - "version": "3.0.0", + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", "dev": true, @@ -12262,6 +12673,37 @@ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -12273,12 +12715,42 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dependencies": { - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -12299,6 +12771,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-what": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", @@ -12732,6 +13216,12 @@ "node": ">=4" } }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -13334,6 +13824,43 @@ "@types/trusted-types": "^2.0.2" } }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", @@ -13654,6 +14181,15 @@ "node": ">= 4.0.0" } }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -14303,6 +14839,12 @@ "node-gyp-build": "^4.2.2" } }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, "node_modules/node-addon-api": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", @@ -14558,6 +15100,113 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm-run-all/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/npm-run-all/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/npm-run-all/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -14613,9 +15262,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -14637,6 +15286,24 @@ "node": ">= 10.12.0" } }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -15150,6 +15817,18 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -15312,6 +15991,14 @@ "node": ">=10.13.0" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -15938,6 +16625,68 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -16064,6 +16813,24 @@ "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==", "dev": true }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regexpu-core": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", @@ -16318,6 +17085,30 @@ "tslib": "^2.1.0" } }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -16337,6 +17128,23 @@ } ] }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-stable-stringify": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", @@ -16654,6 +17462,37 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, + "node_modules/set-function-length": { + "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==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -17171,6 +18010,73 @@ "node": ">=8" } }, + "node_modules/string.prototype.padend": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", + "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -17195,6 +18101,15 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -17739,6 +18654,79 @@ "node": ">= 0.6" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typed-assert": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", @@ -17798,6 +18786,21 @@ "multiformats": "^9.4.2" } }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/uncrypto": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", @@ -18619,21 +19622,37 @@ "which": "bin/which" } }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/which-module": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" }, "node_modules/which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" diff --git a/package.json b/package.json index eba2d988e..e6273b182 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,11 @@ "version": "1.0.0", "scripts": { "ng": "ng", - "start": "ng serve", + "start": "run-p featureflags start:dev", + "start:dev": "ng serve", "build": "ng build --aot=true --output-hashing=all", "build:production": "ng build --aot=true --output-hashing=all --configuration production", + "featureflags": "node scripts/encryptFeatureFlags.mjs main", "watch": "ng build --watch --configuration development", "test": "ng test" }, @@ -104,6 +106,7 @@ "karma-coverage": "~2.0.3", "karma-jasmine": "~4.0.0", "karma-jasmine-html-reporter": "^1.7.0", + "npm-run-all": "^4.1.5", "prettier": "^3.1.1", "typescript": "~4.9.5" } diff --git a/scripts/encryptFeatureFlags.mjs b/scripts/encryptFeatureFlags.mjs new file mode 100644 index 000000000..b5f1394b7 --- /dev/null +++ b/scripts/encryptFeatureFlags.mjs @@ -0,0 +1,43 @@ +import fs from 'fs'; +import { v5 } from 'uuid'; + +const args = process.argv; +if (args.length < 3) { + console.error( + 'Missing env:: `node encryptFeatureFlags.mjs `', + ); + process.exit(1); +} + +const env = args[2]; + +const envs = { develop: 'dev', serenity: 'serenity', euphoria: 'euphoria', main: 'main' }; +const getEnv = () => { + return envs[env] || 'dev'; +}; + +const namespace = '32bf670d-a39e-46a7-8546-2a11d3c16b33'; +const encryptConfig = async () => { + try { + const config = ( + await import(`./feature-flags/${getEnv()}/config.json`, { + assert: { type: 'json' }, + }) + ).default; + + const flags = {}; + for (const flag of Object.entries(config)) { + flags[v5(flag[0], namespace)] = flag[1]; + } + + fs.writeFile('src/assets/config/feature-flags.json', JSON.stringify(flags), function (err) { + if (err) { + console.log(err); + } + }); + return config; + } catch (e) { + console.error(e); + } +}; +encryptConfig(); diff --git a/scripts/feature-flags/dev/config.json b/scripts/feature-flags/dev/config.json new file mode 100644 index 000000000..72367d8c4 --- /dev/null +++ b/scripts/feature-flags/dev/config.json @@ -0,0 +1 @@ +{ "devTest": true, "enhanceEventLog": true, "setTokenInfo": true } diff --git a/scripts/feature-flags/euphoria/config.json b/scripts/feature-flags/euphoria/config.json new file mode 100644 index 000000000..6eb07f737 --- /dev/null +++ b/scripts/feature-flags/euphoria/config.json @@ -0,0 +1 @@ +{ "devTest": false, "enhanceEventLog": false, "setTokenInfo": false } diff --git a/scripts/feature-flags/main/config.json b/scripts/feature-flags/main/config.json new file mode 100644 index 000000000..6eb07f737 --- /dev/null +++ b/scripts/feature-flags/main/config.json @@ -0,0 +1 @@ +{ "devTest": false, "enhanceEventLog": false, "setTokenInfo": false } diff --git a/scripts/feature-flags/serenity/config.json b/scripts/feature-flags/serenity/config.json new file mode 100644 index 000000000..d64273c8c --- /dev/null +++ b/scripts/feature-flags/serenity/config.json @@ -0,0 +1 @@ +{ "devTest": false, "enhanceEventLog": true, "setTokenInfo": true } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 9c63d9926..f762a5a1d 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -28,6 +28,8 @@ import { MediaExpandModule } from './shared/components/media-expand/media-expand import { NgHttpCachingLocalStorage, NgHttpCachingModule, NgHttpCachingStrategy } from 'ng-http-caching'; import { CommonDirectiveModule } from './core/directives/common-directive.module'; import { ChainInfoInterceptor } from './core/helpers/chain-info.interceptor'; +import { FeatureFlagService } from './core/data-services/feature-flag.service'; + initializeApp(environment.firebaseConfig); @NgModule({ @@ -65,6 +67,13 @@ initializeApp(environment.firebaseConfig); multi: true, deps: [EnvironmentService], }, + FeatureFlagService, + { + provide: APP_INITIALIZER, + useFactory: (featureFlagService: FeatureFlagService) => () => featureFlagService.load(), + multi: true, + deps: [FeatureFlagService], + }, { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true }, { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true }, { provide: HTTP_INTERCEPTORS, useClass: RequestTimeoutHttpInterceptor, multi: true }, diff --git a/src/app/core/constants/account.constant.ts b/src/app/core/constants/account.constant.ts index 918a46916..158de4b21 100644 --- a/src/app/core/constants/account.constant.ts +++ b/src/app/core/constants/account.constant.ts @@ -30,4 +30,14 @@ export const TABS_TITLE_ACCOUNT = [ { label: TabsAccount.NativeTxs, value: TabsAccountLink.NativeTxs }, { label: TabsAccount.FtsTxs, value: TabsAccountLink.FtsTxs }, { label: TabsAccount.NftTxs, value: TabsAccountLink.NftTxs }, -]; \ No newline at end of file +]; + +export const COSMOS_ACCOUNT_MESSAGE_TYPE = "/cosmos.auth.v1beta1.BaseAccount"; +export const EVM_ACCOUNT_MESSAGE_TYPE = "/ethermint.types.v1.EthAccount"; +export const COSMOS_WARNING_MESSAGE = "An account created by a EVM wallet (such as Metamask, Rabby, etc.) cannot be used to sign Cosmos transactions." +export const EVM_WARNING_MESSAGE = "An account created by a Cosmos wallet (such as Keplr, Leap,...) cannot be used to sign EVM transactions." + +export const BASE_ACCOUNT_ADDRESS = { + cosmos: "aura1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqg4ha9y", + evm: "0x0000000000000000000000000000000000000000" +} diff --git a/src/app/core/constants/account.enum.ts b/src/app/core/constants/account.enum.ts index 051494cea..b4dcf2182 100644 --- a/src/app/core/constants/account.enum.ts +++ b/src/app/core/constants/account.enum.ts @@ -63,15 +63,22 @@ export enum TabsAccountLink { export enum ETypeFtExport { CW20 = 'cw20-transfer', - ERC20 = 'erc20-transfer' + ERC20 = 'erc20-transfer', +} + +export enum ETypeNftExport { + CW721 = 'cw721-transfer', + ERC721 = 'erc721-transfer', } export enum ExportFileName { ExecutedTxs = 'cosmos-executed', EVMExecutedTxs = 'evm-executed', NativeTxs = 'native-ibc-transfer', - FtsTxs = 'fungible-token-transfer', - NftTxs = 'nft-transfer', + CW20FtsTxs = 'cw20-transfer', + ERC20FtsTxs = 'erc20-transfer', + CW721NftTxs = 'cw721-transfer', + ERC721NftTxs = 'erc721-transfer', } export enum StakeModeAccount { diff --git a/src/app/core/constants/contract.constant.ts b/src/app/core/constants/contract.constant.ts index e54d36939..51abdf27d 100644 --- a/src/app/core/constants/contract.constant.ts +++ b/src/app/core/constants/contract.constant.ts @@ -62,6 +62,7 @@ export const EVM_CONTRACT_TABLE_TEMPLATES: Array = [ isUrl: '/address', isNameTag: true, }, + { matColumnDef: 'arrow', headerCellDef: ' ', type: 'status', headerWidth: 1 }, { matColumnDef: 'to', headerCellDef: 'To', diff --git a/src/app/core/constants/feature-flags.enum.ts b/src/app/core/constants/feature-flags.enum.ts new file mode 100644 index 000000000..b51823941 --- /dev/null +++ b/src/app/core/constants/feature-flags.enum.ts @@ -0,0 +1,9 @@ +import { v5 as uuidv5 } from 'uuid'; + +const FEATURE_FLAGS_NAMESPACE = '32bf670d-a39e-46a7-8546-2a11d3c16b33'; + +export enum FeatureFlags { + DevTest = uuidv5('devTest', FEATURE_FLAGS_NAMESPACE), + EnhanceEventLog = uuidv5('enhanceEventLog', FEATURE_FLAGS_NAMESPACE), + SetTokenInfo = uuidv5('setTokenInfo', FEATURE_FLAGS_NAMESPACE), +} diff --git a/src/app/core/constants/token.constant.ts b/src/app/core/constants/token.constant.ts index a92dd5855..57191b478 100644 --- a/src/app/core/constants/token.constant.ts +++ b/src/app/core/constants/token.constant.ts @@ -50,6 +50,45 @@ export enum ETokenNFTTypeBE { export const TOKEN_EVM_BURNT = '0x0000000000000000000000000000000000000000'; +export const SOCIAL_MEDIA = { + youtube: { + name: 'youtube', + icon: 'assets/icons/icons-svg/basic/youtube.svg', + }, + twitter: { + name: 'twitter', + icon: 'assets/icons/icons-svg/basic/twitter.svg', + }, + discord: { + name: 'discord', + icon: 'assets/icons/icons-svg/basic/discord.svg', + }, + telegram: { + name: 'telegram', + icon: 'assets/icons/icons-svg/basic/telegram.svg', + }, + linkedin: { + name: 'linkedin', + icon: 'assets/icons/icons-svg/basic/linkedIn.svg', + }, + github: { + name: 'github', + icon: 'assets/icons/icons-svg/basic/github.svg', + }, + facebook: { + name: 'facebook', + icon: 'assets/icons/icons-svg/basic/fb-circle.svg', + }, + medium: { + name: 'medium', + icon: 'assets/icons/icons-svg/basic/medium.svg', + }, + otherWebsite: { + name: 'otherWebsite', + icon: 'assets/icons/icons-svg/basic/global.svg', + }, +}; + export const USDC_ADDRESS = '0x80b5a32e4f032b2a058b4f29ec95eefeeb87adcd'; export const USDC_COIN_ID = 'tether'; export const USDC_TOKEN = { diff --git a/src/app/core/data-services/api-cw20-token.service.ts b/src/app/core/data-services/api-cw20-token.service.ts index 1bfcb216f..d62e920eb 100644 --- a/src/app/core/data-services/api-cw20-token.service.ts +++ b/src/app/core/data-services/api-cw20-token.service.ts @@ -75,13 +75,15 @@ export class ApiCw20TokenService { BigNumber(token.balance).gt(0), ); - const usdcCoin = this.parseUSDCToken(USDCToken, coinsMarkets); - - const idx = tokens?.findIndex((f) => f.contract_address?.toLowerCase() === USDC_ADDRESS); - if (idx >= 0) { - tokens[idx] = usdcCoin; - } else { - tokens.push(usdcCoin); + if (USDCToken) { + const usdcCoin = this.parseUSDCToken(USDCToken, coinsMarkets); + + const idx = tokens?.findIndex((f) => f.contract_address?.toLowerCase() === USDC_ADDRESS); + if (idx >= 0) { + tokens[idx] = usdcCoin; + } else { + tokens.push(usdcCoin); + } } const allTokens = [nativeToken, ...tokens]; @@ -115,12 +117,14 @@ export class ApiCw20TokenService { } async getUSDCToken(address: string) { + if (!address) { + return null; + } const contract = this.createContract(); const balance = await contract.balanceOf(address); const name = await contract.name(); const symbol = await contract.symbol(); const decimals = await contract.decimals(); - return { ...USDC_TOKEN, tokenUrl: USDC_ADDRESS, @@ -135,7 +139,6 @@ export class ApiCw20TokenService { const USDCMarket = coinsMarkets?.find((item) => item.coinId === USDC_COIN_ID); const amount = getBalance(token?.balance || 0, token?.decimals); const value = new BigNumber(amount).multipliedBy(Number(USDCMarket?.currentPrice || 0)); - return { ...token, change: null, @@ -218,12 +221,13 @@ export class ApiCw20TokenService { parseNativeToken(account, coinsMarkets) { const nativeId = this.env.coingecko.ids[0]; const coinMarket = coinsMarkets.find((coin) => coin.coinId === nativeId); + return { name: this.env.chainName, symbol: this.currencies.coinDenom, decimals: this.currencies.coinDecimals, denom: this.currencies.coinMinimalDenom, - image: this.currencies.coinImageUrl, + image: this.currencies.coinImageUrl || coinMarket?.image, contract_address: '-', balance: account.data.total, price: coinMarket?.currentPrice || 0, diff --git a/src/app/core/data-services/feature-flag.service.ts b/src/app/core/data-services/feature-flag.service.ts new file mode 100644 index 000000000..40ff284f3 --- /dev/null +++ b/src/app/core/data-services/feature-flag.service.ts @@ -0,0 +1,36 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Subject, lastValueFrom } from 'rxjs'; +import { FeatureFlags } from '../constants/feature-flags.enum'; + +@Injectable() +export class FeatureFlagService { + private configUri = './assets/config/feature-flags.json'; + private flags: BehaviorSubject> = new BehaviorSubject({}); + + private destroyed$ = new Subject(); + constructor(private http: HttpClient) {} + + ngOnDestroy(): void { + this.destroyed$.next(); + this.destroyed$.complete(); + } + + private loadConfig() { + return lastValueFrom(this.http.get>(this.configUri)) + .then((config) => { + this.flags.next(config); + }) + .catch((err: any) => { + console.error(err); + }); + } + + async load(): Promise { + await this.loadConfig(); + } + + isEnabled(flag: FeatureFlags) { + return this.flags.value[flag] || false; + } +} diff --git a/src/app/core/directives/common-directive.module.ts b/src/app/core/directives/common-directive.module.ts index f6cc25384..9a943381b 100644 --- a/src/app/core/directives/common-directive.module.ts +++ b/src/app/core/directives/common-directive.module.ts @@ -9,6 +9,7 @@ import { ExpandableContentDirective } from './expandable-content.directive'; import { TooltipCustomizeDirective } from 'src/app/core/directives/tooltip-customize.directive'; import { DragDropDirective } from './drag-drop.directive'; import { RouterLinkActiveMenuDirective } from './routerLinkActiveMenu.directive'; +import { FeatureFlagDirective } from './feature-flag.directive'; @NgModule({ declarations: [ @@ -16,6 +17,7 @@ import { RouterLinkActiveMenuDirective } from './routerLinkActiveMenu.directive' BigNumberDirective, ImageDirective, FeatureDirective, + FeatureFlagDirective, LinkDenomDirective, CopyButtonDirective, ExpandableContentDirective, @@ -29,6 +31,7 @@ import { RouterLinkActiveMenuDirective } from './routerLinkActiveMenu.directive' BigNumberDirective, ImageDirective, FeatureDirective, + FeatureFlagDirective, LinkDenomDirective, CopyButtonDirective, ExpandableContentDirective, diff --git a/src/app/core/directives/copy-button.directive.ts b/src/app/core/directives/copy-button.directive.ts index d4fc117e2..e50ae2d76 100644 --- a/src/app/core/directives/copy-button.directive.ts +++ b/src/app/core/directives/copy-button.directive.ts @@ -92,4 +92,4 @@ export class CopyButtonDirective implements OnChanges { document.execCommand('copy'); document.body.removeChild(dummy); } -} +} \ No newline at end of file diff --git a/src/app/core/directives/feature-flag.directive.ts b/src/app/core/directives/feature-flag.directive.ts new file mode 100644 index 000000000..0267a31d4 --- /dev/null +++ b/src/app/core/directives/feature-flag.directive.ts @@ -0,0 +1,26 @@ +import { Directive, ElementRef, Input, OnInit } from '@angular/core'; +import { FeatureFlagService } from '../data-services/feature-flag.service'; +import { FeatureFlags } from '../constants/feature-flags.enum'; + +@Directive({ + selector: '[featureFlag]', + providers: [], +}) +export class FeatureFlagDirective implements OnInit { + @Input() featureFlag: keyof typeof FeatureFlags; + @Input() flagEnabled: boolean = true; + + constructor( + private flags: FeatureFlagService, + private elr: ElementRef, + ) {} + + ngOnInit(): void { + if (!this.featureFlag) return; + + const actualFlagEnabled = this.flags.isEnabled(FeatureFlags[this.featureFlag]); + if (this.flagEnabled === actualFlagEnabled) return; + + this.elr.nativeElement.remove(); + } +} diff --git a/src/app/core/helpers/global-error.ts b/src/app/core/helpers/global-error.ts index a6a49e35b..98b2a47d2 100644 --- a/src/app/core/helpers/global-error.ts +++ b/src/app/core/helpers/global-error.ts @@ -3,7 +3,7 @@ import { ErrorHandler, Injectable } from '@angular/core'; @Injectable() export class GlobalErrorHandler implements ErrorHandler { - handleError(error: any): void { + handleError(error: any): void { const chunkFailedMessage = /Loading chunk [\d]+ failed/; if (chunkFailedMessage.test(error?.message)) { diff --git a/src/app/core/pipes/custom-pipe.module.ts b/src/app/core/pipes/custom-pipe.module.ts index 37e1b09ea..8e7c42f45 100644 --- a/src/app/core/pipes/custom-pipe.module.ts +++ b/src/app/core/pipes/custom-pipe.module.ts @@ -14,6 +14,7 @@ import { ObjectKeysPipe } from './object-keys.pipe'; import { CombineTxsMsgPipe, EllipsisPipe } from './string.pipe'; import { NameTagTooltipPipe } from './tooltip.pipe'; import { HighlightFunctionPipe } from './highlight-function.pipe'; +import { NewlinePipe } from './newline.pipe'; @NgModule({ imports: [CommonModule], @@ -43,6 +44,7 @@ import { HighlightFunctionPipe } from './highlight-function.pipe'; CapacityPipe, EvmAddressPipe, HighlightFunctionPipe, + NewlinePipe ], exports: [ JsonPipe, @@ -70,6 +72,7 @@ import { HighlightFunctionPipe } from './highlight-function.pipe'; CapacityPipe, EvmAddressPipe, HighlightFunctionPipe, + NewlinePipe ], providers: [], }) diff --git a/src/app/core/pipes/evm-address.pipe.ts b/src/app/core/pipes/evm-address.pipe.ts index 522125f35..5f63d6441 100644 --- a/src/app/core/pipes/evm-address.pipe.ts +++ b/src/app/core/pipes/evm-address.pipe.ts @@ -1,11 +1,14 @@ import { Pipe, type PipeTransform } from '@angular/core'; import { getEvmChecksumAddress } from '../utils/common/address-converter'; +import { EWalletType } from '../constants/wallet.constant'; @Pipe({ - name: 'appEvmAddress', + name: 'beautyAddress', }) export class EvmAddressPipe implements PipeTransform { transform(value: string): string { + if (!value?.startsWith(EWalletType.EVM)) return value; + return getEvmChecksumAddress(value); } } diff --git a/src/app/core/pipes/newline.pipe.ts b/src/app/core/pipes/newline.pipe.ts new file mode 100644 index 000000000..61052a3e0 --- /dev/null +++ b/src/app/core/pipes/newline.pipe.ts @@ -0,0 +1,14 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { DomSanitizer } from '@angular/platform-browser'; + +@Pipe({ name: 'newline' }) +export class NewlinePipe implements PipeTransform { + constructor(private sanitizer: DomSanitizer) {} + transform(value: string) { + if (!value) return null; + let replacedValue = value; + replacedValue = replacedValue?.replace(/\n/gi, '
'); + return this.sanitizer.bypassSecurityTrustHtml(replacedValue); + } +} + diff --git a/src/app/core/services/account.service.ts b/src/app/core/services/account.service.ts index 5707e9c44..547c2f746 100644 --- a/src/app/core/services/account.service.ts +++ b/src/app/core/services/account.service.ts @@ -8,9 +8,12 @@ import { ApiCw20TokenService } from '../data-services/api-cw20-token.service'; import { TYPE_CW4973 } from '../constants/contract.constant'; import { EnvironmentService } from '../data-services/environment.service'; import { CommonService } from './common.service'; +import { isEvmAddress } from '../utils/common/validation'; @Injectable() export class AccountService extends CommonService { + lcd = this.environmentService.chainConfig.chain_info.rest; + constructor( private http: HttpClient, private environmentService: EnvironmentService, @@ -20,6 +23,10 @@ export class AccountService extends CommonService { super(http, environmentService); } + getAccountInfo(address: string) { + return this.http.get(`${this.lcd}/cosmos/auth/v1beta1/accounts/${address}`); + } + getAccountDetail(account_id: string | number): Observable { return this.apiService.getAccountByAddress(account_id as string); } @@ -182,7 +189,7 @@ export class AccountService extends CommonService { } getAssetERC721ByOwner(payload): Observable { - if (payload.keyword?.length >= LENGTH_CHARACTER.EVM_ADDRESS) { + if (payload.keyword?.length >= LENGTH_CHARACTER.EVM_ADDRESS && isEvmAddress(payload.keyword)) { payload.contractAddress = payload.keyword; } else if (payload.keyword?.length > 0) { payload.token_id = payload.keyword; diff --git a/src/app/core/services/contract.service.ts b/src/app/core/services/contract.service.ts index 8a8e8e40a..cdd5e35ca 100644 --- a/src/app/core/services/contract.service.ts +++ b/src/app/core/services/contract.service.ts @@ -210,6 +210,10 @@ export class ContractService extends CommonService { symbol name } + erc721_contract { + symbol + name + } evm_contract_verifications(limit: 1, where: {status: {_eq:"SUCCESS"}}){ status } @@ -696,6 +700,33 @@ export class ContractService extends CommonService { .pipe(map((res) => (res?.data ? res?.data[this.envDB] : null))); } + + getListProxyAbi(addressList: string[]) { + const query = `query ListProxyContractDetail($address: [String] = null) { + ${this.envDB} { + evm_smart_contract(where: {address: {_in: $address}}) { + address + evm_proxy_histories(order_by: {block_height: desc}, where: {implementation_contract: {_is_null: false}}) { + proxy_contract + implementation_contract + block_height + } + } + } + } + `; + + return this.http + .post(this.graphUrl, { + query: query, + variables: { + address: addressList, + }, + operationName: 'ListProxyContractDetail', + }) + .pipe(map((res) => (res?.data ? res?.data[this.envDB] : null))); + } + queryTokenByContractAddress(address: string) { if (address.toLowerCase() == this.environmentService.coinMinimalDenom) { return of({ diff --git a/src/app/core/services/token.service.ts b/src/app/core/services/token.service.ts index 52e8857b3..7c5d0548b 100644 --- a/src/app/core/services/token.service.ts +++ b/src/app/core/services/token.service.ts @@ -8,7 +8,7 @@ import { CW20_TRACKING } from '../constants/common.constant'; import { LCD_COSMOS } from '../constants/url.constant'; import { EnvironmentService } from '../data-services/environment.service'; import { CommonService } from './common.service'; -import { TOKEN_EVM_BURNT } from '../constants/token.constant'; +import { SOCIAL_MEDIA, TOKEN_EVM_BURNT } from '../constants/token.constant'; @Injectable({ providedIn: 'root' }) export class TokenService extends CommonService { @@ -141,28 +141,29 @@ export class TokenService extends CommonService { .pipe(map((res) => (res?.data ? res?.data[this.envDB] : null))); } - getListErc721Token(payload, textSearch: string = null, address: string = null): Observable { - let queryUpdate = ''; - if (textSearch?.length > 0) { - queryUpdate = `erc721_contract: { _or: [{name: {_ilike: "%${textSearch}%"}} , {evm_smart_contract: {address: {_in: ${address} }}}]}`; - } - - let querySort = `, order_by: [{${payload.sort_column}: ${payload.sort_order}}, {id: desc}]`; + getListErc721Token(payload, textSearch: string = null, addressIn: string[] = []): Observable { + let querySort = `order_by: [{erc721_stat: {${payload.sort_column}: ${ + payload.sort_order === 'asc' ? 'asc_nulls_first' : 'desc_nulls_last' + } }}, {id: desc}]`; + let queryWhere = `where: {_or: [{address: {_in: $addressIn}}, {name: {_ilike: "%${textSearch}%"}}]}`; const operationsDoc = ` - query queryListErc721($limit: Int = 10, $offset: Int = 0) { + query queryListErc721($limit: Int = 10, $offset: Int = 0, $addressIn: [String!] = null) { ${this.envDB} { - list_token: erc721_stats(limit: $limit, offset: $offset ${querySort}, where: { ${queryUpdate} }) { - transfer_24h - total_activity - erc721_contract { - name - symbol - evm_smart_contract { - address - } + list_token: erc721_contract( + limit: $limit + offset: $offset + ${querySort} + ${queryWhere} + ) { + address + name + symbol + erc721_stat { + total_activity + transfer_24h } } - total_token: erc721_stats_aggregate (where: { ${queryUpdate} }) { + total_token: erc721_contract_aggregate (${queryWhere}) { aggregate { count } @@ -176,6 +177,7 @@ export class TokenService extends CommonService { variables: { limit: payload.limit || 20, offset: payload.offset || 0, + addressIn: addressIn, }, operationName: 'queryListErc721', }) @@ -962,4 +964,21 @@ export class TokenService extends CommonService { }) .pipe(map((res) => (res?.data ? res?.data[this.envDB] : null))); } + + mappingSocialProfiles(socialProfiles: { [key: string]: string }) { + if (!socialProfiles) return []; + + const socialMapping = []; + Object.keys(SOCIAL_MEDIA).forEach((key) => { + if (socialProfiles[key]) { + const social = { + name: SOCIAL_MEDIA[key]?.name, + icon: SOCIAL_MEDIA[key]?.icon, + url: socialProfiles[key], + } + socialMapping.push(social); + } + }) + return socialMapping; + } } diff --git a/src/app/core/services/transaction.service.ts b/src/app/core/services/transaction.service.ts index de139cf77..30433c56d 100644 --- a/src/app/core/services/transaction.service.ts +++ b/src/app/core/services/transaction.service.ts @@ -143,7 +143,7 @@ export class TransactionService extends CommonService { ${this.envDB} { transaction( limit: $limit - order_by: [{ height: $order}], + order_by: [{ id: $order}], where: {evm_transaction: {hash: {_is_null: false}}} ) { id @@ -776,6 +776,34 @@ export class TransactionService extends CommonService { .pipe(map((res) => (res?.data ? res?.data[this.envDB] : null))); } + getListAbiContract(addressList: string[]) { + const operationsDoc = ` + query getListAbiContract($address: [String] = null) { + ${this.envDB} { + evm_contract_verification(where: {contract_address: {_in: $address}, status: {_eq: "SUCCESS"}}, order_by: {id: desc}) { + contract_address + created_at + creator_tx_hash + id + status + updated_at + abi + } + } + } + `; + + return this.http + .post(this.graphUrl, { + query: operationsDoc, + variables: { + address: addressList, + }, + operationName: 'getListAbiContract', + }) + .pipe(map((res) => (res?.data ? res?.data[this.envDB] : null))); + } + getListMappingName(methodId: any): Observable { const operationsDoc = ` query queryListNameMethod($limit: Int = 100, $methodId: [String!] = null) { diff --git a/src/app/core/services/user.service.ts b/src/app/core/services/user.service.ts index e485ddf3a..566f02753 100644 --- a/src/app/core/services/user.service.ts +++ b/src/app/core/services/user.service.ts @@ -136,6 +136,28 @@ export class UserService { .pipe(map((res) => (res?.data ? res?.data[this.envDB] : null))); } + getAccountInfoOfAddress(payload) { + const operationsDoc = ` + query QueryAccountInfo($address: String!) { + ${this.envDB} { + account(where: {address: {_eq: $address}}){ + type + sequence + pubkey + } + } + } + `; + + return this.http + .post(this.graphUrl, { + query: operationsDoc, + variables: payload, + operationName: 'QueryAccountInfo', + }) + .pipe(map((res) => (res?.data ? res?.data[this.envDB] : {}))); + } + getListEvmTxByAddress(payload) { const operationsDoc = ` query QueryEvmTxOfAccount($startTime: timestamptz = null, $endTime: timestamptz = null, $limit: Int = null, $orderId: order_by = desc, $address: String! = null) { @@ -240,27 +262,27 @@ export class UserService { getCW20TxByAddress(payload) { const operationsDoc = ` query QueryCW20ListTX( - $receiver: String = null, - $sender: String = null, - $heightGT: Int = null, - $heightLT: Int = null, - $limit: Int = 100, + $receiver: String = null, + $sender: String = null, + $heightGT: Int = null, + $heightLT: Int = null, + $limit: Int = 100, $actionIn: [String!] = null, $actionNotIn: [String!] = null, - $startTime: timestamptz = null, + $startTime: timestamptz = null, $endTime: timestamptz = null ) { ${this.envDB} { transaction( where: { cw20_activities: { - _or: [{to: {_eq: $receiver}}, {from: {_eq: $sender}}], + _or: [{to: {_eq: $receiver}}, {from: {_eq: $sender}}], action: {_in: $actionIn, _nin: $actionNotIn} }, - height: {_gt: $heightGT, _lt: $heightLT}, + height: {_gt: $heightGT, _lt: $heightLT}, timestamp: {_lte: $endTime, _gte: $startTime} - }, - order_by: {height: desc}, + }, + order_by: {height: desc}, limit: $limit) { hash height @@ -285,7 +307,7 @@ export class UserService { } } } - } + } }`; return this.http .post(this.graphUrl, { @@ -443,7 +465,6 @@ export class UserService { $heightGT: Int = null $heightLT: Int = null $limit: Int = null - $neqCw4973: String $actionIn: [String!] = null $actionNotIn: [String!] = null ) { @@ -453,7 +474,6 @@ export class UserService { erc721_activities: { _or: [{ to: { _eq: $receiver } }, { from: { _eq: $sender } }] action: { _in: $actionIn, _nin: $actionNotIn } - erc721_contract: { name: { _neq: $neqCw4973 } } } transaction: { timestamp: { _gte: $startTime, _lte: $endTime } @@ -480,7 +500,10 @@ export class UserService { type } erc721_activities( - where: { _or: [{ to: { _eq: $receiver } }, { from: { _eq: $sender } }] } + where: { + _or: [{ to: { _eq: $receiver } }, { from: { _eq: $sender } }] + action: { _in: $actionIn, _nin: $actionNotIn } + } ) { action from @@ -511,10 +534,10 @@ export class UserService { actionIn: ERC721_TRACKING, actionNotIn: null, // ['approve', 'instantiate', 'revoke'] limit: payload.limit, - neqCw4973: 'crates.io:cw4973', }, operationName: 'QueryERC721ListTX', }) .pipe(map((res) => (res?.data ? res?.data[this.envDB] : null))); } } + diff --git a/src/app/core/services/wallet.service.ts b/src/app/core/services/wallet.service.ts index 2b97e72da..5a93bf676 100644 --- a/src/app/core/services/wallet.service.ts +++ b/src/app/core/services/wallet.service.ts @@ -255,7 +255,10 @@ export class WalletService implements OnDestroy { this.connectToChain(); }, 1000); }; - (window as any).ethereum?.on('accountsChanged', reconnect); + + (window as any).ethereum?.on('accountsChanged', () => { + this.connectEvmWallet(true); + }); (window as any).ethereum?.on('chainChanged', reconnect); } @@ -421,9 +424,9 @@ export class WalletService implements OnDestroy { ); } - async connectEvmWallet() { + async connectEvmWallet(changedWallet = false) { const connected = await this.connectToChain(); - if (!connected) { + if (!changedWallet && !connected) { return; } @@ -473,3 +476,4 @@ export class WalletService implements OnDestroy { return transferAddress(this.env.chainInfo.bech32Config.bech32PrefixAccAddr, address); } } + diff --git a/src/app/core/utils/ethers/utils.ts b/src/app/core/utils/ethers/utils.ts index 3d1214392..91dfd21da 100644 --- a/src/app/core/utils/ethers/utils.ts +++ b/src/app/core/utils/ethers/utils.ts @@ -40,3 +40,37 @@ export async function addNetwork(chain) { console.error(addError); } } + +export const hex2a = (hex: string) => { + if(!hex && typeof hex != 'string') return ""; + const data = hex.toString(); + let str = ''; + for (let i = 0; i < data.length; i += 2) + str += String.fromCharCode(parseInt(data.substr(i, 2), 16)); + return str; +} + +export const getValueOfKeyInObject = (obj: object, key: string) => { + let result = null; + if(obj instanceof Array) { + for(const element of obj) { + result = getValueOfKeyInObject(element, key); + if (result) { + break; + } + } + } else { + for(let prop in obj) { + if(prop === key) { + return obj[key] || {}; + } + if(obj[prop] instanceof Object || obj[prop] instanceof Array) { + result = getValueOfKeyInObject(obj[prop], key); + if (result) { + break; + } + } + } + } + return result; +} diff --git a/src/app/layouts/horizontaltopbar/horizontaltopbar.component.html b/src/app/layouts/horizontaltopbar/horizontaltopbar.component.html index 5dd5c4f2a..32c5e5c35 100644 --- a/src/app/layouts/horizontaltopbar/horizontaltopbar.component.html +++ b/src/app/layouts/horizontaltopbar/horizontaltopbar.component.html @@ -17,7 +17,10 @@ -
{{ pageTitle }}
+
+ {{ pageTitle }} +
DEV test feature flags
+
diff --git a/src/app/layouts/horizontaltopbar/horizontaltopbar.component.ts b/src/app/layouts/horizontaltopbar/horizontaltopbar.component.ts index 1630d445c..fa34a7dd1 100644 --- a/src/app/layouts/horizontaltopbar/horizontaltopbar.component.ts +++ b/src/app/layouts/horizontaltopbar/horizontaltopbar.component.ts @@ -13,6 +13,8 @@ import { LENGTH_CHARACTER, STORAGE_KEYS } from '../../../app/core/constants/comm import { TransactionService } from '../../core/services/transaction.service'; import { MENU, MenuName } from './menu'; import { MenuItem } from './menu.model'; +import { FeatureFlagService } from 'src/app/core/data-services/feature-flag.service'; +import { FeatureFlags } from 'src/app/core/constants/feature-flags.enum'; @Component({ selector: 'app-horizontaltopbar', templateUrl: './horizontaltopbar.component.html', @@ -45,6 +47,7 @@ export class HorizontaltopbarComponent implements OnInit, OnDestroy { private environmentService: EnvironmentService, private nameTagService: NameTagService, private userService: UserService, + private featureFlag: FeatureFlagService, ) {} ngOnDestroy(): void { @@ -57,6 +60,10 @@ export class HorizontaltopbarComponent implements OnInit, OnDestroy { this.checkEnv(); this.checkFeatures(); + if (this.featureFlag.isEnabled(FeatureFlags.DevTest)) { + console.warn('FeatureFlags.DevTest is enabled. remove later!'); + } + this.userService.user$?.pipe(takeUntil(this.destroy$)).subscribe((currentUser) => { this.userEmail = currentUser ? currentUser.email : null; }); diff --git a/src/app/pages/account/account-detail/account-detail.component.html b/src/app/pages/account/account-detail/account-detail.component.html index 14af60552..5e6bc8517 100644 --- a/src/app/pages/account/account-detail/account-detail.component.html +++ b/src/app/pages/account/account-detail/account-detail.component.html @@ -1,31 +1,38 @@ -