remerge_after_web_component

This commit is contained in:
Pascal 2024-12-03 16:43:56 +01:00
commit 4afdcf9a7a
21 changed files with 1495 additions and 432 deletions

3
.env Normal file
View File

@ -0,0 +1,3 @@
# .env
VITE_API_URL=https://api.example.com
VITE_API_KEY=your_api_key

3
.gitignore vendored
View File

@ -3,4 +3,5 @@ pkg/
Cargo.lock
node_modules/
dist/
.vscode
.vscode
public/ssl/

View File

@ -17,6 +17,11 @@
<!-- 4NK Web5 Solution -->
</div>
<!-- <script type="module" src="/src/index.ts"></script> -->
<script type="module" src="/src/router.ts"></script>
<script type="module">
import { init } from '/src/router.ts';
(async () => {
await init();
})();
</script>
</body>
</html>

368
package-lock.json generated
View File

@ -14,6 +14,7 @@
"@vitejs/plugin-react": "^4.3.1",
"@vitejs/plugin-vue": "^5.0.5",
"html5-qrcode": "^2.3.8",
"qr-scanner": "^1.4.2",
"qrcode": "^1.5.3",
"sweetalert2": "^11.14.5",
"vite-plugin-copy": "^0.1.6",
@ -21,6 +22,7 @@
"vite-plugin-wasm": "^3.3.0"
},
"devDependencies": {
"@rollup/plugin-typescript": "^12.1.1",
"copy-webpack-plugin": "^12.0.2",
"html-webpack-plugin": "^5.6.0",
"prettier": "^3.3.3",
@ -941,6 +943,69 @@
"node": ">=14"
}
},
"node_modules/@rollup/plugin-typescript": {
"version": "12.1.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-12.1.1.tgz",
"integrity": "sha512-t7O653DpfB5MbFrqPe/VcKFFkvRuFNp9qId3xq4Eth5xlyymzxNpye2z8Hrl0RIMuXTSr5GGcFpkdlMeacUiFQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@rollup/pluginutils": "^5.1.0",
"resolve": "^1.22.1"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^2.14.0||^3.0.0||^4.0.0",
"tslib": "*",
"typescript": ">=3.7.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
},
"tslib": {
"optional": true
}
}
},
"node_modules/@rollup/plugin-typescript/node_modules/@rollup/pluginutils": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz",
"integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^4.0.2"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/plugin-typescript/node_modules/picomatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/@rollup/pluginutils": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
@ -1348,6 +1413,12 @@
"@types/node": "*"
}
},
"node_modules/@types/offscreencanvas": {
"version": "2019.7.3",
"resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz",
"integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==",
"license": "MIT"
},
"node_modules/@types/qrcode": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.5.tgz",
@ -1780,9 +1851,10 @@
}
},
"node_modules/acorn": {
"version": "8.12.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
"version": "8.14.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
@ -1790,15 +1862,6 @@
"node": ">=0.4.0"
}
},
"node_modules/acorn-import-attributes": {
"version": "1.9.5",
"resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz",
"integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==",
"dev": true,
"peerDependencies": {
"acorn": "^8"
}
},
"node_modules/ajv": {
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz",
@ -1923,10 +1986,11 @@
}
},
"node_modules/body-parser": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
"version": "1.20.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
"integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"dev": true,
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.5",
@ -1936,7 +2000,7 @@
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.11.0",
"qs": "6.13.0",
"raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
@ -1951,6 +2015,7 @@
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
@ -1960,6 +2025,7 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
@ -1968,7 +2034,8 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true
"dev": true,
"license": "MIT"
},
"node_modules/bonjour-service": {
"version": "1.2.1",
@ -2006,9 +2073,9 @@
}
},
"node_modules/browserslist": {
"version": "4.23.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz",
"integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==",
"version": "4.24.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz",
"integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==",
"funding": [
{
"type": "opencollective",
@ -2023,11 +2090,12 @@
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"caniuse-lite": "^1.0.30001629",
"electron-to-chromium": "^1.4.796",
"node-releases": "^2.0.14",
"update-browserslist-db": "^1.0.16"
"caniuse-lite": "^1.0.30001669",
"electron-to-chromium": "^1.5.41",
"node-releases": "^2.0.18",
"update-browserslist-db": "^1.1.1"
},
"bin": {
"browserslist": "cli.js"
@ -2070,6 +2138,7 @@
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
@ -2102,9 +2171,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001640",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz",
"integrity": "sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA==",
"version": "1.0.30001684",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001684.tgz",
"integrity": "sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==",
"funding": [
{
"type": "opencollective",
@ -2118,7 +2187,8 @@
"type": "github",
"url": "https://github.com/sponsors/ai"
}
]
],
"license": "CC-BY-4.0"
},
"node_modules/chalk": {
"version": "2.4.2",
@ -2386,6 +2456,7 @@
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@ -2396,10 +2467,11 @@
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
},
"node_modules/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
"integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@ -2441,10 +2513,11 @@
"dev": true
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
@ -2555,6 +2628,7 @@
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
@ -2584,6 +2658,7 @@
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
@ -2593,6 +2668,7 @@
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
@ -2737,9 +2813,10 @@
}
},
"node_modules/electron-to-chromium": {
"version": "1.4.816",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.816.tgz",
"integrity": "sha512-EKH5X5oqC6hLmiS7/vYtZHZFTNdhsYG5NVPRN6Yn0kQHNBlT59+xSM8HBy66P5fxWpKgZbPqb+diC64ng295Jw=="
"version": "1.5.65",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.65.tgz",
"integrity": "sha512-PWVzBjghx7/wop6n22vS2MLU8tKGd4Q91aCEGhG/TYmW6PP5OcSXcdnxTe1NNt0T66N8D6jxh4kC8UsdzOGaIw==",
"license": "ISC"
},
"node_modules/emoji-regex": {
"version": "9.2.2",
@ -2754,19 +2831,21 @@
"integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw=="
},
"node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/enhanced-resolve": {
"version": "5.17.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz",
"integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==",
"version": "5.17.1",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
"integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
"dev": true,
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.4",
"tapable": "^2.2.0"
@ -2800,6 +2879,7 @@
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"get-intrinsic": "^1.2.4"
},
@ -2812,6 +2892,7 @@
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
@ -2860,9 +2941,10 @@
}
},
"node_modules/escalade": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
@ -2934,6 +3016,7 @@
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@ -2977,37 +3060,38 @@
}
},
"node_modules/express": {
"version": "4.19.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
"body-parser": "1.20.2",
"body-parser": "1.20.3",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
"cookie": "0.6.0",
"cookie": "0.7.1",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
"encodeurl": "~1.0.2",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "1.2.0",
"finalhandler": "1.3.1",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"merge-descriptors": "1.0.1",
"merge-descriptors": "1.0.3",
"methods": "~1.1.2",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.7",
"path-to-regexp": "0.1.10",
"proxy-addr": "~2.0.7",
"qs": "6.11.0",
"qs": "6.13.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "0.18.0",
"serve-static": "1.15.0",
"send": "0.19.0",
"serve-static": "1.16.2",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"type-is": "~1.6.18",
@ -3139,13 +3223,14 @@
}
},
"node_modules/finalhandler": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
"integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
"integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"encodeurl": "~1.0.2",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
@ -3161,6 +3246,7 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
@ -3169,7 +3255,8 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true
"dev": true,
"license": "MIT"
},
"node_modules/find-up": {
"version": "4.1.0",
@ -3256,6 +3343,7 @@
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@ -3316,6 +3404,7 @@
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
@ -3443,6 +3532,7 @@
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"dev": true,
"license": "MIT",
"dependencies": {
"get-intrinsic": "^1.1.3"
},
@ -3474,6 +3564,7 @@
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0"
},
@ -3486,6 +3577,7 @@
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
@ -3498,6 +3590,7 @@
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
@ -3670,6 +3763,7 @@
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"depd": "2.0.0",
"inherits": "2.0.4",
@ -3702,10 +3796,11 @@
}
},
"node_modules/http-proxy-middleware": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz",
"integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==",
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz",
"integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/http-proxy": "^1.17.8",
"http-proxy": "^1.18.1",
@ -3748,6 +3843,7 @@
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"dev": true,
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
@ -4246,6 +4342,7 @@
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
@ -4270,10 +4367,14 @@
}
},
"node_modules/merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
"dev": true
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
"integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/merge-stream": {
"version": "2.0.0",
@ -4299,9 +4400,10 @@
}
},
"node_modules/micromatch": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
"integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"license": "MIT",
"dependencies": {
"braces": "^3.0.3",
"picomatch": "^2.3.1"
@ -4315,6 +4417,7 @@
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"dev": true,
"license": "MIT",
"bin": {
"mime": "cli.js"
},
@ -4457,9 +4560,10 @@
}
},
"node_modules/node-releases": {
"version": "2.0.14",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw=="
"version": "2.0.18",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
"integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
"license": "MIT"
},
"node_modules/normalize-path": {
"version": "3.0.0",
@ -4494,10 +4598,11 @@
}
},
"node_modules/object-inspect": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
"integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
"version": "1.13.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
"integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
@ -4700,10 +4805,11 @@
}
},
"node_modules/path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
"dev": true
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
"integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
"dev": true,
"license": "MIT"
},
"node_modules/path-type": {
"version": "5.0.0",
@ -4850,6 +4956,15 @@
"node": ">=6"
}
},
"node_modules/qr-scanner": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/qr-scanner/-/qr-scanner-1.4.2.tgz",
"integrity": "sha512-kV1yQUe2FENvn59tMZW6mOVfpq9mGxGf8l6+EGaXUOd4RBOLg7tRC83OrirM5AtDvZRpdjdlXURsHreAOSPOUw==",
"license": "MIT",
"dependencies": {
"@types/offscreencanvas": "^2019.6.4"
}
},
"node_modules/qrcode": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz",
@ -4868,12 +4983,13 @@
}
},
"node_modules/qs": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.0.4"
"side-channel": "^1.0.6"
},
"engines": {
"node": ">=0.6"
@ -4924,6 +5040,7 @@
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"dev": true,
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
@ -4939,6 +5056,7 @@
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
@ -5216,7 +5334,8 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true
"dev": true,
"license": "MIT"
},
"node_modules/schema-utils": {
"version": "4.2.0",
@ -5265,10 +5384,11 @@
}
},
"node_modules/send": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
"integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
"dev": true,
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
@ -5293,6 +5413,7 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
@ -5301,13 +5422,25 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true
"dev": true,
"license": "MIT"
},
"node_modules/send/node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/send/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
"dev": true,
"license": "MIT"
},
"node_modules/serialize-javascript": {
"version": "6.0.2",
@ -5397,15 +5530,16 @@
}
},
"node_modules/serve-static": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
"integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
"version": "1.16.2",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
"integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
"dev": true,
"license": "MIT",
"dependencies": {
"encodeurl": "~1.0.2",
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
"send": "0.18.0"
"send": "0.19.0"
},
"engines": {
"node": ">= 0.8.0"
@ -5421,6 +5555,7 @@
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"dev": true,
"license": "MIT",
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
@ -5437,7 +5572,8 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
"dev": true
"dev": true,
"license": "ISC"
},
"node_modules/shallow-clone": {
"version": "3.0.1",
@ -5486,6 +5622,7 @@
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.7",
"es-errors": "^1.3.0",
@ -5589,6 +5726,7 @@
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
@ -5894,6 +6032,7 @@
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.6"
}
@ -6035,6 +6174,7 @@
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"dev": true,
"license": "MIT",
"dependencies": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
@ -6086,14 +6226,15 @@
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/update-browserslist-db": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
"integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
"integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==",
"funding": [
{
"type": "opencollective",
@ -6108,9 +6249,10 @@
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"escalade": "^3.1.2",
"picocolors": "^1.0.1"
"escalade": "^3.2.0",
"picocolors": "^1.1.0"
},
"bin": {
"update-browserslist-db": "cli.js"
@ -6343,21 +6485,21 @@
}
},
"node_modules/webpack": {
"version": "5.92.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.92.1.tgz",
"integrity": "sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA==",
"version": "5.96.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz",
"integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/eslint-scope": "^3.7.3",
"@types/estree": "^1.0.5",
"@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.6",
"@webassemblyjs/ast": "^1.12.1",
"@webassemblyjs/wasm-edit": "^1.12.1",
"@webassemblyjs/wasm-parser": "^1.12.1",
"acorn": "^8.7.1",
"acorn-import-attributes": "^1.9.5",
"browserslist": "^4.21.10",
"acorn": "^8.14.0",
"browserslist": "^4.24.0",
"chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.17.0",
"enhanced-resolve": "^5.17.1",
"es-module-lexer": "^1.2.1",
"eslint-scope": "5.1.1",
"events": "^3.2.0",

View File

@ -5,7 +5,7 @@
"main": "dist/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build_wasm": "wasm-pack build --out-dir ../ihm_client/dist/pkg ../sdk_client --target bundler --dev",
"build_wasm": "wasm-pack build --out-dir ../ihm_client/pkg ../sdk_client --target bundler --dev",
"start": "vite --host 0.0.0.0",
"build": "tsc && vite build",
"deploy": "sudo cp -r dist/* /var/www/html/",
@ -15,6 +15,7 @@
"author": "",
"license": "ISC",
"devDependencies": {
"@rollup/plugin-typescript": "^12.1.1",
"copy-webpack-plugin": "^12.0.2",
"html-webpack-plugin": "^5.6.0",
"prettier": "^3.3.3",
@ -33,6 +34,7 @@
"@vitejs/plugin-react": "^4.3.1",
"@vitejs/plugin-vue": "^5.0.5",
"html5-qrcode": "^2.3.8",
"qr-scanner": "^1.4.2",
"qrcode": "^1.5.3",
"sweetalert2": "^11.14.5",
"vite-plugin-copy": "^0.1.6",

788
src/4nk.css Normal file
View File

@ -0,0 +1,788 @@
:host {
--primary-color
: #3A506B;
/* Bleu métallique */
--secondary-color
: #B0BEC5;
/* Gris acier */
--accent-color
: #D68C45;
/* Cuivre */
font-family: Arial, sans-serif;
height: 100vh;
font-size: 16px;
}
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f4f4f4;
background-image: url(../assets/bgd.webp);
background-repeat:no-repeat;
background-size: cover;
background-blend-mode :soft-light;
height: 100vh;
}
.message {
margin: 30px 0;
font-size: 14px;
overflow-wrap: anywhere;
}
.message strong{
font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif;
font-size: 20px;
}
/** Modal Css */
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
justify-content: center;
align-items: center;
z-index: 3;
}
.modal-content {
width: 55%;
height: 30%;
background-color: white;
border-radius: 4px;
padding: 20px;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
}
.modal-title {
margin: 0;
padding-bottom: 8px;
width: 100%;
font-size: 0.9rem;
border-bottom: 1px solid #ccc;
}
.confirmation-box {
/* margin-top: 20px; */
align-content: center;
width: 70%;
height: 20%;
/* padding: 20px; */
font-size: 1.5em;
color: #333333;
top: 5%;
position: relative;
}
.nav-wrapper {
position: fixed;
background: radial-gradient(circle, white, var(--primary-color));
/* background-color: #CFD8DC; */
display: flex;
justify-content: flex-end;
align-items: center;
color: #37474F;
height: 9vh;
width: 100vw;
left: 0;
top: 0;
box-shadow: 0px 8px 10px -5px rgba(0, 0, 0, .2), 0px 16px 24px 2px rgba(0, 0, 0, .14), 0px 6px 30px 5px rgba(0, 0, 0, .12);
.nav-right-icons {
display: flex;
.notification-container {
position: relative;
display: inline-block;
}
.notification-bell, .burger-menu {
z-index: 3;
height: 20px;
width: 20px;
margin-right: 1rem;
}
.notification-badge {
position: absolute;
top: -.7rem;
left: -.8rem;
background-color: red;
color: white;
border-radius: 50%;
padding: 2.5px 6px;
font-size: 0.8rem;
font-weight: bold;
}
}
.notification-board {
position: absolute;
width: 20rem;
min-height: 8rem;
background-color: white;
right: 0.5rem;
display: none;
border-radius: 4px;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
display: none;
.notification-element {
padding: .8rem 0;
width: 100%;
&:hover {
background-color: rgba(26, 28, 24, .08);
}
}
.notification-element:not(:last-child) {
border-bottom: 1px solid;
}
}
}
.brand-logo {
height: 100%;
width: 100vw;
align-content: center;
position: relative;
display: flex;
position: absolute;
align-items: center;
justify-content: center;
text-align: center;
font-size: 1.5em;
font-weight: bold;
}
.container {
text-align: center;
display: grid;
height: 100vh;
grid-template-columns: repeat(7, 1fr);
gap: 10px;
grid-auto-rows: 10vh 15vh 1fr;
}
.title-container {
grid-column: 2 / 7;
grid-row: 2;
}
.page-container {
grid-column: 2 / 7;
grid-row: 3 ;
justify-content: center;
display: flex;
padding: 1rem;
box-sizing: border-box;
max-height: 60vh;
}
h1 {
font-size: 2em;
margin: 20px 0;
}
@media only screen and (min-width: 600px) {
.tab-container {
display: none;
}
.page-container {
display: flex;
align-items: center;
}
.process-container {
grid-column: 3 / 6;
grid-row: 3 ;
.card {
min-width: 40vw;
}
}
.separator {
width: 2px;
background-color: #78909C;
height: 80%;
margin: 0 0.5em;
}
.tab-content {
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
height: 80%;
}
}
@media only screen and (max-width: 600px) {
.process-container {
grid-column: 2 / 7;
grid-row: 3 ;
}
.container {
grid-auto-rows: 10vh 15vh 15vh 1fr;
}
.tab-container {
grid-column: 1 / 8;
grid-row: 3;
}
.page-container {
grid-column: 2 / 7;
grid-row: 4 ;
}
.separator {
display: none;
}
.tabs {
display: flex;
flex-grow: 1;
overflow: hidden;
z-index: 1;
border-bottom-style: solid;
border-bottom-width: 1px;
border-bottom-color: #E0E4D6;
}
.tab {
flex: 1;
text-align: center;
padding: 10px 0;
cursor: pointer;
font-size: 1rem;
color: #6200ea;
&:hover {
background-color: rgba(26, 28, 24, .08);
}
}
.tab.active {
border-bottom: 2px solid #6200ea;
font-weight: bold;
}
.card.tab-content {
display: none;
}
.tab-content.active {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 80%;
}
.modal-content {
width: 80%;
height: 20%;
}
}
.qr-code {
display: flex;
justify-content: center;
align-items: center;
height: 200px;
}
.emoji-display {
font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif;
font-size: 20px;
}
#emoji-display-2{
margin-top: 30px;
font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif;
font-size: 20px;
}
#okButton{
margin-bottom: 2em;
cursor: pointer;
background-color: #D0D0D7;
color: white;
border-style: none;
border-radius: 5px;
color: #000;
padding: 2px;
margin-top: 10px;
}
.pairing-request {
font-family: "Segoe UI Emoji", "Noto Color Emoji", "Apple Color Emoji", sans-serif;
font-size: 14px;
margin-top: 0px;
}
.sp-address-btn {
margin-bottom: 2em;
cursor: pointer;
background-color: #D0D0D7;
color: white;
border-style: none;
border-radius: 5px;
color: #000;
padding: 2px;
}
.camera-card {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
/* height: 200px; */
}
.btn {
display: inline-block;
padding: 10px 20px;
background-color: var(--primary-color);
color: white;
text-align: center;
border-radius: 5px;
cursor: pointer;
text-decoration: none;
}
.btn:hover {
background-color: #3700b3;
}
.card {
min-width: 300px;
border: 1px solid #e0e0e0;
border-radius: 8px;
background-color: white;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
box-sizing: border-box;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
min-height: 40vh;
max-height: 60vh;
justify-content: flex-start;
padding: 1rem;
overflow-y: auto;
}
.card-content {
flex-grow: 1;
flex-direction: column;
display: flex;
justify-content: flex-start;
align-items: center;
text-align: left;
font-size: .8em;
position: relative;
left: 2vw;
width: 90%;
.process-title {
font-weight: bold;
padding: 1rem 0;
}
.process-element {
padding: .4rem 0;
&:hover {
background-color: rgba(26, 28, 24, .08);
}
&.selected {
background-color: rgba(26, 28, 24, .08);
}
}
}
.card-description {
padding: 20px;
font-size: 1rem;
color: #333;
width: 90%;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 0px;
}
.card-action {
width: 100%;
}
.menu-content {
display: none;
position: absolute;
top: 3.4rem;
right: 1rem;
background-color: white;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
border-radius: 5px;
overflow: hidden;
}
.menu-content a {
display: block;
padding: 10px 20px;
text-decoration: none;
color: #333;
border-bottom: 1px solid #e0e0e0;
&:hover {
background-color: rgba(26, 28, 24, .08);
}
}
.menu-content a:last-child {
border-bottom: none;
}
.qr-code-scanner {
display: none;
}
/* QR READER */
#qr-reader div {
position: inherit;
}
#qr-reader div img{
top: 15px ;
right: 25px;
margin-top: 5px;
}
/* INPUT CSS **/
.input-container {
position: relative;
width: 100%;
background-color: #ECEFF1;
}
.input-field {
width: 36vw;
padding: 10px 0;
font-size: 1rem;
border: none;
border-bottom: 1px solid #ccc;
outline: none;
background: transparent;
transition: border-color 0.3s;
}
.input-field:focus {
border-bottom: 2px solid #6200ea;
}
.input-label {
position: absolute;
margin-top: -0.5em;
top: 0;
left: 0;
padding: 10px 0;
font-size: 1rem;
color: #999;
pointer-events: none;
transition: transform 0.3s, color 0.3s, font-size 0.3s;
}
.input-field:focus + .input-label,
.input-field:not(:placeholder-shown) + .input-label {
transform: translateY(-20px);
font-size: 0.8em;
color: #6200ea;
}
.input-underline {
position: absolute;
bottom: 0;
left: 50%;
width: 0;
height: 2px;
background-color: #6200ea;
transition: width 0.3s, left 0.3s;
}
.input-field:focus ~ .input-underline {
width: 100%;
left: 0;
}
.dropdown-content {
position: absolute;
flex-direction: column;
top: 100%;
left: 0;
width: 100%;
max-height: 150px;
overflow-y: auto;
border: 1px solid #ccc;
border-radius: 4px;
background-color: white;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
display: none;
z-index: 1;
}
.dropdown-content span {
padding: 10px;
cursor: pointer;
list-style: none;
}
.dropdown-content span:hover {
background-color: #f0f0f0;
}
/** AUTOCOMPLETE **/
select[data-multi-select-plugin] {
display: none !important;
}
.multi-select-component {
width: 36vw;
padding: 5px 0;
font-size: 1rem;
border: none;
border-bottom: 1px solid #ccc;
outline: none;
background: transparent;
display: flex;
flex-direction: row;
height: auto;
width: 100%;
-o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
}
.autocomplete-list {
border-radius: 4px 0px 0px 4px;
}
.multi-select-component:focus-within {
box-shadow: inset 0px 0px 0px 2px #78ABFE;
}
.multi-select-component .btn-group {
display: none !important;
}
.multiselect-native-select .multiselect-container {
width: 100%;
}
.selected-processes {
background-color: white;
padding: 0.4em;
}
.selected-wrapper {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
display: inline-block;
border: 1px solid #d9d9d9;
background-color: #ededed;
white-space: nowrap;
margin: 1px 5px 5px 0;
height: 22px;
vertical-align: top;
cursor: default;
}
.selected-wrapper .selected-label {
max-width: 514px;
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
padding-left: 4px;
vertical-align: top;
}
.selected-wrapper .selected-close {
display: inline-block;
text-decoration: none;
font-size: 14px;
line-height: 1.49rem;
margin-left: 5px;
padding-bottom: 10px;
height: 100%;
vertical-align: top;
padding-right: 4px;
opacity: 0.2;
color: #000;
text-shadow: 0 1px 0 #fff;
font-weight: 700;
}
.search-container {
display: flex;
flex-direction: row;
}
.search-container .selected-input {
background: none;
border: 0;
height: 20px;
width: 60px;
padding: 0;
margin-bottom: 6px;
-webkit-box-shadow: none;
box-shadow: none;
}
.search-container .selected-input:focus {
outline: none;
}
.dropdown-icon.active {
transform: rotateX(180deg)
}
.search-container .dropdown-icon {
display: inline-block;
padding: 10px 5px;
position: absolute;
top: 5px;
right: 5px;
width: 10px;
height: 10px;
border: 0 !important;
/* needed */
-webkit-appearance: none;
-moz-appearance: none;
/* SVG background image */
background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2212%22%20height%3D%2212%22%20viewBox%3D%220%200%2012%2012%22%3E%3Ctitle%3Edown-arrow%3C%2Ftitle%3E%3Cg%20fill%3D%22%23818181%22%3E%3Cpath%20d%3D%22M10.293%2C3.293%2C6%2C7.586%2C1.707%2C3.293A1%2C1%2C0%2C0%2C0%2C.293%2C4.707l5%2C5a1%2C1%2C0%2C0%2C0%2C1.414%2C0l5-5a1%2C1%2C0%2C1%2C0-1.414-1.414Z%22%20fill%3D%22%23818181%22%3E%3C%2Fpath%3E%3C%2Fg%3E%3C%2Fsvg%3E");
background-position: center;
background-size: 10px;
background-repeat: no-repeat;
}
.search-container ul {
position: absolute;
list-style: none;
padding: 0;
z-index: 3;
margin-top: 29px;
width: 100%;
right: 0px;
background: #fff;
border: 1px solid #ccc;
border-top: none;
border-bottom: none;
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
}
.search-container ul :focus {
outline: none;
}
.search-container ul li {
display: block;
text-align: left;
padding: 8px 29px 2px 12px;
border-bottom: 1px solid #ccc;
font-size: 14px;
min-height: 31px;
}
.search-container ul li:first-child {
border-top: 1px solid #ccc;
border-radius: 4px 0px 0 0;
}
.search-container ul li:last-child {
border-radius: 4px 0px 0 0;
}
.search-container ul li:hover.not-cursor {
cursor: default;
}
.search-container ul li:hover {
color: #333;
background-color: #f0f0f0;
;
border-color: #adadad;
cursor: pointer;
}
/* Adding scrool to select options */
.autocomplete-list {
max-height: 130px;
overflow-y: auto;
}
/**************************************** Process page card ******************************************************/
.process-card {
min-width: 300px;
border: 1px solid #e0e0e0;
border-radius: 8px;
background-color: white;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
min-height: 40vh;
max-height: 60vh;
justify-content: space-between;
padding: 1rem;
overflow-y: auto;
}
.process-card-content {
text-align: left;
font-size: .8em;
position: relative;
left: 2vw;
width: 90%;
.process-title {
font-weight: bold;
padding: 1rem 0;
}
.process-element {
padding: .4rem 0;
&:hover {
background-color: rgba(26, 28, 24, .08);
}
&.selected {
background-color: rgba(26, 28, 24, .08);
}
}
.selected-process-zone {
background-color: rgba(26, 28, 24, .08);
}
}
.process-card-description {
padding: 20px;
font-size: 1rem;
color: #333;
width: 90%;
}
.process-card-action {
width: 100%;
}

