From 43be344b9aaa73721d061cc2cc83df6b70c8f28b Mon Sep 17 00:00:00 2001 From: Guillaume Beraudo Date: Wed, 6 Nov 2024 10:51:03 +0100 Subject: [PATCH 1/3] Add basic OIDC module --- index.html | 3 + package-lock.json | 504 ++++++++++--------- package.json | 18 +- src/apps/custom/customConfig.ts | 22 + src/interfaces/auth/ingv-auth-context.ts | 31 ++ src/interfaces/auth/ingv-auth-provider.ts | 7 + src/plugins/auth/ngv-auth-oidcjs-provider.ts | 113 +++++ src/plugins/auth/ngv-auth-providers.ts | 15 + src/plugins/auth/ngv-plugin-auth.ts | 64 +++ src/structure/ngv-structure-app.ts | 2 + src/structure/ngv-structure-header.ts | 6 + vite.config.js | 1 + 12 files changed, 529 insertions(+), 257 deletions(-) create mode 100644 src/interfaces/auth/ingv-auth-context.ts create mode 100644 src/interfaces/auth/ingv-auth-provider.ts create mode 100644 src/plugins/auth/ngv-auth-oidcjs-provider.ts create mode 100644 src/plugins/auth/ngv-auth-providers.ts create mode 100644 src/plugins/auth/ngv-plugin-auth.ts diff --git a/index.html b/index.html index e12493b..d6a93f1 100644 --- a/index.html +++ b/index.html @@ -20,6 +20,9 @@

List of turn-key apps:

>Digital twins: illumination / solar +
  • + Your app: custom +
  • ...
  • diff --git a/package-lock.json b/package-lock.json index fdbfb17..053c640 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,32 +13,32 @@ "@types/geojson": "^7946.0.14" }, "devDependencies": { - "@cesium/engine": "11.1.0", - "@cesium/widgets": "8.1.0", - "@eslint/js": "9.13.0", + "@cesium/engine": "12.0.1", + "@cesium/widgets": "9.0.1", + "@eslint/js": "9.15.0", "@geoblocks/ifc-gltf": "^0.0.2", - "@geoblocks/oidcjs": "^0.5.10", + "@geoblocks/oidcjs": "0.5.12", "@lit/context": "1.1.3", "@lit/localize": "^0.12.2", "@lit/localize-tools": "^0.8.0", "@lit/task": "^1.0.1", - "@microsoft/api-documenter": "7.25.21", - "@microsoft/api-extractor": "7.47.11", + "@microsoft/api-documenter": "7.25.22", + "@microsoft/api-extractor": "7.47.12", "@trevoreyre/autocomplete-js": "3.0.3", "csstype": "^3.1.3", - "eslint": "9.13.0", + "eslint": "9.15.0", "eslint-config-prettier": "^9.1.0", "lit": "3.2.1", "prettier": "3.3.3", "typescript": "5.6.3", - "typescript-eslint": "8.12.2", - "vite": "5.4.10" + "typescript-eslint": "8.15.0", + "vite": "5.4.11" } }, "node_modules/@cesium/engine": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/@cesium/engine/-/engine-11.1.0.tgz", - "integrity": "sha512-vrEQAbYQuXt2cMYF9BpBu4Kxu+8uje1CrFHfyI5aNp7gCrUK1RYquldyqT7TDr3YKe7oZMHL+Xeb5Vm8ua6gZQ==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@cesium/engine/-/engine-12.0.1.tgz", + "integrity": "sha512-ou/Vu/tthTHDa2GbCrPiVWgue9AhPevWRk8hOQiEmwd1gy8aQCeMfCAfN3DXfBu7uj4wcw0+AeM7ObQgfVjjdg==", "dev": true, "dependencies": { "@tweenjs/tween.js": "^25.0.0", @@ -54,7 +54,7 @@ "ktx-parse": "^0.7.0", "lerc": "^2.0.0", "mersenne-twister": "^1.1.0", - "meshoptimizer": "^0.21.0", + "meshoptimizer": "^0.22.0", "pako": "^2.0.4", "protobufjs": "^7.1.0", "rbush": "3.0.1", @@ -66,12 +66,12 @@ } }, "node_modules/@cesium/widgets": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@cesium/widgets/-/widgets-8.1.0.tgz", - "integrity": "sha512-WD5eokNfSQmB3oqe97KmdmDefwzooHaMWBm9kE/Af9edyD2j3eQVTrbNhiJ06UIyEjd01U1af2iDOawI9adAgA==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@cesium/widgets/-/widgets-9.0.1.tgz", + "integrity": "sha512-qSm5c97zsGk1IWJKkPhsPNLWTcBqn9RdtumTm5dJCCtpOtJw05H/Uywr5Jz93H7QXs9ClygxLwe5nshNaa+6ig==", "dev": true, "dependencies": { - "@cesium/engine": "^11.1.0", + "@cesium/engine": "^12.0.1", "nosleep.js": "^0.12.0" }, "engines": { @@ -118,18 +118,18 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/config-array": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", - "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz", + "integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==", "dev": true, "dependencies": { "@eslint/object-schema": "^2.1.4", @@ -141,18 +141,18 @@ } }, "node_modules/@eslint/core": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", - "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", + "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -172,10 +172,32 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/@eslint/js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "version": "9.15.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.15.0.tgz", + "integrity": "sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -191,9 +213,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.2.tgz", - "integrity": "sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", + "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", "dev": true, "dependencies": { "levn": "^0.4.1" @@ -234,9 +256,9 @@ } }, "node_modules/@geoblocks/oidcjs": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/@geoblocks/oidcjs/-/oidcjs-0.5.10.tgz", - "integrity": "sha512-LMudD0rdzc6L3qjGgmFtWUirisdNEnXv9ge5d92ercupD/6+jY89Ehf+r8gCLlczXrmY20H9DTRUSsLQknbu4Q==", + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/@geoblocks/oidcjs/-/oidcjs-0.5.12.tgz", + "integrity": "sha512-2qddrxGForwdqiWWUnbLUbUD/q26NtDnGqlBoOzb3U6lWc+JcBzt101c/xGn8F7TQoe0bGCHFJM/dLwYbGHWWA==", "dev": true }, "node_modules/@humanfs/core": { @@ -406,16 +428,16 @@ } }, "node_modules/@microsoft/api-documenter": { - "version": "7.25.21", - "resolved": "https://registry.npmjs.org/@microsoft/api-documenter/-/api-documenter-7.25.21.tgz", - "integrity": "sha512-Nyfidxbi9wIZ1H7VjVqw3nUhRM1fUJuGqvt2iDEI91Z4k8X+BqxSaLOsnn8n65YaAZhUJRkh1Ouxt90r7cnmjA==", + "version": "7.25.22", + "resolved": "https://registry.npmjs.org/@microsoft/api-documenter/-/api-documenter-7.25.22.tgz", + "integrity": "sha512-eTfxI6/5mpJmXfwwADtj8D9zgR1lrHx7On9HlDvwkBhATRwVc6OOmWgzPNbVpPiDjywZy+V4gmgrlsnipY6Meg==", "dev": true, "dependencies": { - "@microsoft/api-extractor-model": "7.29.8", + "@microsoft/api-extractor-model": "7.29.9", "@microsoft/tsdoc": "~0.15.0", - "@rushstack/node-core-library": "5.9.0", - "@rushstack/terminal": "0.14.2", - "@rushstack/ts-command-line": "4.23.0", + "@rushstack/node-core-library": "5.10.0", + "@rushstack/terminal": "0.14.3", + "@rushstack/ts-command-line": "4.23.1", "js-yaml": "~3.13.1", "resolve": "~1.22.1" }, @@ -423,15 +445,6 @@ "api-documenter": "bin/api-documenter" } }, - "node_modules/@microsoft/api-documenter/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/@microsoft/api-documenter/node_modules/js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", @@ -446,18 +459,18 @@ } }, "node_modules/@microsoft/api-extractor": { - "version": "7.47.11", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.47.11.tgz", - "integrity": "sha512-lrudfbPub5wzBhymfFtgZKuBvXxoSIAdrvS2UbHjoMT2TjIEddq6Z13pcve7A03BAouw0x8sW8G4txdgfiSwpQ==", + "version": "7.47.12", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.47.12.tgz", + "integrity": "sha512-YE/h4vE9T1i3oGtgEZC7pHupH/drtGAuQ36iJ1Ua0gQ8NXmPXNKNilkCqzWnX/QvMnr1xSgEjHppWMXEi5YZKQ==", "dev": true, "dependencies": { - "@microsoft/api-extractor-model": "7.29.8", + "@microsoft/api-extractor-model": "7.29.9", "@microsoft/tsdoc": "~0.15.0", "@microsoft/tsdoc-config": "~0.17.0", - "@rushstack/node-core-library": "5.9.0", + "@rushstack/node-core-library": "5.10.0", "@rushstack/rig-package": "0.5.3", - "@rushstack/terminal": "0.14.2", - "@rushstack/ts-command-line": "4.23.0", + "@rushstack/terminal": "0.14.3", + "@rushstack/ts-command-line": "4.23.1", "lodash": "~4.17.15", "minimatch": "~3.0.3", "resolve": "~1.22.1", @@ -470,14 +483,14 @@ } }, "node_modules/@microsoft/api-extractor-model": { - "version": "7.29.8", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.29.8.tgz", - "integrity": "sha512-t3Z/xcO6TRbMcnKGVMs4uMzv/gd5j0NhMiJIGjD4cJMeFJ1Hf8wnLSx37vxlRlL0GWlGJhnFgxvnaL6JlS+73g==", + "version": "7.29.9", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.29.9.tgz", + "integrity": "sha512-/DaMfUjiswmrnLjHCorVzWGbW5rmeTGDo+H0QcvcarJ14SjNVmFWiRKzscN4B2y9AyllqeXMPgwbtSFAdAkpMQ==", "dev": true, "dependencies": { "@microsoft/tsdoc": "~0.15.0", "@microsoft/tsdoc-config": "~0.17.0", - "@rushstack/node-core-library": "5.9.0" + "@rushstack/node-core-library": "5.10.0" } }, "node_modules/@microsoft/api-extractor/node_modules/minimatch": { @@ -523,28 +536,6 @@ "resolve": "~1.22.2" } }, - "node_modules/@microsoft/tsdoc-config/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@microsoft/tsdoc-config/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -862,9 +853,9 @@ ] }, "node_modules/@rushstack/node-core-library": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.9.0.tgz", - "integrity": "sha512-MMsshEWkTbXqxqFxD4gcIUWQOCeBChlGczdZbHfqmNZQFLHB3yWxDFSMHFUdu2/OB9NUk7Awn5qRL+rws4HQNg==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.10.0.tgz", + "integrity": "sha512-2pPLCuS/3x7DCd7liZkqOewGM0OzLyCacdvOe8j6Yrx9LkETGnxul1t7603bIaB8nUAooORcct9fFDOQMbWAgw==", "dev": true, "dependencies": { "ajv": "~8.13.0", @@ -901,26 +892,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@rushstack/node-core-library/node_modules/ajv-draft-04": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", - "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", - "dev": true, - "peerDependencies": { - "ajv": "^8.5.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/@rushstack/node-core-library/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/@rushstack/rig-package": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.5.3.tgz", @@ -932,12 +903,12 @@ } }, "node_modules/@rushstack/terminal": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.14.2.tgz", - "integrity": "sha512-2fC1wqu1VCExKC0/L+0noVcFQEXEnoBOtCIex1TOjBzEDWcw8KzJjjj7aTP6mLxepG0XIyn9OufeFb6SFsa+sg==", + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.14.3.tgz", + "integrity": "sha512-csXbZsAdab/v8DbU1sz7WC2aNaKArcdS/FPmXMOXEj/JBBZMvDK0+1b4Qao0kkG0ciB1Qe86/Mb68GjH6/TnMw==", "dev": true, "dependencies": { - "@rushstack/node-core-library": "5.9.0", + "@rushstack/node-core-library": "5.10.0", "supports-color": "~8.1.1" }, "peerDependencies": { @@ -965,26 +936,17 @@ } }, "node_modules/@rushstack/ts-command-line": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.23.0.tgz", - "integrity": "sha512-jYREBtsxduPV6ptNq8jOKp9+yx0ld1Tb/Tkdnlj8gTjazl1sF3DwX2VbluyYrNd0meWIL0bNeer7WDf5tKFjaQ==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.23.1.tgz", + "integrity": "sha512-40jTmYoiu/xlIpkkRsVfENtBq4CW3R4azbL0Vmda+fMwHWqss6wwf/Cy/UJmMqIzpfYc2OTnjYP1ZLD3CmyeCA==", "dev": true, "dependencies": { - "@rushstack/terminal": "0.14.2", + "@rushstack/terminal": "0.14.3", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" } }, - "node_modules/@rushstack/ts-command-line/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/@shoelace-style/animations": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@shoelace-style/animations/-/animations-1.2.0.tgz", @@ -1118,16 +1080,16 @@ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.12.2.tgz", - "integrity": "sha512-gQxbxM8mcxBwaEmWdtLCIGLfixBMHhQjBqR8sVWNTPpcj45WlYL2IObS/DNMLH1DBP0n8qz+aiiLTGfopPEebw==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz", + "integrity": "sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.12.2", - "@typescript-eslint/type-utils": "8.12.2", - "@typescript-eslint/utils": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/type-utils": "8.15.0", + "@typescript-eslint/utils": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1151,15 +1113,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.12.2.tgz", - "integrity": "sha512-MrvlXNfGPLH3Z+r7Tk+Z5moZAc0dzdVjTgUgwsdGweH7lydysQsnSww3nAmsq8blFuRD5VRlAr9YdEFw3e6PBw==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.15.0.tgz", + "integrity": "sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.12.2", - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/typescript-estree": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2", + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4" }, "engines": { @@ -1179,13 +1141,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.12.2.tgz", - "integrity": "sha512-gPLpLtrj9aMHOvxJkSbDBmbRuYdtiEbnvO25bCMza3DhMjTQw0u7Y1M+YR5JPbMsXXnSPuCf5hfq0nEkQDL/JQ==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", + "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2" + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1196,13 +1158,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.12.2.tgz", - "integrity": "sha512-bwuU4TAogPI+1q/IJSKuD4shBLc/d2vGcRT588q+jzayQyjVK2X6v/fbR4InY2U2sgf8MEvVCqEWUzYzgBNcGQ==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.15.0.tgz", + "integrity": "sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.12.2", - "@typescript-eslint/utils": "8.12.2", + "@typescript-eslint/typescript-estree": "8.15.0", + "@typescript-eslint/utils": "8.15.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1213,6 +1175,9 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, "peerDependenciesMeta": { "typescript": { "optional": true @@ -1220,9 +1185,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.12.2.tgz", - "integrity": "sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", + "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1233,13 +1198,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.2.tgz", - "integrity": "sha512-mME5MDwGe30Pq9zKPvyduyU86PH7aixwqYR2grTglAdB+AN8xXQ1vFGpYaUSJ5o5P/5znsSBeNcs5g5/2aQwow==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", + "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/visitor-keys": "8.15.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1297,15 +1262,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.12.2.tgz", - "integrity": "sha512-UTTuDIX3fkfAz6iSVa5rTuSfWIYZ6ATtEocQ/umkRSyC9O919lbZ8dcH7mysshrCdrAM03skJOEYaBugxN+M6A==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz", + "integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.12.2", - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/typescript-estree": "8.12.2" + "@typescript-eslint/scope-manager": "8.15.0", + "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/typescript-estree": "8.15.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1316,16 +1281,21 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.2.tgz", - "integrity": "sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", + "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.12.2", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "8.15.0", + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1335,6 +1305,18 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@xmldom/xmldom": { "version": "0.8.10", "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", @@ -1377,14 +1359,14 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", "uri-js": "^4.2.2" }, "funding": { @@ -1392,6 +1374,20 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "dev": true, + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/ajv-formats": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", @@ -1409,28 +1405,6 @@ } } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -1447,10 +1421,13 @@ } }, "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } }, "node_modules/autolinker": { "version": "4.0.0", @@ -1577,9 +1554,9 @@ "dev": true }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "dependencies": { "path-key": "^3.1.0", @@ -1699,31 +1676,31 @@ } }, "node_modules/eslint": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", - "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", + "version": "9.15.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.15.0.tgz", + "integrity": "sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.7.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.13.0", - "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.15.0", + "@eslint/plugin-kit": "^0.2.3", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", + "@humanwhocodes/retry": "^0.4.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.5", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -1737,8 +1714,7 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" @@ -1798,12 +1774,41 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/eslint/node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", @@ -1816,6 +1821,12 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/espree": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", @@ -1946,12 +1957,6 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, - "node_modules/fast-uri": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", - "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", - "dev": true - }, "node_modules/fast-xml-parser": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", @@ -2276,6 +2281,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/js-yaml/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "node_modules/jsep": { "version": "1.3.9", "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.3.9.tgz", @@ -2292,9 +2303,9 @@ "dev": true }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { @@ -2477,9 +2488,9 @@ "dev": true }, "node_modules/meshoptimizer": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.21.0.tgz", - "integrity": "sha512-WabtlpnK/GgD0GMwYd1fBTfYHf4MIcQPEg6dt7y4GuDcY51RzLSkSNE8ZogD7U3Vs2/fIf4z89TOLpA80EOnhg==", + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.22.0.tgz", + "integrity": "sha512-IebiK79sqIy+E4EgOr+CAw+Ke8hAspXKzBd0JdgEmPHiAwmvEj2S4h1rfvo+o/BnfEYd/jAOg5IeeIjzlzSnDg==", "dev": true }, "node_modules/micromatch": { @@ -3062,12 +3073,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, "node_modules/three": { "version": "0.160.1", "resolved": "https://registry.npmjs.org/three/-/three-0.160.1.tgz", @@ -3154,14 +3159,14 @@ } }, "node_modules/typescript-eslint": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.12.2.tgz", - "integrity": "sha512-UbuVUWSrHVR03q9CWx+JDHeO6B/Hr9p4U5lRH++5tq/EbFq1faYZe50ZSBePptgfIKLEti0aPQ3hFgnPVcd8ZQ==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.15.0.tgz", + "integrity": "sha512-wY4FRGl0ZI+ZU4Jo/yjdBu0lVTSML58pu6PgGtJmCufvzfV565pUF6iACQt092uFOd49iLOTX/sEVmHtbSrS+w==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "8.12.2", - "@typescript-eslint/parser": "8.12.2", - "@typescript-eslint/utils": "8.12.2" + "@typescript-eslint/eslint-plugin": "8.15.0", + "@typescript-eslint/parser": "8.15.0", + "@typescript-eslint/utils": "8.15.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3170,6 +3175,9 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, "peerDependenciesMeta": { "typescript": { "optional": true @@ -3213,9 +3221,9 @@ "dev": true }, "node_modules/vite": { - "version": "5.4.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz", - "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==", + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", "dev": true, "dependencies": { "esbuild": "^0.21.3", diff --git a/package.json b/package.json index a642245..b347ae0 100644 --- a/package.json +++ b/package.json @@ -23,26 +23,26 @@ "description": "Next Generation 3D Viewer framework", "type": "module", "devDependencies": { - "@cesium/engine": "11.1.0", - "@cesium/widgets": "8.1.0", - "@eslint/js": "9.13.0", + "@cesium/engine": "12.0.1", + "@cesium/widgets": "9.0.1", + "@eslint/js": "9.15.0", "@geoblocks/ifc-gltf": "^0.0.2", - "@geoblocks/oidcjs": "^0.5.10", + "@geoblocks/oidcjs": "0.5.12", "@lit/context": "1.1.3", "@lit/localize": "^0.12.2", "@lit/localize-tools": "^0.8.0", "@lit/task": "^1.0.1", - "@microsoft/api-documenter": "7.25.21", - "@microsoft/api-extractor": "7.47.11", + "@microsoft/api-documenter": "7.25.22", + "@microsoft/api-extractor": "7.47.12", "@trevoreyre/autocomplete-js": "3.0.3", "csstype": "^3.1.3", - "eslint": "9.13.0", + "eslint": "9.15.0", "eslint-config-prettier": "^9.1.0", "lit": "3.2.1", "prettier": "3.3.3", "typescript": "5.6.3", - "typescript-eslint": "8.12.2", - "vite": "5.4.10" + "typescript-eslint": "8.15.0", + "vite": "5.4.11" }, "dependencies": { "@shoelace-style/shoelace": "2.18.0", diff --git a/src/apps/custom/customConfig.ts b/src/apps/custom/customConfig.ts index c953d7a..ff1b822 100644 --- a/src/apps/custom/customConfig.ts +++ b/src/apps/custom/customConfig.ts @@ -1,5 +1,26 @@ +import type {IngvAuthContext} from '../../interfaces/auth/ingv-auth-context.js'; import type {CustomConfig} from './ingv-config-custom.js'; +// See https://developers.google.com/identity/openid-connect/openid-connect#discovery +const wellknown = { + authorization_endpoint: + 'https://sso.geomapfish-demo.prod.apps.gs-ch-prod.camptocamp.com/oauth/v2/authorize', + token_endpoint: + 'https://sso.geomapfish-demo.prod.apps.gs-ch-prod.camptocamp.com/oauth/v2/token', +}; + +const authContext: IngvAuthContext = { + provider: { + type: 'oidc', + wellknown, + options: { + redirectUri: `${document.location.origin}/src/apps/custom/index.html`, + clientId: '294600834753305656', + scopes: ['openid', 'offline_access', 'profile', 'email'], + pkce: true, + }, + }, +}; export const config: CustomConfig = { languages: ['fr', 'en'], header: { @@ -25,6 +46,7 @@ export const config: CustomConfig = { ], }, }, + authContext, footer: { contact: 'me@example.com', impressum: { diff --git a/src/interfaces/auth/ingv-auth-context.ts b/src/interfaces/auth/ingv-auth-context.ts new file mode 100644 index 0000000..f3f96f5 --- /dev/null +++ b/src/interfaces/auth/ingv-auth-context.ts @@ -0,0 +1,31 @@ +/** + * The well known configuration for an OpenID Connect provider + */ +interface OidcWellKnownConfig { + authorization_endpoint: string; + token_endpoint: string; + logout_endpoint?: string; +} + +export interface OidcProviderConfig { + type: 'oidc'; + wellknown: OidcWellKnownConfig; + options: { + clientId: string; + clientSecret?: string; + pkce?: boolean; + scopes: string[]; + redirectUri: string; // automatic? + }; +} + +export interface FormProviderConfig { + type: 'form'; + loginUrl: string; + logoutUrl: string; + userUrl: string; +} + +export interface IngvAuthContext { + provider: OidcProviderConfig | FormProviderConfig; +} diff --git a/src/interfaces/auth/ingv-auth-provider.ts b/src/interfaces/auth/ingv-auth-provider.ts new file mode 100644 index 0000000..4baed6d --- /dev/null +++ b/src/interfaces/auth/ingv-auth-provider.ts @@ -0,0 +1,7 @@ +export interface IngvAuthProvider { + status: 'unknown' | 'logged' | 'unlogged'; + initialize: (config: any) => Promise; + useForm: boolean; + login: () => Promise; + logout: () => Promise; +} diff --git a/src/plugins/auth/ngv-auth-oidcjs-provider.ts b/src/plugins/auth/ngv-auth-oidcjs-provider.ts new file mode 100644 index 0000000..57401c9 --- /dev/null +++ b/src/plugins/auth/ngv-auth-oidcjs-provider.ts @@ -0,0 +1,113 @@ +import Client from '@geoblocks/oidcjs'; +import type {OidcProviderConfig} from '../../interfaces/auth/ingv-auth-context.js'; + +class OidcProvider { + private oidcClient: Client; + private config: OidcProviderConfig; + public status: 'unknown' | 'logged' | 'unlogged' = 'unknown'; + + get useForm() { + return false; + } + + async initialize(config: OidcProviderConfig): Promise { + this.config = config; + this.oidcClient = new Client(config.options, config.wellknown); + + await this.finishAuthenticationProcedure(); + try { + const token = await this.oidcClient.getActiveToken(); + if (!token || token === '') { + this.status = 'unlogged'; + return undefined; + } + const parsedToken = this.oidcClient.parseJwtPayload(token); + console.log('activeToken', parsedToken); + console.log( + 'idToken', + this.oidcClient.parseJwtPayload(this.oidcClient.getActiveIdToken()), + ); + this.status = 'logged'; + return undefined; + } catch (e) { + console.error('could not initialize user', e); + // return Promise.reject(e); + } + } + + private async finishAuthenticationProcedure() { + const postLogoutUrl = localStorage.getItem('appPostLogoutURL'); + if (postLogoutUrl) { + localStorage.removeItem('appPostLogoutURL'); + document.location = postLogoutUrl; + return; + } + const preLoginUrl = localStorage.getItem('appPreLoginURL'); + if (!preLoginUrl) { + return; + } + try { + const searchParams = new URLSearchParams(document.location.search); + await this.oidcClient.handleStateIfInURL(searchParams).then((results) => { + switch (results.status) { + case 'completed': { + localStorage.removeItem('appPreLoginURL'); + document.location = preLoginUrl; + return; + } + case 'invalid': + case 'error': { + // Display an error message + console.log('Login failed', results.msg); + return; + } + case 'nothing': { + // Do nothing + return; + } + } + }); + } catch (error) { + console.log('Login failed', error); + } + } + + async login(): Promise { + localStorage.setItem('appPreLoginURL', document.location.href); + try { + const loginURL = + await this.oidcClient.createAuthorizeAndUpdateLocalStorage(); + document.location = loginURL; + } catch (error) { + console.error('Error:', error); + } + return Promise.resolve(); + } + + logout(): Promise { + if (!this.config.wellknown.logout_endpoint) { + this.oidcClient.lclear(); + this.status = 'unlogged'; + return Promise.resolve(); + } + const idToken = localStorage.getItem('oidcjs_id_token'); + this.oidcClient.lclear(); + // we will reload the page during the logout process so we don't have to clear the user status + // in addition, that would interfere with the logout process + + // Also logout from the SSO itself (not only the app) + const newLocation = new URL(this.config.wellknown.logout_endpoint); + newLocation.searchParams.append( + 'post_logout_redirect_uri', + this.config.options.redirectUri, + ); + newLocation.searchParams.append('client_id', this.config.options.clientId); + newLocation.searchParams.append('id_token_hint', idToken); + localStorage.setItem('appPostLogoutURL', document.location.href); + document.location = newLocation.toString(); + this.status = 'unlogged'; + return Promise.resolve(); + } +} + +export const provider = new OidcProvider(); diff --git a/src/plugins/auth/ngv-auth-providers.ts b/src/plugins/auth/ngv-auth-providers.ts new file mode 100644 index 0000000..f66ecf0 --- /dev/null +++ b/src/plugins/auth/ngv-auth-providers.ts @@ -0,0 +1,15 @@ +import type {IngvAuthProvider} from '../../interfaces/auth/ingv-auth-provider.js'; + +const factories: Record Promise<{provider: IngvAuthProvider}>> = { + // Here we register singletons for builtin providers + oidc: () => import('./ngv-auth-oidcjs-provider.js'), + // add custom singletons here or through the setter +}; + +export async function getProvider(name: string): Promise { + if (name in factories) { + const {provider} = await factories[name](); + return provider; + } + return Promise.reject(new Error('No known provider with name ' + name)); +} diff --git a/src/plugins/auth/ngv-plugin-auth.ts b/src/plugins/auth/ngv-plugin-auth.ts new file mode 100644 index 0000000..fab5227 --- /dev/null +++ b/src/plugins/auth/ngv-plugin-auth.ts @@ -0,0 +1,64 @@ +import type {HTMLTemplateResult} from 'lit'; +import {LitElement, html} from 'lit'; +import {customElement, property, state} from 'lit/decorators.js'; +import {getProvider} from './ngv-auth-providers.js'; +import type {IngvAuthProvider} from '../../interfaces/auth/ingv-auth-provider.js'; +import type {IngvAuthContext} from '../../interfaces/auth/ingv-auth-context.js'; + +@customElement('ngv-plugin-auth') +export class NgvPluginAuth extends LitElement { + @property({type: Object}) + authContext: IngvAuthContext; + + // we need an observable / state + @state() + status: IngvAuthProvider['status']; + + provider: IngvAuthProvider; + + private async initAuth(): Promise { + this.provider = await getProvider(this.authContext.provider.type); + await this.provider.initialize(this.authContext.provider); + this.status = this.provider.status; + } + + protected firstUpdated(): void { + this.initAuth().catch((e) => { + console.error('Error during auth initialization: ', e); + }); + } + + render(): HTMLTemplateResult { + switch (this.status) { + case 'unknown': + return html`?`; + case 'logged': + return html``; + case 'unlogged': + if (this.provider.useForm) { + return html`some form`; + } + return html``; + } + } +} + +declare global { + interface HTMLElementTagNameMap { + 'ngv-plugin-auth': NgvPluginAuth; + } +} diff --git a/src/structure/ngv-structure-app.ts b/src/structure/ngv-structure-app.ts index c1e4887..61502d6 100644 --- a/src/structure/ngv-structure-app.ts +++ b/src/structure/ngv-structure-app.ts @@ -7,9 +7,11 @@ import {getLocale} from './helpers/localeHelper.js'; import './ngv-page.js'; import './ngv-structure-header.js'; import type {IngvSearchContext} from '../interfaces/search/ingv-search-context.js'; +import type {IngvAuthContext} from '../interfaces/auth/ingv-auth-context.js'; export interface INgvStructureApp { languages: Partial[]; + authContext?: IngvAuthContext; header: { logo?: string; title: Partial>; diff --git a/src/structure/ngv-structure-header.ts b/src/structure/ngv-structure-header.ts index bdfa36d..66da786 100644 --- a/src/structure/ngv-structure-header.ts +++ b/src/structure/ngv-structure-header.ts @@ -4,6 +4,7 @@ import {customElement, property} from 'lit/decorators.js'; import type {INgvStructureApp} from './ngv-structure-app.js'; import {getLocale, setLocale} from './helpers/localeHelper.js'; import '../plugins/search/ngv-plugin-search.js'; +import '../plugins/auth/ngv-plugin-auth'; @customElement('ngv-structure-header') export class NgvStructureHeader extends LitElement { @@ -31,6 +32,11 @@ export class NgvStructureHeader extends LitElement { .searchContext=${headerConfig.searchContext} >` : ''} + + +