diff --git a/web/.prettierrc.json b/web/.prettierrc.json deleted file mode 100644 index d1897435dc..0000000000 --- a/web/.prettierrc.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "arrowParens": "always", - "bracketSpacing": true, - "embeddedLanguageFormatting": "auto", - "htmlWhitespaceSensitivity": "css", - "insertPragma": false, - "jsxSingleQuote": false, - "printWidth": 100, - "proseWrap": "preserve", - "quoteProps": "consistent", - "requirePragma": false, - "semi": true, - "singleQuote": false, - "tabWidth": 4, - "trailingComma": "all", - "useTabs": false, - "vueIndentScriptAndStyle": false, - "plugins": ["@trivago/prettier-plugin-sort-imports"], - "importOrder": ["^(@?)lit(.*)$", "\\.css$", "^@goauthentik/api$", "^[./]"], - "importOrderSeparation": true, - "importOrderSortSpecifiers": true, - "importOrderParserPlugins": ["typescript", "jsx", "classProperties", "decorators-legacy"] -} diff --git a/web/package-lock.json b/web/package-lock.json index acbb6602ca..af3baaa947 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -73,6 +73,9 @@ }, "devDependencies": { "@eslint/js": "^9.11.1", + "@goauthentik/esbuild-plugin-live-reload": "^1.0.4", + "@goauthentik/prettier-config": "^1.0.4", + "@goauthentik/tsconfig": "^1.0.4", "@hcaptcha/types": "^1.0.4", "@lit/localize-tools": "^0.8.0", "@rollup/plugin-replace": "^6.0.1", @@ -84,7 +87,7 @@ "@storybook/manager-api": "^8.3.4", "@storybook/web-components": "^8.3.4", "@storybook/web-components-vite": "^8.3.4", - "@trivago/prettier-plugin-sort-imports": "^4.3.0", + "@trivago/prettier-plugin-sort-imports": "^5.2.2", "@types/chart.js": "^2.9.41", "@types/codemirror": "^5.60.15", "@types/dompurify": "^3.0.5", @@ -107,7 +110,6 @@ "eslint": "^9.11.1", "eslint-plugin-lit": "^1.15.0", "eslint-plugin-wc": "^2.1.1", - "find-free-ports": "^3.1.1", "github-slugger": "^2.0.0", "glob": "^11.0.0", "globals": "^15.10.0", @@ -234,40 +236,6 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core/node_modules/@babel/traverse": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/core/node_modules/@babel/types": { "version": "7.27.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", @@ -287,27 +255,6 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, - "node_modules/@babel/core/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/core/node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -318,26 +265,34 @@ } }, "node_modules/@babel/generator": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", - "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "node_modules/@babel/generator/node_modules/@babel/types": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { @@ -379,6 +334,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.24.7" }, @@ -391,6 +347,7 @@ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" @@ -404,6 +361,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.24.7", "@babel/types": "^7.24.7" @@ -417,6 +375,7 @@ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" @@ -430,6 +389,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.24.7" }, @@ -442,6 +402,7 @@ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" @@ -463,40 +424,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-module-imports/node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports/node_modules/@babel/traverse": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-module-imports/node_modules/@babel/types": { "version": "7.27.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", @@ -510,27 +437,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-module-imports/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/helper-module-imports/node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/@babel/helper-module-transforms": { "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", @@ -548,79 +454,12 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-module-transforms/node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms/node_modules/@babel/traverse": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms/node_modules/@babel/types": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", - "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/helper-module-transforms/node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.24.7" }, @@ -633,6 +472,7 @@ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" @@ -774,37 +614,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/@babel/generator": { "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", + "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", "dev": true, + "license": "MIT", "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.27.0", "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", "@babel/types": "^7.27.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" + "debug": "^4.3.1", + "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" @@ -815,6 +637,7 @@ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" @@ -828,22 +651,11 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/@babel/traverse/node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/@babel/types": { "version": "7.17.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", @@ -1731,6 +1543,36 @@ "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2025.2.4-1744886287.tgz", "integrity": "sha512-Wx1/tS3/8fxI/rd8m8WOTuzDOKcUASWdOsoPsds2CxswMi3pt4KaLlh/Hcl8gAabsJnIUNZu4Ajj1p1fMJvwxw==" }, + "node_modules/@goauthentik/esbuild-plugin-live-reload": { + "resolved": "packages/esbuild-plugin-live-reload", + "link": true + }, + "node_modules/@goauthentik/prettier-config": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-1.0.4.tgz", + "integrity": "sha512-CgUVAThlJHif7ZRXUPMbR/7/YLGzkJw7YbqEcleUjjKkvID0aykrypXx04td6cG76zigspTCgJKoXimKT41E7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.11" + }, + "peerDependencies": { + "@trivago/prettier-plugin-sort-imports": "^5.2.2", + "prettier": "^3.5.3", + "prettier-plugin-organize-imports": "^4.1.0", + "prettier-plugin-packagejson": "^2.5.10" + } + }, + "node_modules/@goauthentik/tsconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@goauthentik/tsconfig/-/tsconfig-1.0.4.tgz", + "integrity": "sha512-BTGVpGh8SbCRHTULBf+2WTcw6OHJ8Ws9VtVfAMUUgcq8whbH/A7Q/n8WbkDaEeihzHUFkLk3JBenHKzEKAZWlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.11" + } + }, "node_modules/@goauthentik/web": { "resolved": "", "link": true @@ -3761,6 +3603,20 @@ "node": ">=14" } }, + "node_modules/@pkgr/core": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.2.tgz", + "integrity": "sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/@prisma/instrumentation": { "version": "5.22.0", "resolved": "https://registry.npmjs.org/@prisma/instrumentation/-/instrumentation-5.22.0.tgz", @@ -5989,28 +5845,54 @@ "dev": true }, "node_modules/@trivago/prettier-plugin-sort-imports": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz", - "integrity": "sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-5.2.2.tgz", + "integrity": "sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/generator": "7.17.7", - "@babel/parser": "^7.20.5", - "@babel/traverse": "7.23.2", - "@babel/types": "7.17.0", - "javascript-natural-sort": "0.7.1", + "@babel/generator": "^7.26.5", + "@babel/parser": "^7.26.7", + "@babel/traverse": "^7.26.7", + "@babel/types": "^7.26.7", + "javascript-natural-sort": "^0.7.1", "lodash": "^4.17.21" }, + "engines": { + "node": ">18.12" + }, "peerDependencies": { "@vue/compiler-sfc": "3.x", - "prettier": "2.x - 3.x" + "prettier": "2.x - 3.x", + "prettier-plugin-svelte": "3.x", + "svelte": "4.x || 5.x" }, "peerDependenciesMeta": { "@vue/compiler-sfc": { "optional": true + }, + "prettier-plugin-svelte": { + "optional": true + }, + "svelte": { + "optional": true } } }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/types": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -11121,6 +11003,31 @@ "dev": true, "optional": true }, + "node_modules/detect-indent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", + "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/detect-newline": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz", + "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/devlop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", @@ -13284,8 +13191,7 @@ "node_modules/find-free-ports": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/find-free-ports/-/find-free-ports-3.1.1.tgz", - "integrity": "sha512-hQebewth9i5qkf0a0u06iFaxQssk5ZnPBBggsa1vk8zCYaZoz9IZXpoRLTbEOrYdqfrjvcxU00gYoCPgmXugKA==", - "dev": true + "integrity": "sha512-hQebewth9i5qkf0a0u06iFaxQssk5ZnPBBggsa1vk8zCYaZoz9IZXpoRLTbEOrYdqfrjvcxU00gYoCPgmXugKA==" }, "node_modules/find-up": { "version": "5.0.0", @@ -13622,6 +13528,20 @@ "node": ">= 0.4" } }, + "node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-stream": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", @@ -13708,6 +13628,17 @@ "giget": "dist/cli.mjs" } }, + "node_modules/git-hooks-list": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.2.0.tgz", + "integrity": "sha512-ZHG9a1gEhUMX1TvGrLdyWb9kDopCBbTnI8z4JgRMYxsijWipgjSEYoPWqBuIB0DnRnvqlQSEeVmzpeuPm7NdFQ==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/fisker/git-hooks-list?sponsor=1" + } + }, "node_modules/github-slugger": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", @@ -15648,15 +15579,16 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-buffer": { @@ -19551,6 +19483,44 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/prettier-plugin-organize-imports": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.1.0.tgz", + "integrity": "sha512-5aWRdCgv645xaa58X8lOxzZoiHAldAPChljr/MT0crXVOWTZ+Svl4hIWlz+niYSlO6ikE5UXkN1JrRvIP2ut0A==", + "dev": true, + "license": "MIT", + "peer": true, + "peerDependencies": { + "prettier": ">=2.0", + "typescript": ">=2.9", + "vue-tsc": "^2.1.0" + }, + "peerDependenciesMeta": { + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/prettier-plugin-packagejson": { + "version": "2.5.10", + "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.10.tgz", + "integrity": "sha512-LUxATI5YsImIVSaaLJlJ3aE6wTD+nvots18U3GuQMJpUyClChaZlQrqx3dBnbhF20OnKWZyx8EgyZypQtBDtgQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "sort-package-json": "2.15.1", + "synckit": "0.9.2" + }, + "peerDependencies": { + "prettier": ">= 1.16.0" + }, + "peerDependenciesMeta": { + "prettier": { + "optional": true + } + } + }, "node_modules/pretty-format": { "version": "30.0.0-alpha.6", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.0-alpha.6.tgz", @@ -21697,6 +21667,35 @@ "node": ">=0.10.0" } }, + "node_modules/sort-object-keys": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", + "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/sort-package-json": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.15.1.tgz", + "integrity": "sha512-9x9+o8krTT2saA9liI4BljNjwAbvUnWf11Wq+i/iZt8nl2UGYnf3TH5uBydE7VALmP7AGwlfszuEeL8BDyb0YA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "detect-indent": "^7.0.1", + "detect-newline": "^4.0.0", + "get-stdin": "^9.0.0", + "git-hooks-list": "^3.0.0", + "is-plain-obj": "^4.1.0", + "semver": "^7.6.0", + "sort-object-keys": "^1.1.3", + "tinyglobby": "^0.2.9" + }, + "bin": { + "sort-package-json": "cli.js" + } + }, "node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", @@ -22302,6 +22301,24 @@ "ramda-adjunct": "^5.1.0" } }, + "node_modules/synckit": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/syncpack": { "version": "13.0.3", "resolved": "https://registry.npmjs.org/syncpack/-/syncpack-13.0.3.tgz", @@ -24634,6 +24651,153 @@ "url": "https://github.com/sponsors/wooorm" } }, + "packages/esbuild-plugin-live-reload": { + "name": "@goauthentik/esbuild-plugin-live-reload", + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "find-free-ports": "^3.1.1" + }, + "devDependencies": { + "@goauthentik/prettier-config": "^1.0.4", + "@goauthentik/tsconfig": "^1.0.4", + "@trivago/prettier-plugin-sort-imports": "^5.2.2", + "@types/node": "^22.14.1", + "esbuild": "^0.25.0", + "prettier": "^3.3.3", + "typescript": "^5.6.2" + }, + "engines": { + "node": ">=20.11" + }, + "peerDependencies": { + "esbuild": "^0.25.0" + } + }, + "packages/esbuild-plugin-live-reload/node_modules/@babel/generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "packages/esbuild-plugin-live-reload/node_modules/@babel/traverse": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", + "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "packages/esbuild-plugin-live-reload/node_modules/@babel/types": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "packages/esbuild-plugin-live-reload/node_modules/@goauthentik/prettier-config": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-1.0.4.tgz", + "integrity": "sha512-CgUVAThlJHif7ZRXUPMbR/7/YLGzkJw7YbqEcleUjjKkvID0aykrypXx04td6cG76zigspTCgJKoXimKT41E7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.11" + }, + "peerDependencies": { + "@trivago/prettier-plugin-sort-imports": "^5.2.2", + "prettier": "^3.5.3", + "prettier-plugin-organize-imports": "^4.1.0", + "prettier-plugin-packagejson": "^2.5.10" + } + }, + "packages/esbuild-plugin-live-reload/node_modules/@trivago/prettier-plugin-sort-imports": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-5.2.2.tgz", + "integrity": "sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@babel/generator": "^7.26.5", + "@babel/parser": "^7.26.7", + "@babel/traverse": "^7.26.7", + "@babel/types": "^7.26.7", + "javascript-natural-sort": "^0.7.1", + "lodash": "^4.17.21" + }, + "engines": { + "node": ">18.12" + }, + "peerDependencies": { + "@vue/compiler-sfc": "3.x", + "prettier": "2.x - 3.x", + "prettier-plugin-svelte": "3.x", + "svelte": "4.x || 5.x" + }, + "peerDependenciesMeta": { + "@vue/compiler-sfc": { + "optional": true + }, + "prettier-plugin-svelte": { + "optional": true + }, + "svelte": { + "optional": true + } + } + }, + "packages/esbuild-plugin-live-reload/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "packages/esbuild-plugin-live-reload/node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "packages/sfe": { "name": "@goauthentik/web-sfe", "version": "0.0.0", @@ -24674,10 +24838,148 @@ "@swc/core-win32-x64-msvc": "^1.6.13" } }, + "packages/sfe/node_modules/@babel/generator": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", + "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.17.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "packages/sfe/node_modules/@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "packages/sfe/node_modules/@babel/traverse/node_modules/@babel/generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "packages/sfe/node_modules/@babel/traverse/node_modules/@babel/types": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "packages/sfe/node_modules/@babel/traverse/node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "packages/sfe/node_modules/@goauthentik/api": { "version": "2024.6.0-1720200294", "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2024.6.0-1720200294.tgz", "integrity": "sha512-qGpI+0BpsHWlO8waj89q+6SWjVVuRtYqdmpSIrKFsZt9GLNXCvIAvgS5JI1Sq2z1uWK/8kLNZKDocI/XagqMPQ==" + }, + "packages/sfe/node_modules/@trivago/prettier-plugin-sort-imports": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz", + "integrity": "sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@babel/generator": "7.17.7", + "@babel/parser": "^7.20.5", + "@babel/traverse": "7.23.2", + "@babel/types": "7.17.0", + "javascript-natural-sort": "0.7.1", + "lodash": "^4.17.21" + }, + "peerDependencies": { + "@vue/compiler-sfc": "3.x", + "prettier": "2.x - 3.x" + }, + "peerDependenciesMeta": { + "@vue/compiler-sfc": { + "optional": true + } + } + }, + "packages/sfe/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "packages/sfe/node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "packages/sfe/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } } } } diff --git a/web/package.json b/web/package.json index 6750441db2..4a9e24dc97 100644 --- a/web/package.json +++ b/web/package.json @@ -61,6 +61,9 @@ }, "devDependencies": { "@eslint/js": "^9.11.1", + "@goauthentik/esbuild-plugin-live-reload": "^1.0.4", + "@goauthentik/prettier-config": "^1.0.4", + "@goauthentik/tsconfig": "^1.0.4", "@hcaptcha/types": "^1.0.4", "@lit/localize-tools": "^0.8.0", "@rollup/plugin-replace": "^6.0.1", @@ -72,7 +75,7 @@ "@storybook/manager-api": "^8.3.4", "@storybook/web-components": "^8.3.4", "@storybook/web-components-vite": "^8.3.4", - "@trivago/prettier-plugin-sort-imports": "^4.3.0", + "@trivago/prettier-plugin-sort-imports": "^5.2.2", "@types/chart.js": "^2.9.41", "@types/codemirror": "^5.60.15", "@types/dompurify": "^3.0.5", @@ -95,7 +98,6 @@ "eslint": "^9.11.1", "eslint-plugin-lit": "^1.15.0", "eslint-plugin-wc": "^2.1.1", - "find-free-ports": "^3.1.1", "github-slugger": "^2.0.0", "glob": "^11.0.0", "globals": "^15.10.0", @@ -136,6 +138,7 @@ "axios": "^1.8.4" } }, + "prettier": "@goauthentik/prettier-config", "private": true, "scripts": { "build": "wireit", @@ -271,7 +274,7 @@ "command": "tsc --noEmit -p ./tests" }, "lint:types": { - "command": "tsc --noEmit -p .", + "command": "NODE_OPTIONS=\"--max-old-space-size=3000\" tsc -b .", "dependencies": [ "build-locales", "lint:types:tests" diff --git a/web/src/common/client.ts b/web/packages/esbuild-plugin-live-reload/client/ESBuildObserver.js similarity index 68% rename from web/src/common/client.ts rename to web/packages/esbuild-plugin-live-reload/client/ESBuildObserver.js index 1869392740..b4f90b54a8 100644 --- a/web/src/common/client.ts +++ b/web/packages/esbuild-plugin-live-reload/client/ESBuildObserver.js @@ -1,13 +1,18 @@ +/// + /** - * @file - * Client-side observer for ESBuild events. + * @file Client-side observer for ESBuild events. + * + * @import { Message as ESBuildMessage } from "esbuild"; */ -import type { Message as ESBuildMessage } from "esbuild"; const logPrefix = "👷 [ESBuild]"; const log = console.debug.bind(console, logPrefix); -type BuildEventListener = (event: MessageEvent) => void; +/** + * @template {unknown} [Data=unknown] + * @typedef {(event: MessageEvent) => void} BuildEventListener + */ /** * A client-side watcher for ESBuild. @@ -16,14 +21,13 @@ type BuildEventListener = (event: MessageEvent) => void; * ESBuild may tree-shake it out of production builds. * * ```ts - * if (process.env.NODE_ENV === "development" && process.env.WATCHER_URL) { - * const { ESBuildObserver } = await import("@goauthentik/common/client"); - * - * new ESBuildObserver(process.env.WATCHER_URL); + * if (process.env.NODE_ENV === "development") { + * await import("@goauthentik/esbuild-plugin-live-reload/client") + * .catch(() => console.warn("Failed to import watcher")) * } * ``` -} - + * + * @implements {Disposable} */ export class ESBuildObserver extends EventSource { /** @@ -58,15 +62,19 @@ export class ESBuildObserver extends EventSource { /** * The interval for the keep-alive check. + * @type {ReturnType | undefined} */ - #keepAliveInterval: ReturnType | undefined; + #keepAliveInterval; #trackActivity = () => { this.lastUpdatedAt = Date.now(); this.alive = true; }; - #startListener: BuildEventListener = () => { + /** + * @type {BuildEventListener} + */ + #startListener = () => { this.#trackActivity(); log("⏰ Build started..."); }; @@ -82,13 +90,18 @@ export class ESBuildObserver extends EventSource { } }; - #errorListener: BuildEventListener = (event) => { + /** + * @type {BuildEventListener} + */ + #errorListener = (event) => { this.#trackActivity(); - // eslint-disable-next-line no-console console.group(logPrefix, "⛔️⛔️⛔️ Build error..."); - const esbuildErrorMessages: ESBuildMessage[] = JSON.parse(event.data); + /** + * @type {ESBuildMessage[]} + */ + const esbuildErrorMessages = JSON.parse(event.data); for (const error of esbuildErrorMessages) { console.warn(error.text); @@ -101,11 +114,13 @@ export class ESBuildObserver extends EventSource { } } - // eslint-disable-next-line no-console console.groupEnd(); }; - #endListener: BuildEventListener = () => { + /** + * @type {BuildEventListener} + */ + #endListener = () => { cancelAnimationFrame(this.#reloadFrameID); this.#trackActivity(); @@ -126,12 +141,36 @@ export class ESBuildObserver extends EventSource { }); }; - #keepAliveListener: BuildEventListener = () => { + /** + * @type {BuildEventListener} + */ + #keepAliveListener = () => { this.#trackActivity(); log("🏓 Keep-alive"); }; - constructor(url: string | URL) { + /** + * Initialize the ESBuild observer. + * This should be called once in your application. + * + * @param {string | URL} [url] + * @returns {ESBuildObserver} + */ + static initialize = (url) => { + const esbuildObserver = new ESBuildObserver(url); + + return esbuildObserver; + }; + + /** + * + * @param {string | URL} [url] + */ + constructor(url) { + if (!url) { + throw new TypeError("ESBuildObserver: Cannot construct without a URL"); + } + super(url); this.addEventListener("esbuild:start", this.#startListener); @@ -167,4 +206,14 @@ export class ESBuildObserver extends EventSource { log("👋 Waiting for build to start..."); }, 15_000); } + + [Symbol.dispose]() { + return this.close(); + } + + dispose() { + return this[Symbol.dispose](); + } } + +export default ESBuildObserver; diff --git a/web/packages/esbuild-plugin-live-reload/client/index.js b/web/packages/esbuild-plugin-live-reload/client/index.js new file mode 100644 index 0000000000..41b79aeb8d --- /dev/null +++ b/web/packages/esbuild-plugin-live-reload/client/index.js @@ -0,0 +1,13 @@ +/// +/** + * @file Entry point for the ESBuild client-side observer. + */ +import { ESBuildObserver } from "./ESBuildObserver.js"; + +if (import.meta.env?.ESBUILD_WATCHER_URL) { + const buildObserver = new ESBuildObserver(import.meta.env.ESBUILD_WATCHER_URL); + + window.addEventListener("beforeunload", () => { + buildObserver.dispose(); + }); +} diff --git a/web/packages/esbuild-plugin-live-reload/client/types.d.ts b/web/packages/esbuild-plugin-live-reload/client/types.d.ts new file mode 100644 index 0000000000..c446181716 --- /dev/null +++ b/web/packages/esbuild-plugin-live-reload/client/types.d.ts @@ -0,0 +1,18 @@ +/** + * @file Import meta environment variables available via ESBuild. + */ + +export {}; +declare global { + interface ImportMeta { + readonly env: { + /** + * The injected watcher URL for ESBuild. + * This is used for live reloading in development mode. + * + * @format url + */ + ESBUILD_WATCHER_URL: string; + }; + } +} diff --git a/web/packages/esbuild-plugin-live-reload/index.js b/web/packages/esbuild-plugin-live-reload/index.js new file mode 100644 index 0000000000..9aef9c75db --- /dev/null +++ b/web/packages/esbuild-plugin-live-reload/index.js @@ -0,0 +1,2 @@ +export * from "./client/index.js"; +export * from "./plugin/index.js"; diff --git a/web/packages/esbuild-plugin-live-reload/package.json b/web/packages/esbuild-plugin-live-reload/package.json new file mode 100644 index 0000000000..3ddd26f0a4 --- /dev/null +++ b/web/packages/esbuild-plugin-live-reload/package.json @@ -0,0 +1,53 @@ +{ + "name": "@goauthentik/esbuild-plugin-live-reload", + "description": "ESBuild plugin to watch for file changes and trigger client-side reloads.", + "version": "1.0.4", + "dependencies": { + "find-free-ports": "^3.1.1" + }, + "devDependencies": { + "@goauthentik/prettier-config": "^1.0.4", + "@goauthentik/tsconfig": "^1.0.4", + "@trivago/prettier-plugin-sort-imports": "^5.2.2", + "@types/node": "^22.14.1", + "esbuild": "^0.25.0", + "prettier": "^3.3.3", + "typescript": "^5.6.2" + }, + "engines": { + "node": ">=20.11" + }, + "exports": { + "./package.json": "./package.json", + ".": { + "types": "./out/index.d.ts", + "import": "./index.js" + }, + "./client": { + "types": "./out/client/index.d.ts", + "import": "./client/index.js" + }, + "./plugin": { + "types": "./out/plugin/index.d.ts", + "import": "./plugin/index.js" + } + }, + "files": [ + "./index.js", + "client/**/*", + "plugin/**/*", + "out/**/*" + ], + "license": "MIT", + "main": "index.js", + "peerDependencies": { + "esbuild": "^0.25.0" + }, + "prettier": "@goauthentik/prettier-config", + "private": true, + "publishConfig": { + "access": "public" + }, + "type": "module", + "types": "./out/index.d.ts" +} diff --git a/web/packages/esbuild-plugin-live-reload/plugin/index.js b/web/packages/esbuild-plugin-live-reload/plugin/index.js new file mode 100644 index 0000000000..d69c75645e --- /dev/null +++ b/web/packages/esbuild-plugin-live-reload/plugin/index.js @@ -0,0 +1,243 @@ +/** + * @file Live reload plugin for ESBuild. + * + * @import { ListenOptions } from "node:net"; + * @import {Server as HTTPServer} from "node:http"; + * @import {Server as HTTPSServer} from "node:https"; + */ +import { findFreePorts } from "find-free-ports"; +import * as http from "node:http"; +import * as path from "node:path"; + +/** + * Serializes a custom event to a text stream. + * @param {Event} event + * @returns {string} + */ +export function serializeCustomEventToStream(event) { + // @ts-expect-error - TS doesn't know about the detail property + const data = event.detail ?? {}; + + const eventContent = [`event: ${event.type}`, `data: ${JSON.stringify(data)}`]; + + return eventContent.join("\n") + "\n\n"; +} + +const MIN_PORT = 1025; +const MAX_PORT = 65535; + +/** + * Find a random port that is not in use, sufficiently far from the default port. + * @returns {Promise} + */ +async function findDisparatePort() { + const startPort = Math.floor(Math.random() * (MAX_PORT - MIN_PORT + 1)) + MIN_PORT; + + const wathcherPorts = await findFreePorts(1, { + startPort, + }); + + const [port] = wathcherPorts; + + if (!port) { + throw new Error("No free ports available"); + } + + return port; +} + +/** + * Event server initialization options. + * + * @typedef {Object} EventServerInit + * + * @property {string} pathname + * @property {EventTarget} dispatcher + * @property {string} [logPrefix] + */ + +/** + * @typedef {(req: http.IncomingMessage, res: http.ServerResponse) => void} RequestHandler + */ + +/** + * Create an event request handler. + * @param {EventServerInit} options + * @returns {RequestHandler} + * @category ESBuild + */ +export function createRequestHandler({ pathname, dispatcher, logPrefix = "Build Observer" }) { + // eslint-disable-next-line no-console + const log = console.log.bind(console, `[${logPrefix}]`); + + /** + * @type {RequestHandler} + */ + const requestHandler = (req, res) => { + res.setHeader("Access-Control-Allow-Origin", "*"); + res.setHeader("Access-Control-Allow-Methods", "GET"); + res.setHeader("Access-Control-Allow-Headers", "Content-Type"); + + if (req.url !== pathname) { + log(`🚫 Invalid request to ${req.url}`); + res.writeHead(404); + res.end(); + return; + } + + log("🔌 Client connected"); + + res.writeHead(200, { + "Content-Type": "text/event-stream", + "Cache-Control": "no-cache", + "Connection": "keep-alive", + }); + + /** + * @param {Event} event + */ + const listener = (event) => { + const body = serializeCustomEventToStream(event); + + res.write(body); + }; + + dispatcher.addEventListener("esbuild:start", listener); + dispatcher.addEventListener("esbuild:error", listener); + dispatcher.addEventListener("esbuild:end", listener); + + req.on("close", () => { + log("🔌 Client disconnected"); + + clearInterval(keepAliveInterval); + + dispatcher.removeEventListener("esbuild:start", listener); + dispatcher.removeEventListener("esbuild:error", listener); + dispatcher.removeEventListener("esbuild:end", listener); + }); + + const keepAliveInterval = setInterval(() => { + console.timeStamp("🏓 Keep-alive"); + + res.write("event: keep-alive\n\n"); + res.write(serializeCustomEventToStream(new CustomEvent("esbuild:keep-alive"))); + }, 15_000); + }; + + return requestHandler; +} + +/** + * Options for the build observer plugin. + * + * @typedef {object} BuildObserverOptions + * + * @property {HTTPServer | HTTPSServer} [server] + * @property {ListenOptions} [listenOptions] + * @property {string | URL} [publicURL] + * @property {string} [logPrefix] + * @property {string} [relativeRoot] + */ + +/** + * Creates a plugin that listens for build events and sends them to a server-sent event stream. + * + * @param {BuildObserverOptions} [options] + * @returns {import('esbuild').Plugin} + */ +export function liveReloadPlugin(options = {}) { + return { + name: "build-watcher", + setup: async (build) => { + const logPrefix = options.logPrefix || "Build Observer"; + + const timerLabel = `[${logPrefix}] 🏁`; + const relativeRoot = options.relativeRoot || process.cwd(); + + const dispatcher = new EventTarget(); + + /** + * @type {URL} + */ + let publicURL; + + if (!options.publicURL) { + const port = await findDisparatePort(); + + publicURL = new URL(`http://localhost:${port}/events`); + } else { + publicURL = + typeof options.publicURL === "string" + ? new URL(options.publicURL) + : options.publicURL; + } + + build.initialOptions.define = { + ...build.initialOptions.define, + "import.meta.env.ESBUILD_WATCHER_URL": JSON.stringify(publicURL.href), + }; + + const requestHandler = createRequestHandler({ + pathname: publicURL.pathname, + dispatcher, + logPrefix, + }); + + const server = options.server || http.createServer(requestHandler); + + const listenOptions = options.listenOptions || { + port: parseInt(publicURL.port, 10), + host: publicURL.hostname, + }; + + server.listen(listenOptions, () => { + // eslint-disable-next-line no-console + console.log(`[${logPrefix}] Listening`); + }); + + build.onDispose(() => { + server?.close(); + }); + + build.onStart(() => { + console.time(timerLabel); + + dispatcher.dispatchEvent( + new CustomEvent("esbuild:start", { + detail: new Date().toISOString(), + }), + ); + }); + + build.onEnd((buildResult) => { + console.timeEnd(timerLabel); + + if (!buildResult.errors.length) { + dispatcher.dispatchEvent( + new CustomEvent("esbuild:end", { + detail: new Date().toISOString(), + }), + ); + + return; + } + + console.warn(`Build ended with ${buildResult.errors.length} errors`); + + dispatcher.dispatchEvent( + new CustomEvent("esbuild:error", { + detail: buildResult.errors.map((error) => ({ + ...error, + location: error.location + ? { + ...error.location, + file: path.resolve(relativeRoot, error.location.file), + } + : null, + })), + }), + ); + }); + }, + }; +} diff --git a/web/packages/esbuild-plugin-live-reload/tsconfig.json b/web/packages/esbuild-plugin-live-reload/tsconfig.json new file mode 100644 index 0000000000..a3d5376967 --- /dev/null +++ b/web/packages/esbuild-plugin-live-reload/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@goauthentik/tsconfig", + "compilerOptions": { + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "resolveJsonModule": true, + "baseUrl": ".", + "checkJs": true, + "emitDeclarationOnly": true + } +} diff --git a/web/scripts/build-web.mjs b/web/scripts/build-web.mjs index b75e46d30f..07a14e246a 100644 --- a/web/scripts/build-web.mjs +++ b/web/scripts/build-web.mjs @@ -1,8 +1,13 @@ +/** + * @file ESBuild script for building the authentik web UI. + * + * @import { BuildOptions } from "esbuild"; + */ +import { liveReloadPlugin } from "@goauthentik/esbuild-plugin-live-reload/plugin"; import { execFileSync } from "child_process"; import { deepmerge } from "deepmerge-ts"; import esbuild from "esbuild"; import { polyfillNode } from "esbuild-plugin-polyfill-node"; -import findFreePorts from "find-free-ports"; import { copyFileSync, mkdirSync, readFileSync, statSync } from "fs"; import { globSync } from "glob"; import * as path from "path"; @@ -11,7 +16,6 @@ import process from "process"; import { fileURLToPath } from "url"; import { mdxPlugin } from "./esbuild/build-mdx-plugin.mjs"; -import { buildObserverPlugin } from "./esbuild/build-observer-plugin.mjs"; const __dirname = fileURLToPath(new URL(".", import.meta.url)); let authentikProjectRoot = path.join(__dirname, "..", ".."); @@ -120,7 +124,7 @@ const BASE_ESBUILD_OPTIONS = { splitting: true, treeShaking: true, external: ["*.woff", "*.woff2"], - tsconfig: "./tsconfig.json", + tsconfig: path.resolve(__dirname, "..", "tsconfig.build.json"), loader: { ".css": "text", }, @@ -220,26 +224,17 @@ function doHelp() { async function doWatch() { console.log("Watching all entry points..."); - const wathcherPorts = await findFreePorts(entryPoints.length); - const buildContexts = await Promise.all( - entryPoints.map((entryPoint, i) => { - const port = wathcherPorts[i]; - const serverURL = new URL(`http://localhost:${port}/events`); - + entryPoints.map((entryPoint) => { return esbuild.context( createEntryPointOptions(entryPoint, { + define: definitions, plugins: [ - buildObserverPlugin({ - serverURL, - logPrefix: entryPoint[1], + liveReloadPlugin({ + logPrefix: `Build Observer (${entryPoint[1]})`, relativeRoot: path.join(__dirname, ".."), }), ], - define: { - ...definitions, - "process.env.WATCHER_URL": JSON.stringify(serverURL.toString()), - }, }), ); }), diff --git a/web/scripts/esbuild/build-observer-plugin.mjs b/web/scripts/esbuild/build-observer-plugin.mjs deleted file mode 100644 index c7a0c7e317..0000000000 --- a/web/scripts/esbuild/build-observer-plugin.mjs +++ /dev/null @@ -1,141 +0,0 @@ -import * as http from "http"; -import path from "path"; - -/** - * Serializes a custom event to a text stream. - * a - * @param {Event} event - * @returns {string} - */ -export function serializeCustomEventToStream(event) { - // @ts-expect-error - TS doesn't know about the detail property - const data = event.detail ?? {}; - - const eventContent = [`event: ${event.type}`, `data: ${JSON.stringify(data)}`]; - - return eventContent.join("\n") + "\n\n"; -} - -/** - * Options for the build observer plugin. - * - * @typedef {Object} BuildObserverOptions - * - * @property {URL} serverURL - * @property {string} logPrefix - * @property {string} relativeRoot - */ - -/** - * Creates a plugin that listens for build events and sends them to a server-sent event stream. - * - * @param {BuildObserverOptions} options - * @returns {import('esbuild').Plugin} - */ -export function buildObserverPlugin({ serverURL, logPrefix, relativeRoot }) { - const timerLabel = `[${logPrefix}] Build`; - const endpoint = serverURL.pathname; - const dispatcher = new EventTarget(); - - const eventServer = http.createServer((req, res) => { - res.setHeader("Access-Control-Allow-Origin", "*"); - res.setHeader("Access-Control-Allow-Methods", "GET"); - res.setHeader("Access-Control-Allow-Headers", "Content-Type"); - - if (req.url !== endpoint) { - console.log(`🚫 Invalid request to ${req.url}`); - res.writeHead(404); - res.end(); - return; - } - - console.log("🔌 Client connected"); - - res.writeHead(200, { - "Content-Type": "text/event-stream", - "Cache-Control": "no-cache", - "Connection": "keep-alive", - }); - - /** - * @param {Event} event - */ - const listener = (event) => { - const body = serializeCustomEventToStream(event); - - res.write(body); - }; - - dispatcher.addEventListener("esbuild:start", listener); - dispatcher.addEventListener("esbuild:error", listener); - dispatcher.addEventListener("esbuild:end", listener); - - req.on("close", () => { - console.log("🔌 Client disconnected"); - - clearInterval(keepAliveInterval); - - dispatcher.removeEventListener("esbuild:start", listener); - dispatcher.removeEventListener("esbuild:error", listener); - dispatcher.removeEventListener("esbuild:end", listener); - }); - - const keepAliveInterval = setInterval(() => { - console.timeStamp("🏓 Keep-alive"); - - res.write("event: keep-alive\n\n"); - res.write(serializeCustomEventToStream(new CustomEvent("esbuild:keep-alive"))); - }, 15_000); - }); - - return { - name: "build-watcher", - setup: (build) => { - eventServer.listen(parseInt(serverURL.port, 10), serverURL.hostname); - - build.onDispose(() => { - eventServer.close(); - }); - - build.onStart(() => { - console.time(timerLabel); - - dispatcher.dispatchEvent( - new CustomEvent("esbuild:start", { - detail: new Date().toISOString(), - }), - ); - }); - - build.onEnd((buildResult) => { - console.timeEnd(timerLabel); - - if (!buildResult.errors.length) { - dispatcher.dispatchEvent( - new CustomEvent("esbuild:end", { - detail: new Date().toISOString(), - }), - ); - - return; - } - - console.warn(`Build ended with ${buildResult.errors.length} errors`); - - dispatcher.dispatchEvent( - new CustomEvent("esbuild:error", { - detail: buildResult.errors.map((error) => ({ - ...error, - location: error.location - ? { - ...error.location, - file: path.resolve(relativeRoot, error.location.file), - } - : null, - })), - }), - ); - }); - }, - }; -} diff --git a/web/src/admin/AdminInterface/AdminInterface.ts b/web/src/admin/AdminInterface/AdminInterface.ts index 04c633c81a..dda28c5a37 100644 --- a/web/src/admin/AdminInterface/AdminInterface.ts +++ b/web/src/admin/AdminInterface/AdminInterface.ts @@ -34,6 +34,10 @@ import { SessionUser, UiThemeEnum } from "@goauthentik/api"; import "./AdminSidebar"; +if (process.env.NODE_ENV === "development") { + await import("@goauthentik/esbuild-plugin-live-reload/client"); +} + @customElement("ak-interface-admin") export class AdminInterface extends AuthenticatedInterface { @property({ type: Boolean }) @@ -119,16 +123,6 @@ export class AdminInterface extends AuthenticatedInterface { } } - async connectedCallback(): Promise { - super.connectedCallback(); - - if (process.env.NODE_ENV === "development" && process.env.WATCHER_URL) { - const { ESBuildObserver } = await import("@goauthentik/common/client"); - - new ESBuildObserver(process.env.WATCHER_URL); - } - } - render(): TemplateResult { const sidebarClasses = { "pf-m-light": this.activeTheme === UiThemeEnum.Light, diff --git a/web/src/admin/applications/wizard/steps/SubmitStepOverviewRenderers.ts b/web/src/admin/applications/wizard/steps/SubmitStepOverviewRenderers.ts index 934d92c9ac..f519034b7a 100644 --- a/web/src/admin/applications/wizard/steps/SubmitStepOverviewRenderers.ts +++ b/web/src/admin/applications/wizard/steps/SubmitStepOverviewRenderers.ts @@ -52,7 +52,6 @@ function renderRadiusOverview(rawProvider: OneOfProvider) { } function renderRACOverview(rawProvider: OneOfProvider) { - // @ts-expect-error TS6133 const _provider = rawProvider as RACProvider; } diff --git a/web/src/common/purify.ts b/web/src/common/purify.ts index 38f13f635b..5da9810c8a 100644 --- a/web/src/common/purify.ts +++ b/web/src/common/purify.ts @@ -1,3 +1,4 @@ +import type { Config as DOMPurifyConfig } from "dompurify"; import DOMPurify from "dompurify"; import { render } from "@lit-labs/ssr"; @@ -6,9 +7,9 @@ import { TemplateResult, html } from "lit"; import { unsafeHTML } from "lit/directives/unsafe-html.js"; import { until } from "lit/directives/until.js"; -export const DOM_PURIFY_STRICT: DOMPurify.Config = { +export const DOM_PURIFY_STRICT = { ALLOWED_TAGS: ["#text"], -}; +} as const satisfies DOMPurifyConfig; export async function renderStatic(input: TemplateResult): Promise { return await collectResult(render(input)); diff --git a/web/src/elements/Interface/versionProvider.ts b/web/src/elements/Interface/versionProvider.ts index b8dc5dade9..913b6dd699 100644 --- a/web/src/elements/Interface/versionProvider.ts +++ b/web/src/elements/Interface/versionProvider.ts @@ -1,7 +1,7 @@ import { authentikVersionContext } from "@goauthentik/elements/AuthentikContexts"; import { consume } from "@lit/context"; -import { Constructor } from "@lit/reactive-element/decorators/base"; +import { Constructor } from "@lit/reactive-element/decorators/base.js"; import type { LitElement } from "lit"; import type { Version } from "@goauthentik/api"; diff --git a/web/src/elements/ak-checkbox-group/ak-checkbox-group.ts b/web/src/elements/ak-checkbox-group/ak-checkbox-group.ts index 6b4af8fb5f..ca8712fc73 100644 --- a/web/src/elements/ak-checkbox-group/ak-checkbox-group.ts +++ b/web/src/elements/ak-checkbox-group/ak-checkbox-group.ts @@ -2,7 +2,7 @@ import { AkControlElement } from "@goauthentik/elements/AkControlElement"; import { CustomEmitterElement } from "@goauthentik/elements/utils/eventEmitter"; import { msg } from "@lit/localize"; -import { PropertyValues } from "@lit/reactive-element/reactive-element"; +import { PropertyValues } from "@lit/reactive-element"; import { TemplateResult, css, html } from "lit"; import { customElement, property, queryAll, state } from "lit/decorators.js"; import { map } from "lit/directives/map.js"; diff --git a/web/src/flow/FlowInterface.ts b/web/src/flow/FlowInterface.ts index 994032501e..9f5cfff49c 100644 --- a/web/src/flow/FlowInterface.ts +++ b/web/src/flow/FlowInterface.ts @@ -14,8 +14,6 @@ import "@goauthentik/flow/stages/password/PasswordStage"; // end of stage import -if (process.env.NODE_ENV === "development" && process.env.WATCHER_URL) { - const { ESBuildObserver } = await import("@goauthentik/common/client"); - - new ESBuildObserver(process.env.WATCHER_URL); +if (process.env.NODE_ENV === "development") { + await import("@goauthentik/esbuild-plugin-live-reload/client"); } diff --git a/web/src/user/UserInterface.ts b/web/src/user/UserInterface.ts index d418a6ace9..c710a0cdcb 100644 --- a/web/src/user/UserInterface.ts +++ b/web/src/user/UserInterface.ts @@ -43,6 +43,10 @@ import PFDisplay from "@patternfly/patternfly/utilities/Display/display.css"; import { CurrentBrand, EventsApi, SessionUser } from "@goauthentik/api"; +if (process.env.NODE_ENV === "development") { + await import("@goauthentik/esbuild-plugin-live-reload/client"); +} + const customStyles = css` .pf-c-page__main, .pf-c-drawer__content, @@ -291,12 +295,6 @@ export class UserInterface extends AuthenticatedInterface { window.addEventListener(EVENT_NOTIFICATION_DRAWER_TOGGLE, this.toggleNotificationDrawer); window.addEventListener(EVENT_API_DRAWER_TOGGLE, this.toggleApiDrawer); window.addEventListener(EVENT_WS_MESSAGE, this.fetchConfigurationDetails); - - if (process.env.NODE_ENV === "development" && process.env.WATCHER_URL) { - const { ESBuildObserver } = await import("@goauthentik/common/client"); - - new ESBuildObserver(process.env.WATCHER_URL); - } } disconnectedCallback() { diff --git a/web/tsconfig.base.json b/web/tsconfig.base.json deleted file mode 100644 index 31d05ab479..0000000000 --- a/web/tsconfig.base.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "compilerOptions": { - "strict": true, - "baseUrl": ".", - "esModuleInterop": true, - "paths": { - "@goauthentik/docs/*": ["../website/docs/*"] - }, - "types": [ - "node", - "@wdio/mocha-framework", - "@wdio/types", - "expect-webdriverio", - "grecaptcha" - ], - "jsx": "react-jsx", - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "experimentalDecorators": true, - "sourceMap": true, - "target": "esnext", - "module": "esnext", - "moduleResolution": "node", - "lib": [ - "ES5", - "ES2015", - "ES2016", - "ES2017", - "ES2018", - "ES2019", - "ES2020", - "ESNext", - "DOM", - "DOM.Iterable", - "WebWorker" - ], - "noUnusedLocals": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "strictBindCallApply": true, - "strictFunctionTypes": true, - "strictNullChecks": true, - "allowUnreachableCode": false, - "allowUnusedLabels": false, - "useDefineForClassFields": false, - "useUnknownInCatchVariables": true, - "alwaysStrict": true, - "noImplicitAny": true, - "plugins": [ - { - "name": "ts-lit-plugin", - "strict": true, - "rules": { - "no-unknown-tag-name": "off", - "no-missing-import": "off", - "no-incompatible-type-binding": "off", - "no-unknown-property": "off", - "no-unknown-attribute": "off" - } - }, - { - "name": "@genesiscommunitysuccess/custom-elements-lsp", - "designSystemPrefix": "ak-", - "parser": { - "timeout": 2000 - } - } - ] - }, - "exclude": ["src/**/*.test.ts", "./tests"] -} diff --git a/web/tsconfig.build.json b/web/tsconfig.build.json new file mode 100644 index 0000000000..26422e5959 --- /dev/null +++ b/web/tsconfig.build.json @@ -0,0 +1,6 @@ +// @file TSConfig used by the web package during build. + +{ + "extends": "./tsconfig.json", + "exclude": ["src/**/*.test.ts", "./tests"] +} diff --git a/web/tsconfig.json b/web/tsconfig.json index 333347a361..3ec01581d7 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -1,7 +1,19 @@ +// @file TSConfig used by the web package during development. { - "extends": "./tsconfig.base.json", + "extends": "@goauthentik/tsconfig", "compilerOptions": { - "types": ["@wdio/types", "grecaptcha", "node", "@wdio/mocha-framework", "expect-webdriverio"], + "allowSyntheticDefaultImports": true, + "emitDeclarationOnly": true, + "experimentalDecorators": true, + // See https://lit.dev/docs/components/properties/ + "useDefineForClassFields": false, + "target": "esnext", + "module": "esnext", + "moduleResolution": "bundler", + "baseUrl": ".", + "lib": ["DOM", "DOM.Iterable", "ESNext"], + // TODO: We should enable this when when we're ready to enforce it. + "noUncheckedIndexedAccess": false, "paths": { "@goauthentik/admin/*": ["./src/admin/*"], "@goauthentik/common/*": ["./src/common/*"], @@ -13,6 +25,41 @@ "@goauthentik/polyfill/*": ["./src/polyfill/*"], "@goauthentik/standalone/*": ["./src/standalone/*"], "@goauthentik/user/*": ["./src/user/*"] - } + }, + "plugins": [ + { + "name": "ts-lit-plugin", + "strict": true, + "rules": { + "no-unknown-tag-name": "off", + "no-missing-import": "off", + "no-incompatible-type-binding": "off", + "no-unknown-property": "off", + "no-unknown-attribute": "off" + } + }, + { + "name": "@genesiscommunitysuccess/custom-elements-lsp", + "designSystemPrefix": "ak-", + "parser": { + "timeout": 2000 + } + } + ] }, + "exclude": [ + // --- + "./out/**/*", + "./dist/**/*", + "src/**/*.test.ts", + "./tests", + + // TODO: Remove after monorepo cleanup. + "src/**/*.comp.ts" + ], + "references": [ + { + "path": "./packages/esbuild-plugin-live-reload" + } + ], } diff --git a/web/tsconfig.test.json b/web/tsconfig.test.json index f93c6adf05..8ded1a98d4 100644 --- a/web/tsconfig.test.json +++ b/web/tsconfig.test.json @@ -1,3 +1,4 @@ +// @file TSConfig used during tests. { "compilerOptions": { "baseUrl": ".", diff --git a/web/types/global.d.ts b/web/types/global.d.ts new file mode 100644 index 0000000000..5edb41ecd5 --- /dev/null +++ b/web/types/global.d.ts @@ -0,0 +1,26 @@ +/** + * @file Environment variables available via ESBuild. + */ + +declare module "process" { + global { + namespace NodeJS { + interface ProcessEnv { + NODE_ENV: "production" | "development"; + /** + * + * @todo Determine where this is used and if it is needed, + * give it a better name. + * @deprecated + */ + CWD: string; + /** + * @todo Determine where this is used and if it is needed, + * give it a better name. + * @deprecated + */ + AK_API_BASE_PATH: string; + } + } + } +} diff --git a/web/wdio.conf.ts b/web/wdio.conf.ts index 8767a207f7..8b41fdcd79 100644 --- a/web/wdio.conf.ts +++ b/web/wdio.conf.ts @@ -336,6 +336,7 @@ export const config: Options.Testrunner = { { error: _error, result: _result, duration: _duration, passed: _passed, retries: _retries }, ) { if (lemmeSee) { + // @ts-expect-error TODO await browser.pause(500); } },