View File

@ -0,0 +1,74 @@
import QrScanner from 'qr-scanner';
import Services from '../../services/service';
import { prepareAndSendPairingTx } from '~/utils/sp-address.utils';
export default class QrScannerComponent extends HTMLElement {
videoElement: any;
wrapper: any
qrScanner: any
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.wrapper = document.createElement('div');
this.wrapper.style.position = 'relative';
this.wrapper.style.width = '150px';
this.wrapper.style.height = '150px';
this.videoElement = document.createElement('video');
this.videoElement.style.width = '100%';
document.body?.append(this.wrapper);
this.wrapper.prepend(this.videoElement);
}
connectedCallback() {
this.initializeScanner();
}
async initializeScanner() {
if (!this.videoElement) {
console.error('Video element not found!');
return;
}
console.log("🚀 ~ QrScannerComponent ~ initializeScanner ~ this.videoElement:", this.videoElement)
this.qrScanner = new QrScanner(this.videoElement, result => this.onQrCodeScanned(result),{
highlightScanRegion: true,
highlightCodeOutline: true,
});
try {
await QrScanner.hasCamera();
this.qrScanner.start();
this.videoElement.style = 'height: 200px; width: 200px'
this.shadowRoot?.appendChild(this.wrapper)
} catch (e) {
console.error('No camera found or error starting the QR scanner', e);
}
}
async onQrCodeScanned(result: any) {
console.log(`QR Code detected:`, result);
const data = result.data;
const scannedUrl = new URL(data);
// Extract the 'sp_address' parameter
const spAddress = scannedUrl.searchParams.get('sp_address');
if(spAddress) {
// Call the sendPairingTx function with the extracted sp_address
try {
await prepareAndSendPairingTx(spAddress)
} catch (e) {
console.error('Failed to pair:', e);
}
}
this.qrScanner.stop(); // if you want to stop scanning after one code is detected
}
disconnectedCallback() {
if (this.qrScanner) {
this.qrScanner.destroy();
}
}
}
customElements.define('qr-scanner', QrScannerComponent);

