diff --git a/angular.json b/angular.json index 9746bdb..616a8d7 100644 --- a/angular.json +++ b/angular.json @@ -53,7 +53,8 @@ "node_modules/datatables.net-buttons/js/buttons.html5.js", "node_modules/datatables.net-buttons/js/buttons.print.min.js", "node_modules/datatables.net-select/js/dataTables.select.min.js", - "node_modules/datatables.net-fixedheader/js/dataTables.fixedHeader.js" + "node_modules/datatables.net-fixedheader/js/dataTables.fixedHeader.js", + "node_modules/mermaid/dist/mermaid.min.js" ], "allowedCommonJsDependencies": [ "jsvectormap/dist/maps/world-merc.js", diff --git a/package-lock.json b/package-lock.json index 38b45b5..458daa3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,6 +53,7 @@ "keycloak-js": "^26.2.1", "leaflet": "^1.9.4", "lodash-es": "^4.17.21", + "mermaid": "^11.12.2", "ng-otp-input": "^2.0.9", "ng2-charts": "^8.0.0", "ngx-countup": "^13.2.0", @@ -1246,6 +1247,19 @@ "rxjs": "^6.5.3 || ^7.4.0" } }, + "node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "license": "MIT", + "dependencies": { + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -1534,6 +1548,51 @@ "leaflet": "1" } }, + "node_modules/@braintree/sanitize-url": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.1.tgz", + "integrity": "sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw==", + "license": "MIT" + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", + "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/gast": "11.0.3", + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/gast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", + "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", + "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/types": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", + "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "license": "Apache-2.0" + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -2022,6 +2081,23 @@ "@fullcalendar/core": "~6.1.19" } }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" + }, + "node_modules/@iconify/utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.0.tgz", + "integrity": "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==", + "license": "MIT", + "dependencies": { + "@antfu/install-pkg": "^1.1.0", + "@iconify/types": "^2.0.0", + "mlly": "^1.8.0" + } + }, "node_modules/@inquirer/ansi": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.1.tgz", @@ -2635,6 +2711,15 @@ "win32" ] }, + "node_modules/@mermaid-js/parser": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.3.tgz", + "integrity": "sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==", + "license": "MIT", + "dependencies": { + "langium": "3.3.1" + } + }, "node_modules/@modelcontextprotocol/sdk": { "version": "1.17.3", "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.17.3.tgz", @@ -4301,6 +4386,259 @@ "@types/node": "*" } }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", + "license": "MIT" + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", + "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", + "license": "MIT" + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "license": "MIT", + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", + "license": "MIT" + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", + "license": "MIT" + }, + "node_modules/@types/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", + "license": "MIT" + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", + "license": "MIT" + }, + "node_modules/@types/d3-random": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", + "license": "MIT" + }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", + "license": "MIT" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "license": "MIT", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -4312,7 +4650,6 @@ "version": "7946.0.16", "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", - "dev": true, "license": "MIT" }, "node_modules/@types/jasmine": { @@ -4376,6 +4713,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, "node_modules/@types/validator": { "version": "13.15.4", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.4.tgz", @@ -4426,6 +4770,18 @@ "node": ">= 0.6" } }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", @@ -4988,6 +5344,32 @@ "pnpm": ">=8" } }, + "node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/cst-dts-gen": "11.0.3", + "@chevrotain/gast": "11.0.3", + "@chevrotain/regexp-to-ast": "11.0.3", + "@chevrotain/types": "11.0.3", + "@chevrotain/utils": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/chevrotain-allstar": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz", + "integrity": "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==", + "license": "MIT", + "dependencies": { + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^11.0.0" + } + }, "node_modules/choices.js": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/choices.js/-/choices.js-11.1.0.tgz", @@ -5148,6 +5530,15 @@ "dev": true, "license": "MIT" }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5155,6 +5546,12 @@ "dev": true, "license": "MIT" }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "license": "MIT" + }, "node_modules/connect": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", @@ -5310,6 +5707,15 @@ "node": ">= 0.10" } }, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "license": "MIT", + "dependencies": { + "layout-base": "^1.0.0" + } + }, "node_modules/countup.js": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/countup.js/-/countup.js-2.9.0.tgz", @@ -5368,6 +5774,517 @@ "dev": true, "license": "MIT" }, + "node_modules/cytoscape": { + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz", + "integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "license": "MIT", + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "license": "MIT" + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "license": "ISC", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "license": "ISC", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "license": "ISC", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "license": "ISC", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "license": "ISC", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "license": "ISC", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dagre-d3-es": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.13.tgz", + "integrity": "sha512-efEhnxpSuwpYOKRm/L5KbqoZmNNukHa/Flty4Wp62JRvgH2ojwVgPgdYyr4twpieZnyRDdIH7PY2mopX26+j2Q==", + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "lodash-es": "^4.17.21" + } + }, "node_modules/datatables": { "version": "1.10.18", "resolved": "https://registry.npmjs.org/datatables/-/datatables-1.10.18.tgz", @@ -5511,6 +6428,12 @@ "node": ">=4.0" } }, + "node_modules/dayjs": { + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -5528,6 +6451,15 @@ } } }, + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "license": "ISC", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -5624,6 +6556,15 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", + "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/domutils": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", @@ -6435,6 +7376,12 @@ "dev": true, "license": "ISC" }, + "node_modules/hachure-fill": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", + "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==", + "license": "MIT" + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -6724,6 +7671,15 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/ip-address": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", @@ -7575,6 +8531,31 @@ "node": ">=10" } }, + "node_modules/katex": { + "version": "0.16.27", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.27.tgz", + "integrity": "sha512-aeQoDkuRWSqQN6nSvVCEFvfXdqo1OQiCmmW1kc9xSdjutPv7BGO7pqY9sQRJpMOGrEdfDgF2TfRXe5eUAD2Waw==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/keycloak-angular": { "version": "20.0.0", "resolved": "https://registry.npmjs.org/keycloak-angular/-/keycloak-angular-20.0.0.tgz", @@ -7600,6 +8581,33 @@ "test" ] }, + "node_modules/khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" + }, + "node_modules/langium": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz", + "integrity": "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==", + "license": "MIT", + "dependencies": { + "chevrotain": "~11.0.3", + "chevrotain-allstar": "~0.3.0", + "vscode-languageserver": "~9.0.1", + "vscode-languageserver-textdocument": "~1.0.11", + "vscode-uri": "~3.0.8" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "license": "MIT" + }, "node_modules/leaflet": { "version": "1.9.4", "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", @@ -7893,6 +8901,18 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/marked": { + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", + "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -7926,6 +8946,34 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mermaid": { + "version": "11.12.2", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.12.2.tgz", + "integrity": "sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w==", + "license": "MIT", + "dependencies": { + "@braintree/sanitize-url": "^7.1.1", + "@iconify/utils": "^3.0.1", + "@mermaid-js/parser": "^0.6.3", + "@types/d3": "^7.4.3", + "cytoscape": "^3.29.3", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.13", + "dayjs": "^1.11.18", + "dompurify": "^3.2.5", + "katex": "^0.16.22", + "khroma": "^2.1.0", + "lodash-es": "^4.17.21", + "marked": "^16.2.1", + "roughjs": "^4.6.6", + "stylis": "^4.3.6", + "ts-dedent": "^2.2.0", + "uuid": "^11.1.0" + } + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -8193,6 +9241,18 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/mlly": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.1" + } + }, "node_modules/mrmime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", @@ -8817,6 +9877,12 @@ "dev": true, "license": "BlueOak-1.0.0" }, + "node_modules/package-manager-detector": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", + "license": "MIT" + }, "node_modules/pacote": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.0.0.tgz", @@ -8974,6 +10040,12 @@ "node": ">= 0.8" } }, + "node_modules/path-data-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", + "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", + "license": "MIT" + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -9036,6 +10108,12 @@ "url": "https://opencollective.com/express" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -9077,6 +10155,33 @@ "node": ">=16.20.0" } }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/points-on-curve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", + "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==", + "license": "MIT" + }, + "node_modules/points-on-path": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz", + "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", + "license": "MIT", + "dependencies": { + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" + } + }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -9417,6 +10522,12 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", + "license": "Unlicense" + }, "node_modules/rollup": { "version": "4.52.3", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.3.tgz", @@ -9459,6 +10570,18 @@ "fsevents": "~2.3.2" } }, + "node_modules/roughjs": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", + "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", + "license": "MIT", + "dependencies": { + "hachure-fill": "^0.5.2", + "path-data-parser": "^0.1.0", + "points-on-curve": "^0.2.0", + "points-on-path": "^0.2.1" + } + }, "node_modules/router": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", @@ -9476,6 +10599,12 @@ "node": ">= 18" } }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "license": "BSD-3-Clause" + }, "node_modules/rxjs": { "version": "7.8.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", @@ -9528,7 +10657,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, "license": "MIT" }, "node_modules/sass": { @@ -10229,6 +11357,12 @@ "node": ">=8" } }, + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "license": "MIT" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -10356,6 +11490,15 @@ "dev": true, "license": "ISC" }, + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tinyglobby": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", @@ -10405,6 +11548,15 @@ "node": ">=0.6" } }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "license": "MIT", + "engines": { + "node": ">=6.10" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -10482,6 +11634,12 @@ "node": "*" } }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "license": "MIT" + }, "node_modules/undici-types": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", @@ -10601,6 +11759,19 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -10743,6 +11914,55 @@ "node": ">=0.10.0" } }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "license": "MIT", + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "license": "MIT" + }, "node_modules/watchpack": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", diff --git a/package.json b/package.json index e2aad41..948bf66 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "keycloak-js": "^26.2.1", "leaflet": "^1.9.4", "lodash-es": "^4.17.21", + "mermaid": "^11.12.2", "ng-otp-input": "^2.0.9", "ng2-charts": "^8.0.0", "ngx-countup": "^13.2.0", diff --git a/src/app/modules/documentation/documentation.html b/src/app/modules/documentation/documentation.html index 3fd0888..91dce45 100644 --- a/src/app/modules/documentation/documentation.html +++ b/src/app/modules/documentation/documentation.html @@ -1 +1,785 @@ -

Documentation

\ No newline at end of file +
+ +
+
+
+
+ +
+ +
+
+ + DCB Hub v1.0 +
+

Documentation d'Intégration

+

+ Guide complet pour intégrer le DCB Hub - Plateforme d'agrégation de paiements Direct Carrier Billing +

+
+ + + + + +
+ + @if (activeSection() === 'overview') { +
+ +
+ @for (feature of features; track feature.title) { +
+
+ +
+

{{ feature.title }}

+

{{ feature.desc }}

+
+ } +
+ + +
+

+ + Configuration Requise +

+
+
+

Headers Obligatoires

+
+
+ HTTP Headers + http +
+
X-Merchant-ID: votre-merchant-id
+X-API-Key: votre-api-key
+X-COUNTRY: CI (Côte d'Ivoire), SN (Sénégal), etc.
+X-OPERATOR: ORANGE, MTN, AIRTEL
+
+
+
+

Environnements

+
+
+
+
+

Sandbox

+

https://sandbox.dcb-hub.pixpay.sn/api/v1

+
+
+
+
+
+

Production

+

https://api.dcb-hub.pixpay.sn/api/v1

+
+
+
+
+
+
+
+ } + + + @if (activeSection() === 'flow') { +
+
+

+ + Flux Principal d'Intégration +

+

+ Ce diagramme illustre le flux complet depuis l'authentification OTP jusqu'à l'activation du service. +

+
+ +
+
{{ mermaidDiagram }}
+
+ +
+
+ Phase 1-2 +

Authentification

+

OTP Challenge & Validation

+
+
+ Phase 3-4 +

Souscription

+

Création abonnement & Webhook

+
+
+ Phase 5-6 +

Facturation

+

Charge & SMS confirmation

+
+
+
+ } + + + @if (activeSection() === 'steps') { +
+ @for (step of steps; track step.id) { +
+ + + @if (step.isOpen) { +
+ @if (step.endpoint) { +
+ + {{ step.endpoint.method }} + + {{ step.endpoint.path }} +
+ } + + @if (step.headers) { +
+
+ Headers requis + +
+
{{ step.headers }}
+
+ } + + @if (step.requestBody) { +
+
+ Request Body +
+ json + +
+
+
{{ step.requestBody }}
+
+ } + + @if (step.responseBody) { +
+
+ Response +
+ json + +
+
+
{{ step.responseBody }}
+
+ } + + @if (step.note) { +
+

{{ step.note.text }}

+
+ } +
+ } +
+ } +
+ } + + + @if (activeSection() === 'api') { +
+ +
+ @for (tab of apiTabs; track tab.id) { + + } +
+ + + @if (activeApiTab() === 'otp') { +
+
+

+ + OTP Challenge Endpoints +

+ +
+
+
+ POST + /api/v1/otp-challenge/initiate +
+

Initie un challenge OTP pour authentifier l'utilisateur

+
+
+

Paramètres

+ + + + + + +
msisdnstring, required
channelSMS | USSD | IVR
serviceIdstring
+
+
+

Headers

+ + + + + +
X-Merchant-IDrequired
X-API-Keyrequired
+
+
+
+ +
+
+ POST + /api/v1/otp-challenge/{challengeId}/verify +
+

Vérifie le code OTP entré par l'utilisateur

+
+
+

Path Parameters

+ + + + +
challengeIdstring, required
+
+
+

Responses

+
+
+ 200 + Code validé +
+
+ 400 + Code invalide +
+
+ 404 + Challenge non trouvé +
+
+
+
+
+
+
+
+ } + + + @if (activeApiTab() === 'subscriptions') { +
+
+

+ + Subscriptions Endpoints +

+ +
+
+
+ POST + /api/v1/subscriptions +
+

Créer une nouvelle souscription

+
+ +
+
+ GET + /api/v1/subscriptions +
+

Liste des souscriptions avec pagination et filtres

+
+ page + limit + status + periodicity + serviceId + merchantPartnerId +
+
+ +
+
+ GET + /api/v1/subscriptions/{id} +
+

Détails d'une souscription

+
+ +
+
+ DELETE + /api/v1/subscriptions/{id} +
+

Annuler une souscription

+
+
+ +
+

Statuts possibles

+
+ @for (status of subscriptionStatuses; track status) { + {{ status }} + } +
+
+
+
+ } + + + @if (activeApiTab() === 'payments') { +
+
+

+ + Payments Endpoints +

+ +
+
+
+ POST + /api/v1/payments/charge +
+

Créer une nouvelle charge

+ +
+
+ ChargeDto Schema + typescript +
+
interface ChargeDto {
+  userToken: string;      // ISE2 token from OTP validation
+  amount: number;         // Amount to charge
+  currency: string;       // XOF, XAF, USD, EUR
+  description: string;    // Payment description
+  reference?: string;     // Unique payment reference
+  subscriptionId?: number;
+  callbackUrl?: string;
+  metadata?: Record<string, any>;
+}
+
+
+ +
+
+ GET + /api/v1/payments +
+

Liste des paiements avec filtres avancés

+
+
+

Pagination

+
    +
  • page (default: 1)
  • +
  • limit (max: 100)
  • +
  • sortBy, sortOrder
  • +
+
+
+

Filtres

+
    +
  • type: MM, BANK, CHEQUE
  • +
  • status: SUCCESS, FAILED, PENDING
  • +
  • currency, amountMin, amountMax
  • +
+
+
+

Dates

+
    +
  • createdFrom, createdTo
  • +
  • completedFrom, completedTo
  • +
+
+
+
+ +
+
+ GET + /api/v1/payments/{paymentId} +
+

Détails d'un paiement par ID

+
+ +
+
+ POST + /api/v1/payments/{paymentId}/refund +
+

Rembourser un paiement (total ou partiel)

+
+ +
+
+ POST + /api/v1/payments/{paymentId}/retry +
+

Réessayer un paiement échoué

+
+
+
+
+ } + + + @if (activeApiTab() === 'operators') { +
+
+

+ + Operators Endpoints +

+ +
+
+
+ GET + /api/v1/operators +
+

Liste des opérateurs disponibles

+
+ operatorCode + period + startDate + endDate + active + country +
+
+ +
+
+ GET + /api/v1/operators/{operatorCode}/health +
+

Métriques de santé d'un opérateur

+
+ +
+
+ GET + /api/v1/operators/detect/{msisdn} +
+

Détection automatique de l'opérateur à partir du MSISDN

+
+
+ +
+
+ OperatorResponseDto + typescript +
+
interface OperatorResponseDto {
+  id: string;
+  code: string;       // ORANGE, MTN, AIRTEL, etc.
+  name: string;       // Nom complet
+  country: string;    // CI, SN, CM, CD, etc.
+  active: boolean;
+  features: {
+    otp: boolean;
+    subscription: boolean;
+    oneTimePayment: boolean;
+    refund: boolean;
+  };
+}
+
+
+
+ } + + + @if (activeApiTab() === 'swagger') { +
+ +
+
+

+ + {{ swaggerInfo.title }} +

+

{{ swaggerInfo.description }}

+ Version {{ swaggerInfo.version }} +
+ +
+ +
+ +
+ @for (tag of getFilteredSwaggerTags(); track tag.name) { +
+ + @if (tag.isOpen) { +
+ @for (endpoint of tag.endpoints; track endpoint.operationId) { + + } +
+ } +
+ } +
+ + +
+ @if (selectedSwaggerEndpoint(); as endpoint) { +
+
+
+ + {{ endpoint.method }} + + {{ endpoint.path }} +
+ +
+ +

{{ endpoint.summary }}

+ @if (endpoint.description) { +

{{ endpoint.description }}

+ } + + + @if (endpoint.parameters && endpoint.parameters.length > 0) { +
+
Paramètres
+ + @if (getParametersByLocation(endpoint.parameters, 'path').length > 0) { +
+
Path Parameters
+
+ @for (param of getParametersByLocation(endpoint.parameters, 'path'); track param.name) { +
+
+ {{ param.name }} + @if (param.required) { + required + } +
+
{{ param.schema?.type || 'string' }}
+ @if (param.description) { +
{{ param.description }}
+ } +
+ } +
+
+ } + + @if (getParametersByLocation(endpoint.parameters, 'query').length > 0) { +
+
Query Parameters
+
+ @for (param of getParametersByLocation(endpoint.parameters, 'query'); track param.name) { +
+
+ {{ param.name }} + @if (param.required) { + required + } +
+
+ {{ param.schema?.type || 'string' }} + @if (param.schema?.enum) { + enum: {{ param.schema.enum.join(', ') }} + } +
+ @if (param.description) { +
{{ param.description }}
+ } +
+ } +
+
+ } + + @if (getParametersByLocation(endpoint.parameters, 'header').length > 0) { +
+
Header Parameters
+
+ @for (param of getParametersByLocation(endpoint.parameters, 'header'); track param.name) { +
+
+ {{ param.name }} + @if (param.required) { + required + } +
+
{{ param.schema?.type || 'string' }}
+ @if (param.description) { +
{{ param.description }}
+ } +
+ } +
+
+ } +
+ } + + + @if (endpoint.requestBody) { +
+
Request Body
+
+
+ application/json + json +
+
{{ formatJson(endpoint.requestBody) }}
+
+
+ } + + + @if (endpoint.responses) { +
+
Responses
+
+ @for (response of endpoint.responses | keyvalue; track response.key) { +
+ {{ response.key }} + {{ $any(response.value).description }} + + +
+ } +
+
+ } + + + @if (endpoint.security && endpoint.security.length > 0) { +
+
+ + Authentification requise +
+
+ + Bearer Token (JWT) +
+
+ } +
+ } @else { +
+ +

Sélectionnez un endpoint pour voir les détails

+
+ } +
+
+
+ } +
+ } +
+ + + +
+
diff --git a/src/app/modules/documentation/documentation.scss b/src/app/modules/documentation/documentation.scss new file mode 100644 index 0000000..adf76af --- /dev/null +++ b/src/app/modules/documentation/documentation.scss @@ -0,0 +1,1504 @@ +// Variables - Light Theme +$bg-primary: #ffffff; +$bg-secondary: #f8fafc; +$bg-card: #ffffff; +$bg-hover: #f1f5f9; +$border-color: #e2e8f0; +$text-primary: #1e293b; +$text-secondary: #475569; +$text-muted: #94a3b8; + +$indigo: #6366f1; +$green: #22c55e; +$blue: #3b82f6; +$purple: #a855f7; +$orange: #f97316; +$pink: #ec4899; +$amber: #f59e0b; +$red: #ef4444; + +// Animations +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.animate-fadeIn { + animation: fadeIn 0.3s ease-out; +} + +// Container +.documentation-container { + min-height: 100vh; + background: linear-gradient(135deg, $bg-secondary 0%, $bg-primary 50%, $bg-secondary 100%); + color: $text-primary; + position: relative; + overflow: hidden; +} + +// Background Effects +.bg-effects { + position: fixed; + inset: 0; + overflow: hidden; + pointer-events: none; + z-index: 0; +} + +.bg-blob { + position: absolute; + border-radius: 50%; + filter: blur(100px); + opacity: 0.5; + + &.bg-blob-1 { + top: -10%; + left: 20%; + width: 30rem; + height: 30rem; + background: rgba($indigo, 0.08); + } + + &.bg-blob-2 { + bottom: -10%; + right: 20%; + width: 30rem; + height: 30rem; + background: rgba($purple, 0.08); + } +} + +.content-wrapper { + position: relative; + z-index: 10; + max-width: 80rem; + margin: 0 auto; + padding: 2rem 1.5rem; +} + +// Header +.doc-header { + text-align: center; + margin-bottom: 3rem; +} + +.version-badge { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.5rem 1rem; + border-radius: 9999px; + background: rgba($indigo, 0.1); + border: 1px solid rgba($indigo, 0.2); + margin-bottom: 1.5rem; + + ng-icon { + color: $indigo; + } + + span { + font-size: 0.875rem; + font-weight: 500; + color: $indigo; + } +} + +.doc-title { + font-size: 2.5rem; + font-weight: 700; + margin-bottom: 1rem; + background: linear-gradient(135deg, $text-primary, $indigo); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + + @media (min-width: 768px) { + font-size: 3rem; + } +} + +.doc-subtitle { + font-size: 1.125rem; + color: $text-secondary; + max-width: 42rem; + margin: 0 auto; +} + +// Navigation +.doc-nav { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 0.5rem; + margin-bottom: 3rem; +} + +.nav-btn { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.75rem 1.25rem; + border-radius: 0.75rem; + font-size: 0.875rem; + font-weight: 500; + border: 1px solid $border-color; + background: $bg-card; + color: $text-secondary; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); + + &:hover { + color: $text-primary; + background: $bg-hover; + border-color: darken($border-color, 5%); + } + + &.active { + background: linear-gradient(135deg, $indigo, $purple); + color: white; + border-color: transparent; + box-shadow: 0 4px 15px rgba($indigo, 0.3); + } +} + +// Sections Container +.sections-container { + margin-bottom: 2rem; +} + +// Feature Grid +.feature-grid { + display: grid; + grid-template-columns: repeat(1, 1fr); + gap: 1rem; + margin-bottom: 2rem; + + @media (min-width: 768px) { + grid-template-columns: repeat(2, 1fr); + } + + @media (min-width: 1024px) { + grid-template-columns: repeat(4, 1fr); + } +} + +.feature-card { + padding: 1.5rem; + border-radius: 1rem; + background: $bg-card; + border: 1px solid $border-color; + transition: all 0.3s ease; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); + + &:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.08); + + .feature-icon { + transform: scale(1.1); + } + } + + &.feature-indigo:hover { + border-color: rgba($indigo, 0.3); + } + + &.feature-green:hover { + border-color: rgba($green, 0.3); + } + + &.feature-blue:hover { + border-color: rgba($blue, 0.3); + } + + &.feature-purple:hover { + border-color: rgba($purple, 0.3); + } +} + +.feature-icon { + width: 3rem; + height: 3rem; + border-radius: 0.75rem; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 1rem; + transition: transform 0.3s ease; + + &.icon-indigo { + background: rgba($indigo, 0.1); + color: $indigo; + } + + &.icon-green { + background: rgba($green, 0.1); + color: $green; + } + + &.icon-blue { + background: rgba($blue, 0.1); + color: $blue; + } + + &.icon-purple { + background: rgba($purple, 0.1); + color: $purple; + } +} + +.feature-title { + font-size: 1.125rem; + font-weight: 600; + color: $text-primary; + margin-bottom: 0.5rem; +} + +.feature-desc { + font-size: 0.875rem; + color: $text-secondary; + margin: 0; +} + +// Config Section +.config-section { + padding: 2rem; + border-radius: 1rem; + background: $bg-card; + border: 1px solid $border-color; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); +} + +.config-title { + display: flex; + align-items: center; + gap: 0.75rem; + font-size: 1.5rem; + font-weight: 700; + margin-bottom: 1.5rem; + color: $text-primary; + + ng-icon { + color: $indigo; + } +} + +.config-grid { + display: grid; + grid-template-columns: 1fr; + gap: 1.5rem; + + @media (min-width: 768px) { + grid-template-columns: repeat(2, 1fr); + } +} + +.config-block-title { + font-size: 1.125rem; + font-weight: 600; + color: $text-primary; + margin-bottom: 0.75rem; +} + +// Code Block +.code-block { + border-radius: 0.75rem; + overflow: hidden; + border: 1px solid $border-color; + background: #1e293b; +} + +.code-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.5rem 1rem; + background: #334155; + border-bottom: 1px solid #475569; +} + +.code-label { + font-size: 0.75rem; + font-family: 'JetBrains Mono', monospace; + color: #94a3b8; +} + +.code-lang { + font-size: 0.75rem; + padding: 0.125rem 0.5rem; + border-radius: 0.25rem; + background: rgba($indigo, 0.3); + color: #a5b4fc; + font-family: 'JetBrains Mono', monospace; +} + +.code-actions { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.copy-btn { + padding: 0.375rem; + border-radius: 0.5rem; + background: transparent; + border: none; + color: #94a3b8; + cursor: pointer; + transition: all 0.2s ease; + + &:hover { + background: rgba(255, 255, 255, 0.1); + color: white; + } +} + +.code-content { + padding: 1rem; + margin: 0; + overflow-x: auto; + font-size: 0.875rem; + background: #1e293b; + + code { + font-family: 'JetBrains Mono', monospace; + color: #e2e8f0; + } +} + +// Environment List +.env-list { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.env-item { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem; + border-radius: 0.75rem; + background: $bg-secondary; + border: 1px solid $border-color; +} + +.env-indicator { + width: 0.75rem; + height: 0.75rem; + border-radius: 50%; + + &.env-sandbox { + background: $amber; + animation: pulse 2s infinite; + } + + &.env-prod { + background: $green; + } +} + +@keyframes pulse { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } +} + +.env-info { + flex: 1; +} + +.env-name { + font-size: 0.875rem; + font-weight: 500; + color: $text-primary; + margin: 0; +} + +.env-url { + font-size: 0.75rem; + font-family: 'JetBrains Mono', monospace; + color: $text-secondary; + margin: 0; +} + +// Flow Section +.flow-header { + padding: 1.5rem; + border-radius: 1rem; + background: linear-gradient(135deg, rgba($indigo, 0.05), rgba($purple, 0.05)); + border: 1px solid rgba($indigo, 0.15); + margin-bottom: 1.5rem; +} + +.flow-title { + display: flex; + align-items: center; + gap: 0.75rem; + font-size: 1.25rem; + font-weight: 700; + margin-bottom: 0.5rem; + color: $text-primary; + + ng-icon { + color: $indigo; + } +} + +.flow-desc { + color: $text-secondary; + margin: 0; +} + +// Mermaid Container +.mermaid-container { + padding: 1.5rem; + border-radius: 1rem; + background: $bg-card; + border: 1px solid $border-color; + overflow-x: auto; + margin-bottom: 2rem; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); + + .mermaid { + background: transparent !important; + + svg { + max-width: 100%; + height: auto; + } + } +} + +// Phases Grid +.phases-grid { + display: grid; + grid-template-columns: 1fr; + gap: 1rem; + + @media (min-width: 768px) { + grid-template-columns: repeat(3, 1fr); + } +} + +.phase-card { + padding: 1.25rem; + border-radius: 0.75rem; + background: $bg-card; + border: 1px solid $border-color; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); +} + +.phase-badge { + display: inline-block; + padding: 0.25rem 0.5rem; + border-radius: 0.25rem; + font-size: 0.75rem; + font-weight: 700; + color: white; + margin-bottom: 0.75rem; + + &.phase-indigo { + background: $indigo; + } + + &.phase-blue { + background: $blue; + } + + &.phase-orange { + background: $orange; + } +} + +.phase-title { + font-size: 1.125rem; + font-weight: 600; + color: $text-primary; + margin-bottom: 0.25rem; +} + +.phase-desc { + font-size: 0.875rem; + color: $text-secondary; + margin: 0; +} + +// Steps Section +.steps-section { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.step-card { + border-radius: 1rem; + overflow: hidden; +} + +.step-header { + width: 100%; + display: flex; + align-items: flex-start; + gap: 1rem; + padding: 1.25rem; + background: $bg-card; + border: 1px solid $border-color; + border-radius: 1rem; + cursor: pointer; + transition: all 0.3s ease; + text-align: left; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); + + &:hover { + background: $bg-hover; + border-color: darken($border-color, 5%); + } +} + +.step-icon { + flex-shrink: 0; + width: 3rem; + height: 3rem; + border-radius: 0.75rem; + display: flex; + align-items: center; + justify-content: center; + color: white; + + &.step-indigo { + background: linear-gradient(135deg, $indigo, darken($indigo, 10%)); + box-shadow: 0 4px 15px rgba($indigo, 0.3); + } + + &.step-green { + background: linear-gradient(135deg, $green, darken($green, 10%)); + box-shadow: 0 4px 15px rgba($green, 0.3); + } + + &.step-blue { + background: linear-gradient(135deg, $blue, darken($blue, 10%)); + box-shadow: 0 4px 15px rgba($blue, 0.3); + } + + &.step-purple { + background: linear-gradient(135deg, $purple, darken($purple, 10%)); + box-shadow: 0 4px 15px rgba($purple, 0.3); + } + + &.step-orange { + background: linear-gradient(135deg, $orange, darken($orange, 10%)); + box-shadow: 0 4px 15px rgba($orange, 0.3); + } + + &.step-pink { + background: linear-gradient(135deg, $pink, darken($pink, 10%)); + box-shadow: 0 4px 15px rgba($pink, 0.3); + } +} + +.step-info { + flex: 1; +} + +.step-label { + font-size: 0.75rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.05em; + color: $text-muted; +} + +.step-title { + font-size: 1.125rem; + font-weight: 600; + color: $text-primary; + margin: 0.25rem 0; +} + +.step-desc { + font-size: 0.875rem; + color: $text-secondary; + margin: 0; +} + +.step-chevron { + flex-shrink: 0; + margin-top: 0.5rem; + color: $text-muted; + transition: transform 0.3s ease; + + &.open { + transform: rotate(90deg); + } +} + +.step-content { + margin-left: 4rem; + padding: 1rem 0 1rem 1rem; + border-left: 2px solid $border-color; + display: flex; + flex-direction: column; + gap: 1rem; +} + +// Endpoint Badge +.endpoint-badge { + display: flex; + align-items: center; + gap: 0.5rem; + font-family: 'JetBrains Mono', monospace; + font-size: 0.875rem; + + &.large { + font-size: 1rem; + + .method { + padding: 0.375rem 0.75rem; + } + } +} + +.method { + padding: 0.25rem 0.5rem; + border-radius: 0.5rem; + font-weight: 700; + border: 1px solid; + + &.method-get { + background: rgba($green, 0.1); + color: darken($green, 10%); + border-color: rgba($green, 0.3); + } + + &.method-post { + background: rgba($blue, 0.1); + color: darken($blue, 10%); + border-color: rgba($blue, 0.3); + } + + &.method-put { + background: rgba($amber, 0.1); + color: darken($amber, 10%); + border-color: rgba($amber, 0.3); + } + + &.method-delete { + background: rgba($red, 0.1); + color: darken($red, 10%); + border-color: rgba($red, 0.3); + } + + &.method-patch { + background: rgba($purple, 0.1); + color: darken($purple, 10%); + border-color: rgba($purple, 0.3); + } +} + +.path { + color: $text-secondary; +} + +// Note Box +.note-box { + padding: 1rem; + border-radius: 0.75rem; + + p { + font-size: 0.875rem; + margin: 0; + } + + &.note-warning { + background: rgba($amber, 0.1); + border: 1px solid rgba($amber, 0.2); + + p { + color: darken($amber, 15%); + } + } + + &.note-success { + background: rgba($green, 0.1); + border: 1px solid rgba($green, 0.2); + + p { + color: darken($green, 15%); + } + } + + &.note-info { + background: rgba($blue, 0.1); + border: 1px solid rgba($blue, 0.2); + + p { + color: darken($blue, 15%); + } + } + + &.note-purple { + background: rgba($purple, 0.1); + border: 1px solid rgba($purple, 0.2); + + p { + color: darken($purple, 15%); + } + } +} + +// API Section +.api-tabs { + display: flex; + gap: 0.25rem; + padding: 0.25rem; + background: $bg-secondary; + border-radius: 0.75rem; + border: 1px solid $border-color; + margin-bottom: 1.5rem; + overflow-x: auto; +} + +.api-tab { + flex: 1; + min-width: max-content; + display: flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + padding: 0.625rem 1rem; + border-radius: 0.5rem; + font-size: 0.875rem; + font-weight: 500; + background: transparent; + border: none; + color: $text-secondary; + cursor: pointer; + transition: all 0.2s ease; + + &:hover { + color: $text-primary; + background: $bg-hover; + } + + &.active { + background: $indigo; + color: white; + box-shadow: 0 4px 15px rgba($indigo, 0.3); + } +} + +.api-content { + // Placeholder +} + +.api-section { + padding: 1.5rem; + border-radius: 1rem; + background: $bg-card; + border: 1px solid $border-color; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); +} + +.api-section-title { + display: flex; + align-items: center; + gap: 0.75rem; + font-size: 1.25rem; + font-weight: 700; + margin-bottom: 1rem; + color: $text-primary; + + ng-icon { + color: $indigo; + } +} + +.api-endpoints { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.api-endpoint { + padding: 1rem; + border-radius: 0.75rem; + background: $bg-secondary; + border: 1px solid $border-color; +} + +.endpoint-desc { + font-size: 0.875rem; + color: $text-secondary; + margin: 0.5rem 0; +} + +.endpoint-details { + display: grid; + grid-template-columns: 1fr; + gap: 1rem; + margin-top: 1rem; + + @media (min-width: 768px) { + grid-template-columns: repeat(2, 1fr); + } + + &.three-cols { + @media (min-width: 768px) { + grid-template-columns: repeat(3, 1fr); + } + } +} + +.detail-title { + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + color: $text-muted; + margin-bottom: 0.5rem; +} + +.params-table { + width: 100%; + font-size: 0.875rem; + + tbody { + tr { + border-bottom: 1px solid $border-color; + + &:last-child { + border-bottom: none; + } + } + + td { + padding: 0.5rem 0; + + &:first-child { + color: $text-primary; + font-weight: 500; + } + + &:last-child { + color: $text-secondary; + } + } + } +} + +.detail-list { + list-style: none; + padding: 0; + margin: 0; + + li { + font-size: 0.875rem; + color: $text-secondary; + padding: 0.25rem 0; + } +} + +.responses-list { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.response-item { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.875rem; + color: $text-secondary; +} + +.response-code { + padding: 0.125rem 0.5rem; + border-radius: 0.25rem; + font-size: 0.75rem; + font-weight: 500; + + &.response-success { + background: rgba($green, 0.15); + color: darken($green, 10%); + } + + &.response-warning { + background: rgba($amber, 0.15); + color: darken($amber, 10%); + } + + &.response-error { + background: rgba($red, 0.15); + color: darken($red, 10%); + } +} + +.param-tags { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin-top: 0.5rem; +} + +.param-tag { + padding: 0.25rem 0.5rem; + border-radius: 0.25rem; + background: $bg-hover; + border: 1px solid $border-color; + font-size: 0.75rem; + font-family: 'JetBrains Mono', monospace; + color: $text-secondary; +} + +.status-box { + margin-top: 1.5rem; + padding: 1rem; + border-radius: 0.75rem; + background: rgba($green, 0.05); + border: 1px solid rgba($green, 0.2); +} + +.status-title { + font-size: 0.875rem; + font-weight: 600; + color: darken($green, 10%); + margin-bottom: 0.5rem; +} + +.status-tags { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; +} + +.status-tag { + padding: 0.25rem 0.75rem; + border-radius: 9999px; + background: rgba($green, 0.1); + font-size: 0.75rem; + font-weight: 500; + color: darken($green, 10%); +} + +// Swagger Section +.swagger-header { + display: flex; + flex-direction: column; + gap: 1rem; + margin-bottom: 1.5rem; + padding: 1.5rem; + background: linear-gradient(135deg, rgba($indigo, 0.05), rgba($blue, 0.05)); + border: 1px solid rgba($indigo, 0.15); + border-radius: 1rem; + + @media (min-width: 768px) { + flex-direction: row; + align-items: center; + justify-content: space-between; + } +} + +.swagger-info { + flex: 1; +} + +.swagger-title { + display: flex; + align-items: center; + gap: 0.75rem; + font-size: 1.25rem; + font-weight: 700; + color: $text-primary; + margin-bottom: 0.5rem; + + ng-icon { + color: $indigo; + } +} + +.swagger-desc { + font-size: 0.875rem; + color: $text-secondary; + margin: 0 0 0.5rem; +} + +.swagger-version { + font-size: 0.75rem; + padding: 0.25rem 0.75rem; + background: rgba($indigo, 0.1); + color: $indigo; + border-radius: 9999px; + font-weight: 500; +} + +.swagger-search { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.625rem 1rem; + background: $bg-card; + border: 1px solid $border-color; + border-radius: 0.5rem; + min-width: 280px; + + ng-icon { + color: $text-muted; + } + + input { + flex: 1; + border: none; + background: transparent; + font-size: 0.875rem; + color: $text-primary; + outline: none; + + &::placeholder { + color: $text-muted; + } + } +} + +.swagger-layout { + display: grid; + grid-template-columns: 1fr; + gap: 1.5rem; + + @media (min-width: 1024px) { + grid-template-columns: 350px 1fr; + } +} + +.swagger-sidebar { + display: flex; + flex-direction: column; + gap: 0.5rem; + max-height: 600px; + overflow-y: auto; + padding-right: 0.5rem; + + &::-webkit-scrollbar { + width: 6px; + } + + &::-webkit-scrollbar-track { + background: $bg-secondary; + border-radius: 3px; + } + + &::-webkit-scrollbar-thumb { + background: $border-color; + border-radius: 3px; + + &:hover { + background: darken($border-color, 10%); + } + } +} + +.swagger-tag-group { + background: $bg-card; + border: 1px solid $border-color; + border-radius: 0.75rem; + overflow: hidden; +} + +.swagger-tag-header { + display: flex; + align-items: center; + gap: 0.5rem; + width: 100%; + padding: 0.875rem 1rem; + background: transparent; + border: none; + cursor: pointer; + transition: background 0.2s ease; + + &:hover { + background: $bg-hover; + } + + .tag-name { + flex: 1; + text-align: left; + font-weight: 600; + color: $text-primary; + text-transform: capitalize; + } + + .tag-count { + font-size: 0.75rem; + padding: 0.125rem 0.5rem; + background: rgba($indigo, 0.1); + color: $indigo; + border-radius: 9999px; + font-weight: 500; + } + + ng-icon { + color: $text-muted; + } +} + +.swagger-tag-endpoints { + border-top: 1px solid $border-color; + padding: 0.5rem; +} + +.swagger-endpoint-item { + display: flex; + align-items: center; + gap: 0.5rem; + width: 100%; + padding: 0.625rem 0.75rem; + background: transparent; + border: none; + border-radius: 0.5rem; + cursor: pointer; + transition: background 0.2s ease; + text-align: left; + + &:hover { + background: $bg-hover; + } + + &.selected { + background: rgba($indigo, 0.1); + + .endpoint-path { + color: $indigo; + } + } + + .endpoint-method { + font-size: 0.625rem; + padding: 0.125rem 0.375rem; + border-radius: 0.25rem; + font-weight: 700; + font-family: 'JetBrains Mono', monospace; + } + + .endpoint-path { + flex: 1; + font-size: 0.75rem; + font-family: 'JetBrains Mono', monospace; + color: $text-secondary; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } +} + +.swagger-detail { + min-height: 400px; +} + +.swagger-placeholder { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + min-height: 400px; + background: $bg-card; + border: 1px dashed $border-color; + border-radius: 1rem; + color: $text-muted; + + ng-icon { + margin-bottom: 1rem; + opacity: 0.5; + } + + p { + font-size: 0.875rem; + } +} + +.endpoint-detail-card { + background: $bg-card; + border: 1px solid $border-color; + border-radius: 1rem; + overflow: hidden; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); +} + +.endpoint-detail-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem 1.25rem; + background: $bg-secondary; + border-bottom: 1px solid $border-color; + + .close-btn { + width: 2rem; + height: 2rem; + display: flex; + align-items: center; + justify-content: center; + background: transparent; + border: 1px solid $border-color; + border-radius: 0.5rem; + font-size: 1.25rem; + color: $text-muted; + cursor: pointer; + transition: all 0.2s ease; + + &:hover { + background: $bg-hover; + color: $text-primary; + } + } +} + +.endpoint-summary { + font-size: 1.125rem; + font-weight: 600; + color: $text-primary; + margin: 1rem 1.25rem 0.5rem; +} + +.endpoint-description { + font-size: 0.875rem; + color: $text-secondary; + margin: 0 1.25rem 1rem; +} + +.endpoint-section { + padding: 1rem 1.25rem; + border-top: 1px solid $border-color; + + .section-title { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.875rem; + font-weight: 600; + color: $text-primary; + margin-bottom: 0.75rem; + text-transform: uppercase; + letter-spacing: 0.025em; + + ng-icon { + color: $indigo; + } + } +} + +.params-group { + margin-bottom: 1rem; + + &:last-child { + margin-bottom: 0; + } +} + +.params-group-title { + font-size: 0.75rem; + font-weight: 600; + color: $text-muted; + margin-bottom: 0.5rem; + text-transform: uppercase; +} + +.params-list { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.param-item { + padding: 0.75rem; + background: $bg-secondary; + border-radius: 0.5rem; + border: 1px solid $border-color; + + .param-name { + font-weight: 600; + color: $text-primary; + font-size: 0.875rem; + margin-bottom: 0.25rem; + display: flex; + align-items: center; + gap: 0.5rem; + } + + .required-badge { + font-size: 0.625rem; + padding: 0.125rem 0.375rem; + background: rgba($red, 0.1); + color: $red; + border-radius: 0.25rem; + font-weight: 500; + text-transform: uppercase; + } + + .param-type { + font-size: 0.75rem; + font-family: 'JetBrains Mono', monospace; + color: $indigo; + margin-bottom: 0.25rem; + } + + .param-enum { + display: block; + font-size: 0.7rem; + color: $text-muted; + margin-top: 0.25rem; + } + + .param-desc { + font-size: 0.75rem; + color: $text-secondary; + } +} + +.responses-grid { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; +} + +.response-card { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.5rem 0.75rem; + border-radius: 0.5rem; + border: 1px solid; + + &.response-2 { + background: rgba($green, 0.05); + border-color: rgba($green, 0.2); + + .response-status { + color: $green; + } + } + + &.response-4 { + background: rgba($amber, 0.05); + border-color: rgba($amber, 0.2); + + .response-status { + color: $amber; + } + } + + &.response-5 { + background: rgba($red, 0.05); + border-color: rgba($red, 0.2); + + .response-status { + color: $red; + } + } + + .response-status { + font-weight: 700; + font-family: 'JetBrains Mono', monospace; + } + + .response-desc { + font-size: 0.875rem; + color: $text-secondary; + } +} + +.security-badge { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.5rem 0.75rem; + background: rgba($green, 0.1); + border: 1px solid rgba($green, 0.2); + border-radius: 0.5rem; + font-size: 0.875rem; + font-weight: 500; + color: darken($green, 10%); + + ng-icon { + color: $green; + } +} + +// Footer +.doc-footer { + margin-top: 4rem; + padding-top: 2rem; + border-top: 1px solid $border-color; + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; + + @media (min-width: 768px) { + flex-direction: row; + justify-content: space-between; + } +} + +.footer-brand { + display: flex; + align-items: center; + gap: 0.5rem; + color: $text-secondary; + + ng-icon { + color: $indigo; + } +} + +.footer-name { + font-weight: 600; + color: $text-primary; +} + +.footer-divider { + color: $border-color; +} + +.footer-version { + font-size: 0.875rem; +} + +.footer-links { + display: flex; + align-items: center; + gap: 1rem; +} + +.footer-link { + display: flex; + align-items: center; + gap: 0.25rem; + font-size: 0.875rem; + color: $text-secondary; + text-decoration: none; + transition: color 0.2s ease; + + &:hover { + color: $indigo; + } +} + +// Utility Classes +.mt-3 { + margin-top: 0.75rem; +} + +.mt-4 { + margin-top: 1rem; +} diff --git a/src/app/modules/documentation/documentation.ts b/src/app/modules/documentation/documentation.ts index e388056..4c5f907 100644 --- a/src/app/modules/documentation/documentation.ts +++ b/src/app/modules/documentation/documentation.ts @@ -1,7 +1,784 @@ -import { Component } from '@angular/core'; +import { Component, OnInit, AfterViewInit, signal } from '@angular/core'; +import { CommonModule, KeyValuePipe } from '@angular/common'; +import { NgIcon, provideIcons } from '@ng-icons/core'; +import { + lucideZap, + lucideShield, + lucideUsers, + lucideCreditCard, + lucideBell, + lucideSettings, + lucideBookOpen, + lucideCode, + lucideArrowRight, + lucideExternalLink, + lucideChevronRight, + lucideChevronDown, + lucidePlay, + lucideCopy, + lucideCheck, + lucideMessageSquare, + lucideHome, + lucideFileJson, + lucideSearch, + lucideFilter, +} from '@ng-icons/lucide'; + +declare var mermaid: any; + +interface Step { + id: number; + title: string; + description: string; + icon: string; + color: string; + isOpen: boolean; + endpoint?: { + method: string; + path: string; + }; + requestBody?: string; + responseBody?: string; + note?: { + type: 'warning' | 'success' | 'info' | 'purple'; + text: string; + }; + headers?: string; +} + +interface SwaggerEndpoint { + method: string; + path: string; + summary: string; + description?: string; + operationId: string; + tags: string[]; + parameters?: any[]; + requestBody?: any; + responses?: any; + security?: any[]; +} + +interface SwaggerTag { + name: string; + endpoints: SwaggerEndpoint[]; + isOpen: boolean; +} @Component({ selector: 'app-documentation', + standalone: true, + imports: [CommonModule, NgIcon, KeyValuePipe], + viewProviders: [ + provideIcons({ + lucideZap, + lucideShield, + lucideUsers, + lucideCreditCard, + lucideBell, + lucideSettings, + lucideBookOpen, + lucideCode, + lucideArrowRight, + lucideExternalLink, + lucideChevronRight, + lucideChevronDown, + lucidePlay, + lucideCopy, + lucideCheck, + lucideMessageSquare, + lucideHome, + lucideFileJson, + lucideSearch, + lucideFilter, + }), + ], templateUrl: './documentation.html', + styleUrl: './documentation.scss', }) -export class Documentation {} \ No newline at end of file +export class Documentation implements OnInit, AfterViewInit { + activeSection = signal('overview'); + activeApiTab = signal('otp'); + copiedCode = signal(null); + swaggerSearch = signal(''); + selectedSwaggerEndpoint = signal(null); + + sections = [ + { id: 'overview', label: "Vue d'ensemble", icon: 'lucideBookOpen' }, + { id: 'flow', label: 'Call Flow', icon: 'lucidePlay' }, + { id: 'steps', label: "Étapes d'intégration", icon: 'lucideArrowRight' }, + { id: 'api', label: 'API Reference', icon: 'lucideCode' }, + ]; + + apiTabs = [ + { id: 'otp', label: 'OTP Challenge' }, + { id: 'subscriptions', label: 'Subscriptions' }, + { id: 'payments', label: 'Payments' }, + { id: 'operators', label: 'Operators' }, + { id: 'swagger', label: 'Swagger API' }, + ]; + + features = [ + { + icon: 'lucideShield', + title: 'OTP Challenge', + desc: 'Authentification sécurisée par SMS', + color: 'indigo', + }, + { + icon: 'lucideUsers', + title: 'Subscriptions', + desc: 'Gestion des abonnements récurrents', + color: 'green', + }, + { + icon: 'lucideCreditCard', + title: 'Payments', + desc: 'Facturation et charges', + color: 'blue', + }, + { + icon: 'lucideBell', + title: 'Webhooks', + desc: 'Notifications en temps réel', + color: 'purple', + }, + ]; + + steps: Step[] = [ + { + id: 1, + title: 'Initier le Challenge OTP', + description: "Envoi d'un code OTP au numéro de téléphone de l'utilisateur", + icon: 'lucideShield', + color: 'indigo', + isOpen: true, + endpoint: { method: 'POST', path: '/api/v1/otp-challenge/initiate' }, + requestBody: `{ + "msisdn": "225XXXXXXXXX", + "channel": "SMS", + "serviceId": "your-service-id", + "merchantId": "your-merchant-id" +}`, + responseBody: `{ + "challengeId": "chg_abc123xyz", + "status": "PENDING", + "expiresAt": "2024-01-15T10:30:00Z", + "channel": "SMS" +}`, + note: { + type: 'warning', + text: "⚠️ Note: Le code OTP expire après 15 minutes. Maximum 3 tentatives de validation.", + }, + }, + { + id: 2, + title: 'Valider le Code OTP', + description: "Vérification du code saisi par l'utilisateur et récupération du token ISE2", + icon: 'lucideCheck', + color: 'green', + isOpen: false, + endpoint: { method: 'POST', path: '/api/v1/otp-challenge/{challengeId}/verify' }, + requestBody: `{ + "otp": "123456" +}`, + responseBody: `{ + "challengeId": "chg_abc123xyz", + "status": "VALIDATED", + "ise2Token": "eyJhbGciOiJSUzI1NiIs...", + "validatedAt": "2024-01-15T10:28:45Z" +}`, + note: { + type: 'success', + text: "✅ Important: Conservez le ise2Token - il sera nécessaire pour la souscription et les charges.", + }, + }, + { + id: 3, + title: 'Créer une Souscription', + description: "Enregistrement de l'abonnement utilisateur au service", + icon: 'lucideUsers', + color: 'blue', + isOpen: false, + endpoint: { method: 'POST', path: '/api/v1/subscriptions' }, + requestBody: `{ + "userToken": "ise2_token_from_otp_validation", + "userAlias": "225XXXXXXXXX", + "planId": 1, + "callbackUrl": "https://your-domain.com/webhooks/subscription", + "metadata": { + "customerId": "cust_123", + "source": "mobile_app" + } +}`, + responseBody: `{ + "id": 456, + "status": "ACTIVE", + "planId": 1, + "startDate": "2024-01-15", + "nextPaymentDate": "2024-02-15", + "createdAt": "2024-01-15T10:29:00Z" +}`, + }, + { + id: 4, + title: 'Recevoir les Webhooks', + description: 'Notifications automatiques des événements (souscription, paiement, etc.)', + icon: 'lucideBell', + color: 'purple', + isOpen: false, + responseBody: `{ + "event": "subscription.created", + "timestamp": "2024-01-15T10:29:05Z", + "data": { + "subscriptionId": 456, + "ise2": "ise2_token", + "productId": "prod_abc", + "serviceId": "svc_xyz", + "status": "ACTIVE", + "msisdn": "225XXXXXXXXX" + }, + "signature": "sha256=..." +}`, + note: { + type: 'purple', + text: "🔔 Types d'événements: subscription.created, subscription.cancelled, payment.success, payment.failed", + }, + }, + { + id: 5, + title: 'Effectuer une Charge', + description: "Facturation du montant sur le compte mobile de l'utilisateur", + icon: 'lucideCreditCard', + color: 'orange', + isOpen: false, + endpoint: { method: 'POST', path: '/api/v1/payments/charge' }, + headers: `X-Merchant-ID: your-merchant-id +X-COUNTRY: CI +X-OPERATOR: ORANGE`, + requestBody: `{ + "userToken": "ise2_token", + "amount": 500, + "currency": "XOF", + "description": "Abonnement Premium - Janvier 2024", + "reference": "PAY-2024-001-ABC", + "subscriptionId": 456, + "callbackUrl": "https://your-domain.com/webhooks/payment", + "metadata": { + "orderId": "ord_789" + } +}`, + responseBody: `{ + "id": "pay_xyz789", + "status": "SUCCESS", + "amount": 500, + "currency": "XOF", + "reference": "PAY-2024-001-ABC", + "operatorReference": "OPR-123456", + "completedAt": "2024-01-15T10:30:15Z" +}`, + }, + { + id: 6, + title: 'Envoyer un SMS de Confirmation', + description: "Notification SMS à l'utilisateur confirmant l'activation du service", + icon: 'lucideMessageSquare', + color: 'pink', + isOpen: false, + endpoint: { method: 'POST', path: '/smsmessaging/service/mea/v1/outbound/{senderMsisdn}/requests' }, + requestBody: `{ + "outboundSMSMessageRequest": { + "address": ["tel:+225XXXXXXXXX"], + "senderAddress": "tel:+225YYYYYYYYYY", + "outboundSMSTextMessage": { + "message": "Félicitations! Votre abonnement Premium est maintenant actif." + } + } +}`, + }, + ]; + + subscriptionStatuses = ['ACTIVE', 'TRIAL', 'PENDING', 'SUSPENDED', 'EXPIRED', 'CANCELLED']; + + // Swagger data parsed from the JSON + swaggerTags: SwaggerTag[] = []; + swaggerInfo = { + title: 'Payment Hub API', + description: 'Unified DCB Payment Aggregation Platform', + version: '1.0.0' + }; + + mermaidDiagram = `sequenceDiagram + participant USER as 👤 Utilisateur + participant Partner as 🏪 Partner + participant HUB as ⚡ HUB DCB + participant DigiPay as 📱 DigiPay + + rect rgb(99, 102, 241, 0.1) + Note over Partner,DigiPay: 🔐 Phase 1: OTP Challenge + Partner->>HUB: POST /api/v1/otp-challenge/initiate + HUB->>DigiPay: POST /challenge/v1/challenges + DigiPay-->>HUB: challengeId + status + HUB-->>Partner: challengeId + status + end + + DigiPay->>USER: 📨 SMS avec code OTP + USER->>Partner: Saisie du code OTP + + rect rgb(34, 197, 94, 0.1) + Note over Partner,DigiPay: ✅ Phase 2: Validation OTP + Partner->>HUB: POST /api/v1/otp-challenge/{id}/verify + HUB->>DigiPay: POST /challenge/v1/challenges/{id} + DigiPay-->>HUB: ise2 token + HUB-->>Partner: ise2 token + end + + rect rgb(59, 130, 246, 0.1) + Note over Partner,DigiPay: 📋 Phase 3: Souscription + Partner->>HUB: POST /api/v1/subscriptions + HUB->>DigiPay: POST /digipay_sub/productOrder/ + DigiPay-->>HUB: subscription response + HUB-->>Partner: subscription details + end + + rect rgb(168, 85, 247, 0.1) + Note over Partner,DigiPay: 🔔 Notification Webhook + DigiPay->>HUB: Subscription notification + HUB->>Partner: Webhook callback + end + + rect rgb(249, 115, 22, 0.1) + Note over Partner,DigiPay: 💳 Phase 4: Facturation + Partner->>HUB: POST /api/v1/payments/charge + HUB->>DigiPay: POST /payment/mea/v1/.../transactions/amount + DigiPay-->>HUB: payment response + HUB-->>Partner: payment confirmation + end + + rect rgb(236, 72, 153, 0.1) + Note over Partner,DigiPay: 📱 Phase 5: SMS Confirmation + Partner->>HUB: POST /smsmessaging/.../requests + HUB->>DigiPay: Send SMS + DigiPay->>USER: 📨 SMS de confirmation + end + + HUB->>USER: 🎉 Service activé`; + + ngOnInit(): void { + this.parseSwaggerSpec(); + } + + ngAfterViewInit(): void { + this.initMermaid(); + } + + private parseSwaggerSpec(): void { + // Parse the Swagger JSON spec + const swaggerSpec = { + "openapi": "3.0.0", + "paths": { + "/api/v1/operators": { + "get": { + "operationId": "OperatorsController_getOperatorStatistics", + "parameters": [ + {"name": "operatorCode", "required": true, "in": "path", "schema": {"type": "string"}}, + {"name": "period", "required": false, "in": "query", "schema": {"enum": ["daily", "weekly", "monthly", "yearly"], "type": "string"}}, + {"name": "startDate", "required": false, "in": "query", "schema": {"format": "date-time", "type": "string"}}, + {"name": "endDate", "required": false, "in": "query", "schema": {"format": "date-time", "type": "string"}}, + {"name": "active", "required": false, "in": "query", "schema": {"type": "boolean"}}, + {"name": "country", "required": false, "in": "query", "schema": {}} + ], + "responses": {"200": {"description": "List of operators"}}, + "security": [{"bearer": []}], + "summary": "List all available operators", + "tags": ["operators"] + } + }, + "/api/v1/operators/{operatorCode}/health": { + "get": { + "operationId": "OperatorsController_getOperatorHealth", + "parameters": [{"name": "operatorCode", "required": true, "in": "path", "schema": {"type": "string"}}], + "responses": {"200": {"description": "Operator health metrics"}}, + "security": [{"bearer": []}], + "summary": "Get operator health metrics", + "tags": ["operators"] + } + }, + "/api/v1/operators/detect/{msisdn}": { + "get": { + "operationId": "OperatorsController_detectOperator", + "parameters": [{"name": "msisdn", "required": true, "in": "path", "schema": {"type": "string"}}], + "responses": {"200": {"description": "Detected operator information"}}, + "security": [{"bearer": []}], + "summary": "Detect operator from MSISDN", + "tags": ["operators"] + } + }, + "/api/v1/payments/charge": { + "post": { + "operationId": "PaymentsController_createCharge", + "parameters": [ + {"name": "X-Merchant-ID", "required": true, "in": "header", "schema": {"type": "string"}}, + {"name": "X-COUNTRY", "required": true, "in": "header", "schema": {"type": "string"}}, + {"name": "X-OPERATOR", "required": true, "in": "header", "schema": {"type": "string"}} + ], + "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChargeDto"}}}}, + "responses": { + "201": {"description": "Payment created successfully"}, + "400": {"description": "Bad request"}, + "401": {"description": "Unauthorized"} + }, + "security": [{"bearer": []}], + "summary": "Create a new charge", + "tags": ["payments"] + } + }, + "/api/v1/payments/{paymentId}/refund": { + "post": { + "operationId": "PaymentsController_refundPayment", + "parameters": [{"name": "paymentId", "required": true, "in": "path", "schema": {"type": "string"}}], + "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/RefundDto"}}}}, + "responses": { + "200": {"description": "Refund processed successfully"}, + "404": {"description": "Payment not found"} + }, + "security": [{"bearer": []}], + "summary": "Refund a payment", + "tags": ["payments"] + } + }, + "/api/v1/payments/{paymentId}": { + "get": { + "operationId": "PaymentsController_getPayment", + "parameters": [{"name": "paymentId", "required": true, "in": "path", "schema": {"type": "number"}}], + "responses": { + "200": {"description": "Payment details retrieved"}, + "404": {"description": "Payment not found"} + }, + "security": [{"bearer": []}], + "summary": "Get payment details", + "tags": ["payments"] + } + }, + "/api/v1/payments/reference/{reference}": { + "get": { + "operationId": "PaymentsController_getPaymentByReference", + "parameters": [{"name": "reference", "required": true, "in": "path", "schema": {"type": "string"}}], + "responses": {"200": {"description": "Payment details retrieved"}}, + "security": [{"bearer": []}], + "summary": "Get payment by reference", + "tags": ["payments"] + } + }, + "/api/v1/payments": { + "get": { + "description": "Retrieve payments with optional filters on status, type, dates, amounts, etc.", + "operationId": "PaymentsController_getAll", + "parameters": [ + {"name": "page", "required": false, "in": "query", "description": "Page number", "schema": {"minimum": 1, "default": 1, "type": "number"}}, + {"name": "limit", "required": false, "in": "query", "description": "Number of items per page", "schema": {"minimum": 1, "maximum": 100, "default": 10, "type": "number"}}, + {"name": "type", "required": false, "in": "query", "description": "Filter by payment type", "schema": {"type": "string", "enum": ["MM", "BANK", "CHEQUE"]}}, + {"name": "status", "required": false, "in": "query", "description": "Filter by transaction status", "schema": {"type": "string", "enum": ["SUCCESS", "FAILED", "PENDING"]}}, + {"name": "merchantPartnerId", "required": false, "in": "query", "description": "Filter by merchant partner ID", "schema": {"type": "number"}}, + {"name": "currency", "required": false, "in": "query", "description": "Filter by currency code", "schema": {"example": "XOF", "type": "string"}}, + {"name": "amountMin", "required": false, "in": "query", "description": "Filter payments with amount >= this value", "schema": {"type": "number"}}, + {"name": "amountMax", "required": false, "in": "query", "description": "Filter payments with amount <= this value", "schema": {"type": "number"}}, + {"name": "createdFrom", "required": false, "in": "query", "description": "Filter payments created from this date", "schema": {"type": "string"}}, + {"name": "createdTo", "required": false, "in": "query", "description": "Filter payments created until this date", "schema": {"type": "string"}}, + {"name": "sortBy", "required": false, "in": "query", "description": "Sort field", "schema": {"default": "createdAt", "type": "string", "enum": ["createdAt", "completedAt", "amount"]}}, + {"name": "sortOrder", "required": false, "in": "query", "description": "Sort order", "schema": {"default": "desc", "type": "string", "enum": ["asc", "desc"]}} + ], + "responses": {"200": {"description": "Paginated list of payments"}}, + "summary": "Get payment list with pagination and filters", + "tags": ["payments"] + } + }, + "/api/v1/payments/{paymentId}/retry": { + "post": { + "operationId": "PaymentsController_retryPayment", + "parameters": [{"name": "paymentId", "required": true, "in": "path", "schema": {"type": "string"}}], + "responses": { + "200": {"description": "Payment retry initiated"}, + "400": {"description": "Payment cannot be retried"} + }, + "security": [{"bearer": []}], + "summary": "Retry a failed payment", + "tags": ["payments"] + } + }, + "/api/v1/subscriptions": { + "post": { + "operationId": "SubscriptionsController_create", + "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CreateSubscriptionDto"}}}}, + "responses": {"201": {"description": "Subscription created successfully"}}, + "summary": "Create subscription", + "tags": ["subscriptions"] + }, + "get": { + "operationId": "SubscriptionsController_getAll", + "parameters": [ + {"name": "page", "required": false, "in": "query", "description": "Page number", "schema": {"minimum": 1, "default": 1, "type": "number"}}, + {"name": "limit", "required": false, "in": "query", "description": "Number of items per page", "schema": {"minimum": 1, "maximum": 100, "default": 10, "type": "number"}}, + {"name": "status", "required": false, "in": "query", "description": "Filter by subscription status", "schema": {"type": "string", "enum": ["ACTIVE", "TRIAL", "PENDING", "SUSPENDED", "EXPIRED", "CANCELLED"]}}, + {"name": "periodicity", "required": false, "in": "query", "description": "Filter by periodicity", "schema": {"type": "string", "enum": ["Daily", "Weekly", "Monthly", "OneTime"]}}, + {"name": "serviceId", "required": false, "in": "query", "description": "Filter by service ID", "schema": {"type": "number"}} + ], + "responses": {"200": {"description": "Paginated list of subscriptions"}}, + "summary": "Get subscription list with pagination", + "tags": ["subscriptions"] + } + }, + "/api/v1/subscriptions/{id}": { + "get": { + "operationId": "SubscriptionsController_get", + "parameters": [{"name": "id", "required": true, "in": "path", "schema": {"type": "number"}}], + "responses": {"200": {"description": "Subscription details"}}, + "summary": "Get subscription details", + "tags": ["subscriptions"] + }, + "delete": { + "operationId": "SubscriptionsController_cancel", + "parameters": [{"name": "id", "required": true, "in": "path", "schema": {"type": "number"}}], + "responses": {"200": {"description": "Subscription cancelled"}}, + "summary": "Cancel subscription", + "tags": ["subscriptions"] + } + }, + "/api/v1/otp-challenge/initiate": { + "post": { + "description": "Envoie un code OTP au numéro de téléphone spécifié via SMS, USSD ou IVR", + "operationId": "OtpChallengeController_initiateChallenge", + "parameters": [ + {"name": "X-Merchant-ID", "required": true, "in": "header", "description": "Identifiant du merchant", "schema": {"type": "string"}}, + {"name": "X-API-Key", "required": true, "in": "header", "description": "Clé API du merchant", "schema": {"type": "string"}} + ], + "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OtpChallengeRequestDto"}}}}, + "responses": { + "201": {"description": "Challenge OTP initié avec succès"}, + "400": {"description": "Requête invalide"}, + "500": {"description": "Erreur serveur"} + }, + "summary": "Initier un challenge OTP", + "tags": ["OTP Challenge"] + } + }, + "/api/v1/otp-challenge/{challengeId}/verify": { + "post": { + "description": "Vérifie le code OTP entré par l'utilisateur", + "operationId": "OtpChallengeController_verifyOtp", + "parameters": [ + {"name": "challengeId", "required": true, "in": "path", "description": "Identifiant du challenge", "schema": {"type": "string"}}, + {"name": "X-Merchant-ID", "required": true, "in": "header", "description": "Identifiant du merchant", "schema": {"type": "string"}}, + {"name": "X-API-Key", "required": true, "in": "header", "description": "Clé API du merchant", "schema": {"type": "string"}} + ], + "responses": { + "200": {"description": "Code OTP vérifié avec succès"}, + "400": {"description": "Code OTP invalide"}, + "404": {"description": "Challenge non trouvé"} + }, + "summary": "Vérifier un code OTP", + "tags": ["OTP Challenge"] + } + } + }, + "info": { + "title": "Payment Hub API", + "description": "Unified DCB Payment Aggregation Platform", + "version": "1.0.0" + }, + "components": { + "schemas": { + "ChargeDto": { + "type": "object", + "properties": { + "userToken": {"type": "string", "description": "User token from authentication"}, + "amount": {"type": "number", "description": "Amount to charge"}, + "currency": {"type": "string", "description": "Currency code (XOF, XAF, USD, etc.)"}, + "description": {"type": "string", "description": "Payment description"}, + "reference": {"type": "string", "description": "Unique payment reference"}, + "subscriptionId": {"type": "number", "description": "Subscription ID if recurring"}, + "callbackUrl": {"type": "string", "description": "Callback URL for notifications"}, + "metadata": {"type": "object", "description": "Additional metadata"} + }, + "required": ["userToken", "amount", "currency", "description"] + }, + "RefundDto": { + "type": "object", + "properties": { + "amount": {"type": "number", "description": "Amount to refund (partial refund)"}, + "reason": {"type": "string", "description": "Reason for refund"}, + "metadata": {"type": "object", "description": "Additional metadata"} + }, + "required": ["reason"] + }, + "CreateSubscriptionDto": { + "type": "object", + "properties": { + "userToken": {"type": "string"}, + "userAlias": {"type": "string"}, + "planId": {"type": "number"}, + "callbackUrl": {"type": "string"}, + "metadata": {"type": "object"} + }, + "required": ["userToken", "userAlias", "planId"] + }, + "OtpChallengeRequestDto": { + "type": "object", + "properties": { + "msisdn": {"type": "string", "description": "Phone number"}, + "channel": {"type": "string", "enum": ["SMS", "USSD", "IVR"]}, + "serviceId": {"type": "string"} + } + } + } + } + }; + + // Group endpoints by tags + const tagGroups: Record = {}; + + Object.entries(swaggerSpec.paths).forEach(([path, methods]) => { + Object.entries(methods as Record).forEach(([method, details]) => { + const endpoint: SwaggerEndpoint = { + method: method.toUpperCase(), + path: path, + summary: details.summary || '', + description: details.description || '', + operationId: details.operationId || '', + tags: details.tags || ['default'], + parameters: details.parameters || [], + requestBody: details.requestBody, + responses: details.responses, + security: details.security + }; + + const tag = endpoint.tags[0] || 'default'; + if (!tagGroups[tag]) { + tagGroups[tag] = []; + } + tagGroups[tag].push(endpoint); + }); + }); + + this.swaggerTags = Object.entries(tagGroups).map(([name, endpoints]) => ({ + name, + endpoints, + isOpen: name === 'payments' + })); + } + + private initMermaid(): void { + if (typeof mermaid !== 'undefined') { + mermaid.initialize({ + startOnLoad: false, + theme: 'default', + themeVariables: { + primaryColor: '#6366f1', + primaryTextColor: '#1e293b', + primaryBorderColor: '#818cf8', + lineColor: '#64748b', + secondaryColor: '#f1f5f9', + tertiaryColor: '#ffffff', + background: '#ffffff', + mainBkg: '#f8fafc', + textColor: '#1e293b', + }, + }); + } + } + + renderMermaid(): void { + setTimeout(() => { + if (typeof mermaid !== 'undefined') { + const element = document.querySelector('.mermaid'); + if (element) { + element.innerHTML = this.mermaidDiagram; + mermaid.run({ nodes: [element] }); + } + } + }, 100); + } + + setActiveSection(sectionId: string): void { + this.activeSection.set(sectionId); + if (sectionId === 'flow') { + this.renderMermaid(); + } + } + + setActiveApiTab(tabId: string): void { + this.activeApiTab.set(tabId); + } + + toggleStep(step: Step): void { + step.isOpen = !step.isOpen; + } + + toggleSwaggerTag(tag: SwaggerTag): void { + tag.isOpen = !tag.isOpen; + } + + selectSwaggerEndpoint(endpoint: SwaggerEndpoint): void { + this.selectedSwaggerEndpoint.set(endpoint); + } + + closeSwaggerDetail(): void { + this.selectedSwaggerEndpoint.set(null); + } + + async copyCode(code: string, codeId: string): Promise { + try { + await navigator.clipboard.writeText(code); + this.copiedCode.set(codeId); + setTimeout(() => this.copiedCode.set(null), 2000); + } catch (err) { + console.error('Failed to copy:', err); + } + } + + getMethodClass(method: string): string { + const classes: Record = { + GET: 'method-get', + POST: 'method-post', + PUT: 'method-put', + DELETE: 'method-delete', + PATCH: 'method-patch', + }; + return classes[method] || 'method-get'; + } + + getStepColorClass(color: string): string { + return `step-${color}`; + } + + getNoteClass(type: string): string { + return `note-${type}`; + } + + getFilteredSwaggerTags(): SwaggerTag[] { + const search = this.swaggerSearch().toLowerCase(); + if (!search) return this.swaggerTags; + + return this.swaggerTags.map(tag => ({ + ...tag, + endpoints: tag.endpoints.filter( + e => e.path.toLowerCase().includes(search) || + e.summary.toLowerCase().includes(search) || + e.method.toLowerCase().includes(search) + ) + })).filter(tag => tag.endpoints.length > 0); + } + + onSwaggerSearch(event: Event): void { + const value = (event.target as HTMLInputElement).value; + this.swaggerSearch.set(value); + } + + formatJson(obj: any): string { + return JSON.stringify(obj, null, 2); + } + + getParametersByLocation(params: any[], location: string): any[] { + return params?.filter(p => p.in === location) || []; + } +} diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 80c1eef..927a057 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -1,8 +1,8 @@ export const environment = { production: false, - localServiceTestApiUrl: "http://localhost:4200/api/v1", - iamApiUrl: "http://localhost:3000/api/v1", + localServiceTestApiUrl: "https://backoffice.dcb.pixpay.sn/api/v1", + iamApiUrl: "https://api-user-service.dcb.pixpay.sn/api/v1", configApiUrl: 'https://api-merchant-config-service.dcb.pixpay.sn/api/v1', - apiCoreUrl: 'https://api-core-service.dcb.pixpay.sn/api/v1', - reportingApiUrl: 'https://api-reporting-service.dcb.pixpay.sn/api/v1', -} \ No newline at end of file + apiCoreUrl: 'https://api-core-service.dcb.pixpay.sn/api/v1', + reportingApiUrl: 'https://api-reporting-service.dcb.pixpay.sn/api/v1/', +} diff --git a/src/types/mermaid.d.ts b/src/types/mermaid.d.ts new file mode 100644 index 0000000..f47792e --- /dev/null +++ b/src/types/mermaid.d.ts @@ -0,0 +1,27 @@ +// src/types/mermaid.d.ts + +declare module 'mermaid' { + interface MermaidConfig { + startOnLoad?: boolean; + theme?: string; + themeVariables?: Record; + securityLevel?: string; + flowchart?: Record; + sequence?: Record; + } + + interface MermaidAPI { + initialize(config: MermaidConfig): void; + run(config?: { nodes?: Element[] }): Promise; + render(id: string, text: string): Promise<{ svg: string }>; + } + + const mermaid: MermaidAPI; + export default mermaid; +} + +declare var mermaid: { + initialize(config: any): void; + run(config?: { nodes?: Element[] }): Promise; + render(id: string, text: string): Promise<{ svg: string }>; +};