10
src/decs.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
declare class AccountComponent extends HTMLElement {
_callback: any;
constructor();
connectedCallback(): void;
fetchData(): Promise<void>;
set callback(fn: any);
get callback(): any;
render(): void;
}
export { AccountComponent };

View File

@ -0,0 +1,48 @@
import loginHtml from './home.html?raw'
import loginScript from './home.ts?raw'
import loginCss from '../../4nk.css?raw'
import { initHomePage } from './home';
export class LoginComponent extends HTMLElement {
_callback: any;
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
console.log('CALLBACK LOGIN PAGE')
this.render();
setTimeout(() => {
initHomePage();
}, 500);
}
set callback(fn) {
if (typeof fn === 'function') {
this._callback = fn;
} else {
console.error('Callback is not a function');
}
}
get callback() {
return this._callback;
}
render() {
if(this.shadowRoot) this.shadowRoot.innerHTML = `
<style>
${loginCss}
</style>${loginHtml}
<script type="module">
${loginScript}
</scipt>
`;
}
}
if (!customElements.get('login-4nk-component')) {
customElements.define('login-4nk-component', LoginComponent);
}

View File

@ -24,6 +24,7 @@
<div class="card-description">Scan your other device :</div>
<div class="card-image camera-card">
<img id="scanner" src="assets/camera.jpg" alt="QR Code" width="150" height="150" />
<button id="scan-btn" onclick="scanDevice()">Scan</button>
<div class="qr-code-scanner">
<div id="qr-reader" style="width: 200px; display: contents"></div>
<div id="qr-reader-results"></div>

View File

@ -1,22 +1,20 @@
import { Html5QrcodeScanner } from 'html5-qrcode';
import Routing from '../../services/modal.service';
import Services from '../../services/service';
import { addSubscription } from '../../utils/subscription.utils';
import { displayEmojis, generateQRCode } from '../../utils/sp-address.utils';
let resultContainer = document.getElementById('qr-reader-results');
let lastResult: any,
countResults = 0;
import { getCorrectDOM } from '../../utils/html.utils';
import QrScannerComponent from '../../components/qrcode-scanner/qrcode-scanner-component';
export {QrScannerComponent}
export async function initHomePage(): Promise<void> {
console.log('INIT');
document.querySelectorAll('.tab').forEach((tab) => {
console.log('INIT-HOME');
const container = getCorrectDOM('login-4nk-component') as HTMLElement
container.querySelectorAll('.tab').forEach((tab) => {
addSubscription(tab, 'click', () => {
document.querySelectorAll('.tab').forEach((t) => t.classList.remove('active'));
container.querySelectorAll('.tab').forEach((t) => t.classList.remove('active'));
tab.classList.add('active');
document.querySelectorAll('.tab-content').forEach((content) => content.classList.remove('active'));
document.getElementById(tab.getAttribute('data-tab') as string)?.classList.add('active');
container.querySelectorAll('.tab-content').forEach((content) => content.classList.remove('active'));
container.querySelector(`#${tab.getAttribute('data-tab') as string}`)?.classList.add('active');
});
});
@ -24,68 +22,6 @@ export async function initHomePage(): Promise<void> {
const spAddress = await service.getDeviceAddress();
generateQRCode(spAddress);
displayEmojis(spAddress);
const notifBell = document.getElementById('notification-bell');
if (notifBell) addSubscription(notifBell, 'click', openCloseNotifications);
var html5QrcodeScanner = new Html5QrcodeScanner('qr-reader', { fps: 10, qrbox: 250 }, undefined);
html5QrcodeScanner.render(onScanSuccess, undefined);
docReady(() => {
scanDevice();
});
}
async function onScanSuccess(decodedText: any, decodedResult: any) {
if (lastResult === decodedText) {
return;
}
lastResult = decodedText;
++countResults;
// Handle on success condition with the decoded message.
console.log(`Scan result ${decodedText}`, decodedResult);
try {
// Attempt to parse the decoded text as a URL
const scannedUrl = new URL(decodedText);
// Extract the 'sp_address' parameter
const spAddress = scannedUrl.searchParams.get('sp_address');
if (spAddress) {
html5QrcodeScanner.clear();
const service = await Services.getInstance();
// Call the sendPairingTx function with the extracted sp_address
try {
const sharedSecret = await service.getSecretForAddress(spAddress);
if (!sharedSecret) {
const member = {
sp_addresses: [spAddress],
}
await service.connectMember([member]);
}
// await service.sendPairingTx(spAddress);
} catch (e) {
console.error('Failed to pair:', e);
}
} else {
console.error('The scanned URL does not contain the sp_address parameter.');
alert('Invalid QR code: sp_address parameter missing.');
}
} catch (error) {
// Handle cases where decodedText is not a valid URL
console.error('Scanned text is not a valid URL:', error);
alert('Invalid QR code: Unable to parse URL.');
}
}
export function toggleMenu() {
let menu = document.getElementById('menu');
if (menu) {
if (menu.style.display === 'block') {
menu.style.display = 'none';
} else {
menu.style.display = 'block';
}
}
}
//// Modal
@ -94,33 +30,21 @@ export async function openModal(myAddress: string, receiverAddress: string) {
router.openLoginModal(myAddress, receiverAddress);
}
function openCloseNotifications() {
const notifications = document.querySelector('.notification-board') as HTMLDivElement;
notifications.style.display = notifications?.style.display === 'none' ? 'block' : 'none';
}
// const service = await Services.getInstance()
// service.setNotification()
(window as any).toggleMenu = toggleMenu;
(window as any).openModal = openModal;
/// Scan QR Code
function docReady(fn: any) {
// see if DOM is already available
if (document.readyState === 'complete' || document.readyState === 'interactive') {
// call on next available tick
setTimeout(fn, 1);
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}
function scanDevice() {
const scannerImg = document.querySelector('#scanner') as HTMLElement;
const container = getCorrectDOM('login-4nk-component') as HTMLElement
const scannerImg = container.querySelector('#scanner') as HTMLElement;
if (scannerImg) scannerImg.style.display = 'none';
const scannerQrCode = document.querySelector('.qr-code-scanner') as HTMLElement;
const scannerQrCode = container.querySelector('.qr-code-scanner') as HTMLElement;
if (scannerQrCode) scannerQrCode.style.display = 'block';
const scanButton = container?.querySelector('#scan-btn') as HTMLElement;
if (scanButton) scanButton.style.display = 'none';
const reader = container?.querySelector('#qr-reader')
if(reader) reader.innerHTML = '<qr-scanner></qr-scanner>'
}
(window as any).scanDevice = scanDevice;

View File

@ -36,7 +36,7 @@ export async function init() {
const processes = await getProcesses();
for (let process of processes) {
const processName = process[1].title;
const processName = process['description'];
const opt = new Option(processName);
opt.value = processName;
element.add(opt);
@ -364,7 +364,7 @@ async function showSelectedProcess(elem: MouseEvent) {
titleDiv.className = 'process-title';
titleDiv.innerHTML = `${process[1].title} : ${process[1].description}`;
processDiv.appendChild(titleDiv);
for (const zone of process[1].zones) {
for (const zone of process.zones) {
const zoneElement = document.createElement('div');
zoneElement.className = 'process-element';
const zoneId = process[1].title + '-' + zone.id;
@ -408,5 +408,10 @@ async function getProcesses(): Promise<any[]> {
const service = await Services.getInstance();
const processes = await service.getProcesses();
return processes;
const res = Object.entries(processes).map(([key, value]) => ({
key,
value
}))
return res;
}

View File

@ -3,7 +3,9 @@ import { initHeader } from '../src/components/header/header';
import Database from './services/database.service';
import Services from './services/service';
import { cleanSubscriptions } from './utils/subscription.utils';
import { LoginComponent } from './pages/home/home-component';
import { prepareAndSendPairingTx } from './utils/sp-address.utils';
export {Services};
const routes: { [key: string]: string } = {
home: '/src/pages/home/home.html',
process: '/src/pages/process/process.html',
@ -17,6 +19,7 @@ export let currentRoute = '';
export async function navigate(path: string) {
cleanSubscriptions();
cleanPage()
path = path.replace(/^\//, '');
if (path.includes('/')) {
const parsedPath = path.split('/')[0];
@ -39,17 +42,21 @@ async function handleLocation(path: string) {
const content = document.getElementById('containerId');
if (content) {
const html = await fetch(routeHtml).then((data) => data.text());
content.innerHTML = html;
if(path === 'home' ) {
const login = LoginComponent
const container = document.querySelector('#containerId');
const accountComponent = document.createElement('login-4nk-component');
accountComponent.setAttribute('style', 'width: 100vw; height: 100vh; position: relative; grid-row: 2;')
if(container) container.appendChild(accountComponent)
} else {
const html = await fetch(routeHtml).then((data) => data.text());
content.innerHTML = html;
}
await new Promise(requestAnimationFrame);
injectHeader();
switch (path) {
case 'home':
const { initHomePage } = await import('./pages/home/home');
initHomePage();
break;
case 'process':
const { init } = await import('./pages/process/process');
init();
@ -111,9 +118,10 @@ window.onpopstate = async () => {
}
};
async function init(): Promise<void> {
export async function init(): Promise<void> {
try {
const services = await Services.getInstance();
(window as any).myService = services;
await Database.getInstance();
setTimeout(async () => {
let device = await services.getDevice();
@ -125,6 +133,7 @@ async function init(): Promise<void> {
await services.restoreDevice(device);
}
await services.restoreProcesses();
await services.restoreSecrets();
if (services.isPaired()) {
await navigate('process');
@ -136,10 +145,7 @@ async function init(): Promise<void> {
setTimeout(async () => {
try {
// check if we have a shared secret with that address
const sharedSecret = await services.getSecretForAddress(pairingAddress);
if (!sharedSecret) {
await services.connectMember([{sp_addresses: [pairingAddress]}]);
}
await prepareAndSendPairingTx(pairingAddress)
} catch (e) {
console.error('Failed to pair:', e);
}
@ -154,6 +160,11 @@ async function init(): Promise<void> {
}
}
async function cleanPage() {
const container = document.querySelector('#containerId');
if(container) container.innerHTML = ''
}
async function injectHeader() {
const headerContainer = document.getElementById('header-container');
if (headerContainer) {
@ -168,8 +179,4 @@ async function injectHeader() {
}
}
(async () => {
await init();
})();
(window as any).navigate = navigate;

View File

@ -13,13 +13,13 @@ class Database {
indices: [],
},
AnkProcess: {
name: 'process',
options: { keyPath: 'id' },
name: 'processes',
options: {},
indices: [],
},
AnkSharedSecrets: {
name: 'shared_secrets',
options: { keyPath: 'key' },
options: {},
indices: [],
},
AnkUnconfirmedSecrets: {
@ -27,11 +27,6 @@ class Database {
options: { autoIncrement: true },
indices: [],
},
AnkProcessData: {
name: 'process-data',
options: { keyPath: 'id' },
indices: [],
},
};
// Private constructor to prevent direct instantiation from outside
@ -191,6 +186,36 @@ class Database {
});
return result
}
public async dumpStore(storeName: string): Promise<Record<string, any>> {
const db = await this.getDb();
const tx = db.transaction(storeName, 'readonly');
const store = tx.objectStore(storeName);
try {
// Wait for both getAllKeys() and getAll() to resolve
const [keys, values] = await Promise.all([
new Promise<any[]>((resolve, reject) => {
const request = store.getAllKeys();
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
}),
new Promise<any[]>((resolve, reject) => {
const request = store.getAll();
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
}),
]);
// Combine keys and values into an object
const result: Record<string, any> = Object.fromEntries(keys.map((key, index) => [key, values[index]]));
return result;
} catch (error) {
console.error("Error fetching data from IndexedDB:", error);
throw error;
}
}
}
export default Database;

View File

@ -4,7 +4,7 @@ import Services from './service';
import { U32_MAX } from './service';
import { navigate } from '../router';
import { addressToEmoji } from '../utils/sp-address.utils';
import { RoleDefinition } from 'dist/pkg/sdk_client';
import { RoleDefinition } from 'pkg/sdk_client';
export default class ModalService {
private static instance: ModalService;
@ -37,7 +37,7 @@ export default class ModalService {
}
async injectModal(members: any[]) {
const container = document.querySelector('.page-container');
const container = document.querySelector('#containerId');
if (container) {
let html = await fetch('/src/components/modal/confirmation-modal.html').then((res) => res.text());
html = html.replace('{{device1}}', await addressToEmoji(members[0]['sp_addresses'][0]));
@ -53,23 +53,11 @@ export default class ModalService {
}
// this is kind of too specific for pairing though
public async openConfirmationModal(pcd: any, commitmentTx: string, merkleRoot: string) {
let map: Record<string, RoleDefinition>;
if (pcd['roles']) {
const roles = pcd['roles'];
try {
map = JSON.parse(roles);
} catch (e) {
throw new Error(`Failed to parse roles: ${e}`);
}
} else {
throw new Error('Pcd doesn\'t have a \"roles\" field');
}
public async openPairingConfirmationModal(roleDefinition: Record<string, RoleDefinition>, commitmentTx: string, merkleRoot: string) {
// pairing specifics
let members;
if (map['owner']) {
const owner = map['owner'];
if (roleDefinition['owner']) {
const owner = roleDefinition['owner'];
members = owner.members;
} else {
throw new Error('No \"owner\" role');
@ -83,7 +71,6 @@ export default class ModalService {
// We take all the addresses except our own
const service = await Services.getInstance();
const localAddress = await service.getDeviceAddress();
console.log('🚀 ~ Routing ~ openConfirmationModal ~ pcd:', pcd);
for (const member of members) {
for (const address of member['sp_addresses']) {
if (address !== localAddress) {
@ -127,7 +114,7 @@ export default class ModalService {
// We send the prd update
if (this.currentPcdCommitment) {
try {
const createPrdUpdateReturn = await service.createPrdUpdate(this.currentPcdCommitment);
const createPrdUpdateReturn = service.createPrdUpdate(this.currentPcdCommitment);
await service.handleApiReturn(createPrdUpdateReturn);
} catch (e) {
throw e
@ -138,13 +125,18 @@ export default class ModalService {
// We send confirmation that we validate the change
try {
const approveChangeReturn = await service.approveChange(this.currentPcdCommitment!);
const approveChangeReturn = service.approveChange(this.currentPcdCommitment!);
await service.handleApiReturn(approveChangeReturn);
} catch (e) {
throw e
}
service.pairDevice(this.paired_addresses);
try {
service.pairDevice(this.paired_addresses);
} catch (e) {
throw e;
}
this.paired_addresses = [];
this.currentOutpoint = null;
this.currentPcdCommitment = null;

View File

@ -3,9 +3,8 @@ import { INotification } from '~/models/notification.model';
import { IProcess } from '~/models/process.model';
// import Database from './database';
import { initWebsocket, sendMessage } from '../websockets';
import { ApiReturn, Member } from '../../dist/pkg/sdk_client';
import { ApiReturn, Member, PcdUpdates, Process, RoleDefinition } from '../../pkg/sdk_client';
import ModalService from './modal.service';
import { navigate } from '../router';
import Database from './database.service';
export const U32_MAX = 4294967295;
@ -16,7 +15,7 @@ export default class Services {
private static initializing: Promise<Services> | null = null;
private static instance: Services;
private currentProcess: string | null = null;
private pendingUpdates: Record<string, any> = {};
private pendingUpdates: PcdUpdates | null = null;
private currentUpdateMerkleRoot: string | null = null;
private localAddress: string | null = null;
private pairedAddresses: string[] = [];
@ -52,7 +51,7 @@ export default class Services {
public async init(): Promise<void> {
this.notifications = this.getNotifications();
this.sdkClient = await import('../../dist/pkg/sdk_client');
this.sdkClient = await import('../../pkg/sdk_client');
this.sdkClient.setup();
await this.addWebsocketConnection(wsurl);
}
@ -69,7 +68,7 @@ export default class Services {
public isPaired(): boolean {
try {
return this.sdkClient.is_linking();
return this.sdkClient.is_paired();
} catch (e) {
throw new Error(`isPaired ~ Error: ${e}`);
}
@ -215,17 +214,17 @@ export default class Services {
}
async sendNewTxMessage(message: string) {
await sendMessage('NewTx', message);
sendMessage('NewTx', message);
}
async sendCommitMessage(message: string) {
await sendMessage('Commit', message);
sendMessage('Commit', message);
}
async sendCipherMessages(ciphers: string[]) {
for (let i = 0; i < ciphers.length; i++) {
const cipher = ciphers[i];
await sendMessage('Cipher', cipher);
sendMessage('Cipher', cipher);
}
}
@ -235,8 +234,8 @@ export default class Services {
async parseCipher(message: string) {
try {
console.log('parsing new cipher');
const apiReturn = await this.sdkClient.parse_cipher(message);
// console.log('parsing new cipher');
const apiReturn = this.sdkClient.parse_cipher(message);
console.log('🚀 ~ Services ~ parseCipher ~ apiReturn:', apiReturn);
await this.handleApiReturn(apiReturn);
} catch (e) {
@ -247,12 +246,11 @@ export default class Services {
async parseNewTx(tx: string) {
try {
const parsedTx = await this.sdkClient.parse_new_tx(tx, 0);
const parsedTx = this.sdkClient.parse_new_tx(tx, 0);
if (parsedTx) {
console.log('🚀 ~ Services ~ parseNewTx ~ parsedTx:', parsedTx);
try {
await this.handleApiReturn(parsedTx);
const newDevice = await this.dumpDevice();
const newDevice = this.dumpDevice();
await this.saveDevice(newDevice);
} catch (e) {
console.error('Failed to update device with new tx');
@ -265,10 +263,10 @@ export default class Services {
public getUpdateProposals(commitmentOutpoint: string) {
try {
const proposals: ApiReturn = this.sdkClient.get_update_proposals(commitmentOutpoint);
const proposals: PcdUpdates = this.sdkClient.get_update_proposals(commitmentOutpoint);
if (proposals.decrypted_pcds && proposals.decrypted_pcds.length != 0) {
this.currentProcess = commitmentOutpoint;
this.pendingUpdates = proposals.decrypted_pcds;
this.pendingUpdates = proposals;
} else {
throw new Error('No pending proposals');
}
@ -296,25 +294,51 @@ export default class Services {
}
const entries = Object.entries(confirmedSecrets).map(([key, value]) => ({ key, value }));
for (const entry of entries) {
db.addObject({
storeName: 'shared_secrets',
object: entry,
key: null,
});
try {
db.addObject({
storeName: 'shared_secrets',
object: entry.value,
key: entry.key,
});
} catch (e) {
throw e;
}
// We don't want to throw an error, it could simply be that we registered directly the shared secret
// this.removeUnconfirmedSecret(entry.value);
}
}
setTimeout(async () => {
if (apiReturn.updated_process && apiReturn.updated_process.length) {
const [commitmentTx, process] = apiReturn.updated_process;
if (apiReturn.updated_process) {
const updatedProcess = apiReturn.updated_process;
// Save process to storage
const db = await Database.getInstance();
db.addObject({
storeName: 'process',
object: { id: commitmentTx, process },
key: null,
});
try {
await this.saveProcess(updatedProcess.commitment_tx, updatedProcess.current_process);
} catch (e) {
throw e;
}
if (updatedProcess.new_state) {
this.currentProcess = updatedProcess.commitment_tx;
this.getUpdateProposals(this.currentProcess!);
await this.evaluatePendingUpdates();
} else if (updatedProcess.modified_state) {
// We added validation tokens
// We check if the state is now valid
// If enough validation tokens we shoot a commit msg to the relay
const [previous_state, new_state] = updatedProcess.modified_state;
const init_commitment = updatedProcess.commitment_tx;
try {
const apiReturn = this.sdkClient.evaluate_state(init_commitment, null, JSON.stringify(new_state));
await this.handleApiReturn(apiReturn);
} catch (e) {
throw e
}
}
}
if (apiReturn.commit_to_send) {
@ -341,16 +365,28 @@ export default class Services {
}
private async openConfirmationModal() {
if (this.pendingUpdates.length === 0) {
console.log('No pending updates');
if (!this.pendingUpdates || this.pendingUpdates.modified_values.length === 0) {
console.log('No pending updates to validate');
}
try {
for (const [merkleRoot, actual_proposal] of Object.entries(this.pendingUpdates)) {
await this.routingInstance.openConfirmationModal(actual_proposal, this.currentProcess!, merkleRoot);
for (const value of this.pendingUpdates!.modified_values) {
if (value.notify_user) {
// TODO notification pop up
}
if (!value.need_validation) {
continue;
}
if (value.proof) {
// It seems we already validated that, check the proof and if valid just notify user
continue;
}
const actualProposal: Record<string, RoleDefinition> = JSON.parse(value.new_value);
const merkleRoot: string = value.new_state_merkle_root;
try {
await this.routingInstance.openPairingConfirmationModal(actualProposal, this.currentProcess!, merkleRoot);
} catch (e) {
throw new Error(`${e}`);
}
} catch (e) {
throw new Error(`${e}`);
}
}
@ -444,86 +480,62 @@ export default class Services {
}
}
async getProcesses(): Promise<any[]> {
const process = [
[
'1',
{
title: 'Messaging',
description: 'Messagerie chiffrée',
html: '<div><input /></div>',
css: '',
script: '',
zones: [
{
id: '1',
title: 'zone 1',
description: 'zone 1',
},
{
id: '2',
title: 'zone 2',
description: 'zone 2',
},
],
roles: {
owner: {
members: ['dfdsfdfdsf', 'dfdfdfdsfsfdfdsf'],
validation_rules: [
{
quorum: 1.0,
fields: ['description', 'roles', 'session_privkey', 'session_pubkey', 'key_parity'],
min_sig_member: 1.0,
},
],
},
},
},
],
[
'2',
{
title: 'Database',
description: 'Database chiffrée',
html: '<div><input value="{{inputValue}}" /></div>',
css: '',
script: '',
zones: [
{
id: '1',
title: 'zone 1',
description: 'zone 1',
},
{
id: '2',
title: 'zone 2',
description: 'zone 2',
},
],
roles: {
owner: {
members: ['dfdsfdfdsf', 'dfdfdfdsfsfdfdsf'],
validation_rules: [
{
quorum: 1.0,
fields: ['description', 'roles', 'session_privkey', 'session_pubkey', 'key_parity'],
min_sig_member: 1.0,
},
],
},
},
},
],
];
return process;
public async saveProcess(commitedIn: string, process: any) {
const db = await Database.getInstance();
try {
await db.addObject({
storeName: 'processes',
object: process,
key: commitedIn,
});
} catch (e) {
throw new Error(`Failed to save process: ${e}`)
}
}
private getProcessesCache() {
console.log('TODO get processes from indexedDB')
public async getProcess(commitedIn: string): Promise<Process> {
const db = await Database.getInstance();
return await db.getObject('processes', commitedIn);
}
public async getProcesses(): Promise<Record<string, Process>> {
const db = await Database.getInstance();
const processes: Record<string, Process> = await db.dumpStore('processes');
return processes;
}
// Restore process in wasm with persistent storage
public async restoreProcesses() {
console.log('TODO: restore processes from indexedDB');
const db = await Database.getInstance();
try {
const processes: Record<string, Process> = await db.dumpStore('processes');
if (processes && Object.keys(processes).length != 0) {
console.log(`Restoring ${Object.keys(processes).length} processes`);
this.sdkClient.set_process_cache(JSON.stringify(processes));
} else {
console.log('No processes to restore!');
}
} catch (e) {
throw e;
}
}
public async restoreSecrets() {
const db = await Database.getInstance();
try {
const sharedSecrets: Record<string, string> = await db.dumpStore('shared_secrets');
const unconfirmedSecrets = await db.dumpStore('unconfirmed_secrets');
const secretsStore = {
'shared_secrets': sharedSecrets,
'unconfirmed_secrets': Object.values(unconfirmedSecrets),
};
this.sdkClient.set_shared_secrets(JSON.stringify(secretsStore));
} catch (e) {
throw e;
}
}
getNotifications(): INotification[] {

View File

@ -1,3 +1,8 @@
export function interpolate(template: string, data: { [key: string]: string }) {
return template.replace(/{{(.*?)}}/g, (_, key) => data[key.trim()]);
}
export function getCorrectDOM(componentTag: string): Node {
const dom = document?.querySelector(componentTag)?.shadowRoot || document as Node
return dom
}

View File

@ -1,4 +1,5 @@
import Services from '../services/service';
import { getCorrectDOM } from './html.utils';
import { addSubscription } from './subscription.utils';
import QRCode from 'qrcode';
@ -56,7 +57,7 @@ export async function addressToEmoji(text: string): Promise<string> {
//Get emojis from other device
async function emojisPairingRequest() {
try {
const container = document.getElementById('containerId');
const container = getCorrectDOM('login-4nk-component') as HTMLElement;
const urlParams: URLSearchParams = new URLSearchParams(window.location.search);
const sp_adress: string | null = urlParams.get('sp_address');
@ -81,7 +82,7 @@ async function emojisPairingRequest() {
export async function displayEmojis(text: string) {
console.log('🚀 ~ Services ~ adressToEmoji');
try {
const container = document.getElementById('containerId');
const container = getCorrectDOM('login-4nk-component') as HTMLElement;
const emojis = await addressToEmoji(text);
const emojiDisplay = container?.querySelector('.emoji-display');
@ -99,9 +100,10 @@ export async function displayEmojis(text: string) {
// Verify Other address
export function initAddressInput() {
const addressInput = document.getElementById('addressInput') as HTMLInputElement;
const emojiDisplay = document.getElementById('emoji-display-2');
const okButton = document.getElementById('okButton');
const container = getCorrectDOM('login-4nk-component') as HTMLElement
const addressInput = container.querySelector('#addressInput') as HTMLInputElement;
const emojiDisplay = container.querySelector('#emoji-display-2');
const okButton = container.querySelector('#okButton') as HTMLButtonElement;
addSubscription(addressInput, 'input', async () => {
let address = addressInput.value;
@ -146,40 +148,43 @@ export function initAddressInput() {
}
async function onOkButtonClick() {
const service = await Services.getInstance();
const addressInput = (document.getElementById('addressInput') as HTMLInputElement).value;
const container = getCorrectDOM('login-4nk-component') as HTMLElement
const secondDeviceAddress = (container.querySelector('#addressInput') as HTMLInputElement).value;
try {
// Connect to target, if necessary
const sharedSecret = await service.getSecretForAddress(addressInput);
if (!sharedSecret) {
const member = {
sp_addresses: [addressInput],
}
const connectMemberResult = await service.connectMember([member]);
await service.handleApiReturn(connectMemberResult);
}
// Create the process
await prepareAndSendPairingTx(secondDeviceAddress);
} catch (e) {
console.error(`onOkButtonClick error: ${e}`);
}
}
export async function prepareAndSendPairingTx(secondDeviceAddress: string) {
const service = await Services.getInstance();
const sharedSecret = await service.getSecretForAddress(secondDeviceAddress);
if (!sharedSecret) {
const member = {
sp_addresses: [secondDeviceAddress],
};
const connectMemberResult = await service.connectMember([member]);
await service.handleApiReturn(connectMemberResult);
}
// Create the process
setTimeout(async () => {
const relayAddress = await service.getRelayAddresses(); // Get one (or more?) relay addresses
const createPairingProcessReturn = await service.createPairingProcess([addressInput], relayAddress[0], 1);
await service.handleApiReturn(createPairingProcessReturn);
const createPairingProcessReturn = await service.createPairingProcess([secondDeviceAddress], relayAddress[0], 1);
if (!createPairingProcessReturn.updated_process) {
throw new Error('createPairingProcess returned an empty new process'); // This should never happen
}
const [commitmentOutpoint, process] = createPairingProcessReturn.updated_process;
// We set the service to the process
service.getUpdateProposals(commitmentOutpoint);
await service.evaluatePendingUpdates();
} catch (e) {
console.error('onOkButtonClick error:', e);
}
await service.handleApiReturn(createPairingProcessReturn);
}, 1000);
}
export async function generateQRCode(spAddress: string) {
try {
const container = document.getElementById('containerId');
const container = getCorrectDOM('login-4nk-component') as HTMLElement
const currentUrl = 'https://' + window.location.host;
const url = await QRCode.toDataURL(currentUrl + '?sp_address=' + spAddress);
const qrCode = container?.querySelector('.qr-code img');
@ -190,7 +195,7 @@ export async function generateQRCode(spAddress: string) {
if (address) {
address.textContent = 'Copy address';
}
const copyBtn = document.getElementById('copyBtn');
const copyBtn = container.querySelector('#copyBtn');
if (copyBtn) {
addSubscription(copyBtn, 'click', () => copyToClipboard(currentUrl + '?sp_address=' + spAddress));
}

View File

@ -1,4 +1,4 @@
import { AnkFlag } from 'dist/pkg/sdk_client';
import { AnkFlag } from 'pkg/sdk_client';
import Services from './services/service';
let ws: WebSocket;

View File

@ -1,26 +1,28 @@
{
"compilerOptions": {
"declaration": true,
"outDir": "./dist",
"target": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ESNext", "webworker"],
"types": ["vite/client", "node"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"baseUrl": "./",
"paths": {
"~/": ["src/"]
}
"declaration": true,
"outDir": "./dist",
"target": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ESNext", "webworker"],
"types": ["vite/client", "node"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"experimentalDecorators": true,
"useDefineForClassFields": true,
"noEmit": true,
"jsx": "react-jsx",
"baseUrl": "./",
"paths": {
"~/*": ["src/*"]
}
},
"include": ["src", "src/*/", "./vite.config.ts", "src/*.d.ts", "src/main.ts"],
"exclude": ["node_modules"]

View File

@ -2,8 +2,10 @@ import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue'; // or react from '@vitejs/plugin-react' if using React
import wasm from 'vite-plugin-wasm';
import {createHtmlPlugin} from 'vite-plugin-html';
import typescript from "@rollup/plugin-typescript";
import fs from 'fs'
import path from 'path'
// import pluginTerminal from 'vite-plugin-terminal';
export default defineConfig({
optimizeDeps: {
@ -16,23 +18,33 @@ export default defineConfig({
minify: true,
template: 'index.html',
}),
typescript({
sourceMap: false,
declaration: true,
declarationDir: "dist/types",
rootDir: "src",
outDir: "dist",
}),
// pluginTerminal({
// console: 'terminal',
// output: ['terminal', 'console']
// })
],
build: {
outDir: 'dist',
target: 'esnext',
minify: false,
rollupOptions: {
input: './src/main.ts',
external: ['ihm_client'],
output: {
entryFileNames: 'index.js',
}
input: './src/router.ts',
output: {
entryFileNames: 'index.js',
},
},
lib: {
entry: path.resolve(__dirname, 'src/main.ts'),
name: 'signature',
entry: path.resolve(__dirname, 'src/router.ts'),
name: 'ihm-service',
formats: ['es'],
fileName: (format) => `signature.${format}.js`,
fileName: (format) => `ihm-service.${format}.js`,
},
},
resolve: {
@ -42,9 +54,9 @@ export default defineConfig({
extensions: ['.ts', '.tsx', '.js'],
},
server: {
host: 'localhost',
open: false,
fs: {
cachedChecks: false
},
port: 3001,
strictPort: true // Empêche de changer de port si le 3001 est occupé
}
},
});