From 662b85bbe41ffa4cadcae47ef81fe0385c3bbae1 Mon Sep 17 00:00:00 2001
From: Christoph Zwerschke
Date: Fri, 29 Nov 2024 12:23:35 +0100
Subject: [PATCH] Add authentication (#17)
---
.devcontainer/create_cert | 3 +-
.devcontainer/data-portal.yaml | 4 +
.devcontainer/dev_install | 2 +-
.devcontainer/devcontainer.json | 10 +-
.prettierrc | 3 +-
.vscode/settings.json | 9 +-
Dockerfile | 5 +-
README.md | 8 +
data-portal.default.yaml | 10 +
eslint.config.js | 16 +-
package.json | 44 +-
pnpm-lock.yaml | 1132 ++++++++++-------
src/app/app.component.html | 1 +
src/app/app.component.ts | 8 +-
src/app/app.config.ts | 16 +-
src/app/app.routes.ts | 32 +
.../confirm-totp/confirm-totp.component.html | 22 +
.../confirm-totp.component.spec.ts | 22 +
.../confirm-totp/confirm-totp.component.ts | 72 ++
.../features/register/register.component.html | 66 +
.../features/register/register.component.scss | 5 +
.../register/register.component.spec.ts | 22 +
.../features/register/register.component.ts | 81 ++
.../setup-totp/setup-totp.component.html | 61 +
.../setup-totp/setup-totp.component.spec.ts | 22 +
.../setup-totp/setup-totp.component.ts | 82 ++
src/app/auth/models/user.ts | 54 +
src/app/auth/services/auth.service.spec.ts | 16 +
src/app/auth/services/auth.service.ts | 459 +++++++
src/app/auth/services/csrf.service.ts | 46 +
.../home-page/home-page.component.html | 4 -
.../features/home-page/home-page.component.ts | 9 +-
.../show-session/show-session.component.html | 5 +
.../show-session.component.spec.ts | 22 +
.../show-session/show-session.component.ts | 19 +
.../site-header/site-header.component.html | 12 +-
.../site-header/site-header.component.ts | 26 +-
src/app/shared/services/config.service.ts | 124 +-
tsconfig.json | 3 +-
39 files changed, 2031 insertions(+), 526 deletions(-)
create mode 100644 src/app/auth/features/confirm-totp/confirm-totp.component.html
create mode 100644 src/app/auth/features/confirm-totp/confirm-totp.component.spec.ts
create mode 100644 src/app/auth/features/confirm-totp/confirm-totp.component.ts
create mode 100644 src/app/auth/features/register/register.component.html
create mode 100644 src/app/auth/features/register/register.component.scss
create mode 100644 src/app/auth/features/register/register.component.spec.ts
create mode 100644 src/app/auth/features/register/register.component.ts
create mode 100644 src/app/auth/features/setup-totp/setup-totp.component.html
create mode 100644 src/app/auth/features/setup-totp/setup-totp.component.spec.ts
create mode 100644 src/app/auth/features/setup-totp/setup-totp.component.ts
create mode 100644 src/app/auth/models/user.ts
create mode 100644 src/app/auth/services/auth.service.spec.ts
create mode 100644 src/app/auth/services/auth.service.ts
create mode 100644 src/app/auth/services/csrf.service.ts
create mode 100644 src/app/portal/features/show-session/show-session.component.html
create mode 100644 src/app/portal/features/show-session/show-session.component.spec.ts
create mode 100644 src/app/portal/features/show-session/show-session.component.ts
diff --git a/.devcontainer/create_cert b/.devcontainer/create_cert
index 8ee607f..dba0dac 100755
--- a/.devcontainer/create_cert
+++ b/.devcontainer/create_cert
@@ -2,7 +2,8 @@
# create self-signed certificate for testing with the browser
-HOST=data.staging.ghga.dev
+BASE_URL=${BASE_URL:-https://data.staging.ghga.dev}
+HOST=${BASE_URL#https://}
CERTFILE=cert.pem
KEYFILE=key.pem
diff --git a/.devcontainer/data-portal.yaml b/.devcontainer/data-portal.yaml
index 5139827..4fe7b96 100644
--- a/.devcontainer/data-portal.yaml
+++ b/.devcontainer/data-portal.yaml
@@ -11,5 +11,9 @@ log_level: DEBUG
base_url: http://127.0.0.1:8080
+auth_url: /api/auth
mass_url: /api/mass
metldata_url: /api/metldata
+
+oidc_client_id: ghga-dev-client
+oidc_authority_url: https://login.aai.lifescience-ri.eu/oidc/
diff --git a/.devcontainer/dev_install b/.devcontainer/dev_install
index 6f716f5..130549e 100755
--- a/.devcontainer/dev_install
+++ b/.devcontainer/dev_install
@@ -3,7 +3,7 @@
cd /workspace
-corepack prepare pnpm@9.13.2 --activate
+corepack prepare pnpm@9.14.2 --activate
echo "Updating pnpm..."
npm install -g pnpm
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index f1e146b..42972fc 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -8,7 +8,10 @@
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
- "forwardPorts": [8080, 443],
+ "forwardPorts": [
+ 8080,
+ 443
+ ],
// Create an empty local env file if it does not yet exist
"initializeCommand": "touch .devcontainer/local.env",
// Use 'postCreateCommand' to run commands after the container is created.
@@ -29,7 +32,10 @@
},
"editor.formatOnSave": true,
"editor.renderWhitespace": "all",
- "editor.rulers": [88, 120],
+ "editor.rulers": [
+ 88,
+ 120
+ ],
"editor.defaultFormatter": "vscode.typescript-language-features"
},
// Add the IDs of extensions you want installed when the container is created.
diff --git a/.prettierrc b/.prettierrc
index df55829..917cd5d 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -4,5 +4,6 @@
"useTabs": false,
"singleQuote": true,
"printWidth": 88,
- "proseWrap": "preserve"
+ "proseWrap": "preserve",
+ "endOfLine": "lf"
}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 9ace906..4f1750a 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,8 +1,11 @@
{
"window.title": "Data Portal - ${dirty}${activeEditorShort}${separator}${rootName}${separator}${profileName}${separator}${appName}",
- "cSpell.words": ["devcontainer", "devkit", "metldata"],
+ "cSpell.words": ["devcontainer", "devkit", "metldata", "TOTP"],
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
+ "[html]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
@@ -18,5 +21,7 @@
"eslint.options": {
"overrideConfigFile": "/workspace/eslint.config.js"
},
- "remote.localPortHost": "allInterfaces"
+ "remote.localPortHost": "allInterfaces",
+ "files.insertFinalNewline": true,
+ "files.trimFinalNewlines": true
}
diff --git a/Dockerfile b/Dockerfile
index 3bb2f04..6831af0 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -5,7 +5,7 @@ RUN apk upgrade --no-cache --available
# BUILDER: a container to build the service dist directory
FROM base AS builder
# install pnpm
-RUN corepack prepare pnpm@9.13.2 --activate
+RUN corepack prepare pnpm@9.14.2 --activate
RUN npm install -g pnpm
# install static web server
RUN apk add curl sudo which
@@ -28,8 +28,7 @@ COPY --from=builder /service/dist/data-portal/browser ./dist
COPY --from=builder /usr/local/bin/static-web-server /usr/local/bin
# make the config file writeable to the appuser
USER root
-RUN touch ./dist/config.js
-RUN chown appuser ./dist/config.js
+RUN touch ./dist/config.js && chown appuser ./dist/config.js
USER appuser
# install run script
COPY ./run.js ./run.mjs
diff --git a/README.md b/README.md
index 3ccf9d7..7bc016c 100644
--- a/README.md
+++ b/README.md
@@ -30,6 +30,14 @@ If the staging backend requires an additional Basic authentication, you can set
dev_launcher staging username:password
```
+In order to make the OIDC and basic authentication work, you also need to add a `.devcontainer/local.env` file like this, with the proper credentials:
+
+```env
+data_portal_base_url=https://data.staging.ghga.dev
+data_portal_basic_auth=USERNAME:PASSWORD
+data_portal_oidc_client_id=OIDC_DEV_CLIENT_ID
+```
+
## Code scaffolding
Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
diff --git a/data-portal.default.yaml b/data-portal.default.yaml
index d9a7ed0..19ec6fe 100644
--- a/data-portal.default.yaml
+++ b/data-portal.default.yaml
@@ -13,5 +13,15 @@ log_level: INFO
base_url: http://127.0.0.1:8080
+auth_url: /api/auth
mass_url: /api/mass
metldata_url: /api/metldata
+
+oidc_client_id: ghga-client
+oidc_redirect_url: oauth/callback
+oidc_scope: 'openid profile email'
+oidc_authority_url: https://login.aai.lifescience-ri.eu/oidc/
+oidc_authorization_url: authorize
+oidc_token_url: token
+oidc_userinfo_url: userinfo
+oidc_use_discovery: true
diff --git a/eslint.config.js b/eslint.config.js
index 1dc2511..cd2bef4 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -131,21 +131,17 @@ export default [
{
from: ['config'],
disallow: ['*'],
- message: 'Config modules can only import modules with routes',
+ message: 'Config modules can only import routes and auth services',
},
{
from: ['config'],
- allow: ['routes'],
+ allow: ['routes', ['service', { context: 'auth' }]],
},
- // modules for routes may only import feature components
+ // modules for routes may not import ui components
{
from: ['routes'],
- disallow: ['*'],
- message: 'Modules for routes can only import feature components',
- },
- {
- from: ['routes'],
- allow: ['features'],
+ disallow: ['ui'],
+ message: 'Modules for routes cannot import ui components',
},
// unit tests are currently exempt from all rules
{
@@ -180,7 +176,7 @@ export default [
},
// Auth service may be imported in other contexts
{
- from: ['features', 'service'],
+ from: ['features', 'service', 'routes'],
allow: [['service', { context: 'auth' }]],
},
// Auth models may be imported in other contexts
diff --git a/package.json b/package.json
index e8f1829..9c9e2ad 100644
--- a/package.json
+++ b/package.json
@@ -20,38 +20,40 @@
"type": "module",
"private": true,
"dependencies": {
- "@angular-eslint/eslint-plugin": "^18.4.1",
- "@angular-eslint/template-parser": "^18.4.1",
- "@angular/animations": "19.0.0-rc.3",
- "@angular/cdk": "19.0.0-rc.3",
- "@angular/common": "19.0.0-rc.3",
- "@angular/compiler": "19.0.0-rc.3",
- "@angular/core": "19.0.0-rc.3",
- "@angular/forms": "19.0.0-rc.3",
- "@angular/material": "19.0.0-rc.3",
- "@angular/platform-browser": "19.0.0-rc.3",
- "@angular/platform-browser-dynamic": "19.0.0-rc.3",
- "@angular/router": "19.0.0-rc.3",
+ "@angular-eslint/eslint-plugin": "^18.4.2",
+ "@angular-eslint/template-parser": "^18.4.2",
+ "@angular/animations": "^19.0.1",
+ "@angular/cdk": "^19.0.1",
+ "@angular/common": "^19.0.1",
+ "@angular/compiler": "^19.0.1",
+ "@angular/core": "^19.0.1",
+ "@angular/forms": "^19.0.1",
+ "@angular/material": "^19.0.1",
+ "@angular/platform-browser": "^19.0.1",
+ "@angular/platform-browser-dynamic": "^19.0.1",
+ "@angular/router": "^19.0.1",
+ "angularx-qrcode": "^19.0.0",
"js-yaml": "^4.1.0",
+ "oidc-client-ts": "^3.1.0",
"rxjs": "~7.8.1",
"tslib": "^2.8.1"
},
"devDependencies": {
- "@angular-devkit/build-angular": "19.0.0-rc.3",
- "@angular/cli": "19.0.0-rc.3",
- "@angular/compiler-cli": "19.0.0-rc.3",
+ "@angular-devkit/build-angular": "^19.0.2",
+ "@angular/cli": "^19.0.2",
+ "@angular/compiler-cli": "^19.0.1",
"@compodoc/compodoc": "^1.1.26",
"@eslint/markdown": "^6.2.1",
"@types/jasmine": "~5.1.4",
- "@typescript-eslint/eslint-plugin": "^8.15.0",
- "@typescript-eslint/parser": "^8.15.0",
- "angular-eslint": "^18.4.1",
+ "@typescript-eslint/eslint-plugin": "^8.16.0",
+ "@typescript-eslint/parser": "^8.16.0",
+ "angular-eslint": "19.0.0-alpha.4",
"autoprefixer": "^10.4.20",
"eslint": "^9.15.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-boundaries": "^5.0.1",
- "eslint-plugin-jsdoc": "^50.5.0",
+ "eslint-plugin-jsdoc": "^50.6.0",
"eslint-plugin-prettier": "^5.2.1",
"husky": "^9.1.7",
"jasmine-core": "~5.4.0",
@@ -62,9 +64,9 @@
"karma-jasmine-html-reporter": "~2.1.0",
"postcss": "^8.4.49",
"prettier": "3.3.3",
- "prettier-plugin-tailwindcss": "^0.6.8",
+ "prettier-plugin-tailwindcss": "^0.6.9",
"tailwindcss": "^3.4.15",
"typescript": "~5.6.3",
- "typescript-eslint": "^8.15.0"
+ "typescript-eslint": "^8.16.0"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1c72984..b202213 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -9,44 +9,50 @@ importers:
.:
dependencies:
'@angular-eslint/eslint-plugin':
- specifier: ^18.4.1
- version: 18.4.1(@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ specifier: ^18.4.2
+ version: 18.4.2(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
'@angular-eslint/template-parser':
- specifier: ^18.4.1
- version: 18.4.1(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ specifier: ^18.4.2
+ version: 18.4.2(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
'@angular/animations':
- specifier: 19.0.0-rc.3
- version: 19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))
+ specifier: ^19.0.1
+ version: 19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))
'@angular/cdk':
- specifier: 19.0.0-rc.3
- version: 19.0.0-rc.3(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
+ specifier: ^19.0.1
+ version: 19.0.1(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
'@angular/common':
- specifier: 19.0.0-rc.3
- version: 19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
+ specifier: ^19.0.1
+ version: 19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
'@angular/compiler':
- specifier: 19.0.0-rc.3
- version: 19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))
+ specifier: ^19.0.1
+ version: 19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))
'@angular/core':
- specifier: 19.0.0-rc.3
- version: 19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)
+ specifier: ^19.0.1
+ version: 19.0.1(rxjs@7.8.1)(zone.js@0.15.0)
'@angular/forms':
- specifier: 19.0.0-rc.3
- version: 19.0.0-rc.3(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.0.0-rc.3(@angular/animations@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1)
+ specifier: ^19.0.1
+ version: 19.0.1(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.0.1(@angular/animations@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1)
'@angular/material':
- specifier: 19.0.0-rc.3
- version: 19.0.0-rc.3(2ggkf5bmbgan54h663qv7i4v7a)
+ specifier: ^19.0.1
+ version: 19.0.1(caeb6eiffeog75fr4ymtnaa34q)
'@angular/platform-browser':
- specifier: 19.0.0-rc.3
- version: 19.0.0-rc.3(@angular/animations@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))
+ specifier: ^19.0.1
+ version: 19.0.1(@angular/animations@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))
'@angular/platform-browser-dynamic':
- specifier: 19.0.0-rc.3
- version: 19.0.0-rc.3(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.0.0-rc.3(@angular/animations@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))
+ specifier: ^19.0.1
+ version: 19.0.1(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.0.1(@angular/animations@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))
'@angular/router':
- specifier: 19.0.0-rc.3
- version: 19.0.0-rc.3(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.0.0-rc.3(@angular/animations@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1)
+ specifier: ^19.0.1
+ version: 19.0.1(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.0.1(@angular/animations@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1)
+ angularx-qrcode:
+ specifier: ^19.0.0
+ version: 19.0.0(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))
js-yaml:
specifier: ^4.1.0
version: 4.1.0
+ oidc-client-ts:
+ specifier: ^3.1.0
+ version: 3.1.0
rxjs:
specifier: ~7.8.1
version: 7.8.1
@@ -55,14 +61,14 @@ importers:
version: 2.8.1
devDependencies:
'@angular-devkit/build-angular':
- specifier: 19.0.0-rc.3
- version: 19.0.0-rc.3(@angular/compiler-cli@19.0.0-rc.3(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3))(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@types/node@22.9.0)(chokidar@4.0.1)(karma@6.4.4)(tailwindcss@3.4.15)(typescript@5.6.3)(vite@5.4.11(@types/node@22.9.0)(less@4.2.0)(sass@1.80.7)(terser@5.36.0))
+ specifier: ^19.0.2
+ version: 19.0.2(@angular/compiler-cli@19.0.1(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3))(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@types/node@22.10.0)(chokidar@4.0.1)(karma@6.4.4)(tailwindcss@3.4.15)(typescript@5.6.3)(vite@5.4.11(@types/node@22.10.0)(less@4.2.0)(sass@1.80.7)(terser@5.36.0))
'@angular/cli':
- specifier: 19.0.0-rc.3
- version: 19.0.0-rc.3(@types/node@22.9.0)(chokidar@4.0.1)
+ specifier: ^19.0.2
+ version: 19.0.2(@types/node@22.10.0)(chokidar@4.0.1)
'@angular/compiler-cli':
- specifier: 19.0.0-rc.3
- version: 19.0.0-rc.3(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3)
+ specifier: ^19.0.1
+ version: 19.0.1(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3)
'@compodoc/compodoc':
specifier: ^1.1.26
version: 1.1.26(typescript@5.6.3)
@@ -73,14 +79,14 @@ importers:
specifier: ~5.1.4
version: 5.1.4
'@typescript-eslint/eslint-plugin':
- specifier: ^8.15.0
- version: 8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ specifier: ^8.16.0
+ version: 8.16.0(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
'@typescript-eslint/parser':
- specifier: ^8.15.0
- version: 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ specifier: ^8.16.0
+ version: 8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
angular-eslint:
- specifier: ^18.4.1
- version: 18.4.1(@angular-devkit/core@19.0.0-rc.3(chokidar@4.0.1))(@angular-devkit/schematics@19.0.0-rc.3(chokidar@4.0.1))(@typescript-eslint/types@8.15.0)(@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript-eslint@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(typescript@5.6.3)
+ specifier: 19.0.0-alpha.4
+ version: 19.0.0-alpha.4(@angular-devkit/core@19.0.2(chokidar@4.0.1))(@angular-devkit/schematics@19.0.2(chokidar@4.0.1))(@typescript-eslint/types@8.16.0)(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript-eslint@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(typescript@5.6.3)
autoprefixer:
specifier: ^10.4.20
version: 10.4.20(postcss@8.4.49)
@@ -92,13 +98,13 @@ importers:
version: 9.1.0(eslint@9.15.0(jiti@1.21.6))
eslint-import-resolver-typescript:
specifier: ^3.6.3
- version: 3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))
+ version: 3.6.3(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))
eslint-plugin-boundaries:
specifier: ^5.0.1
- version: 5.0.1(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6)))(eslint@9.15.0(jiti@1.21.6))
+ version: 5.0.1(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6)))(eslint@9.15.0(jiti@1.21.6))
eslint-plugin-jsdoc:
- specifier: ^50.5.0
- version: 50.5.0(eslint@9.15.0(jiti@1.21.6))
+ specifier: ^50.6.0
+ version: 50.6.0(eslint@9.15.0(jiti@1.21.6))
eslint-plugin-prettier:
specifier: ^5.2.1
version: 5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.15.0(jiti@1.21.6)))(eslint@9.15.0(jiti@1.21.6))(prettier@3.3.3)
@@ -130,8 +136,8 @@ importers:
specifier: 3.3.3
version: 3.3.3
prettier-plugin-tailwindcss:
- specifier: ^0.6.8
- version: 0.6.8(prettier@3.3.3)
+ specifier: ^0.6.9
+ version: 0.6.9(prettier@3.3.3)
tailwindcss:
specifier: ^3.4.15
version: 3.4.15
@@ -139,8 +145,8 @@ importers:
specifier: ~5.6.3
version: 5.6.3
typescript-eslint:
- specifier: ^8.15.0
- version: 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ specifier: ^8.16.0
+ version: 8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
packages:
@@ -155,25 +161,25 @@ packages:
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
engines: {node: '>=6.0.0'}
- '@angular-devkit/architect@0.1900.0-rc.3':
- resolution: {integrity: sha512-unCfZQ6akI8CnMN2WJgPkdXSm1z+K1iJlbzbIaoidVeuh4Yt5RiJqvarm/1rfdBhBMSvheIvycK2zPqSWBk3cA==}
+ '@angular-devkit/architect@0.1900.2':
+ resolution: {integrity: sha512-rGUgOgN/jb3Pyx3E1JsUbwQQZp4C0M/t0lwyWIFjUpndl27aBDjO2y5hzeG0B1+FgOuSNg8BPOYaEIO5vSCspw==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
- '@angular-devkit/build-angular@19.0.0-rc.3':
- resolution: {integrity: sha512-gh1OYsoChngmhBCeACRqyQw62KOvzrI68coXH80tVvUDy6v/0de87CFlbndIKt3voZyavzTi+d230QB7dl3pdw==}
+ '@angular-devkit/build-angular@19.0.2':
+ resolution: {integrity: sha512-F7wwo0fVshrlnTyBuqP6abt95soOsO+H/dYLn0JVud+SXhbSXpKDxZovlIBUKh1kj0BXny7erTYHmPWVtZpfsg==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
peerDependencies:
- '@angular/compiler-cli': ^19.0.0-next.0
- '@angular/localize': ^19.0.0-next.0
- '@angular/platform-server': ^19.0.0-next.0
- '@angular/service-worker': ^19.0.0-next.0
- '@angular/ssr': ^19.0.0-rc.3
+ '@angular/compiler-cli': ^19.0.0
+ '@angular/localize': ^19.0.0
+ '@angular/platform-server': ^19.0.0
+ '@angular/service-worker': ^19.0.0
+ '@angular/ssr': ^19.0.2
'@web/test-runner': ^0.19.0
browser-sync: ^3.0.2
jest: ^29.5.0
jest-environment-jsdom: ^29.5.0
karma: ^6.3.0
- ng-packagr: ^19.0.0-next.0
+ ng-packagr: ^19.0.0
protractor: ^7.0.0
tailwindcss: ^2.0.0 || ^3.0.0
typescript: '>=5.5 <5.7'
@@ -203,8 +209,8 @@ packages:
tailwindcss:
optional: true
- '@angular-devkit/build-webpack@0.1900.0-rc.3':
- resolution: {integrity: sha512-g9OqbmmE6nsdpfZBCGAu0u4kuIm/lpOEiKOwQKYt4gk5gCKexPAgIbnKyc04oE+ZtagHdwZflElej0qR544SMg==}
+ '@angular-devkit/build-webpack@0.1900.2':
+ resolution: {integrity: sha512-4JHkY6908YsIWh9FM/6ihsVZyWAM4/C91D8S4v/aZhVLt37HwTAxbecPbYNbexgDca81LI5TAqR8cwb0syIkWA==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
peerDependencies:
webpack: ^5.30.0
@@ -219,8 +225,8 @@ packages:
chokidar:
optional: true
- '@angular-devkit/core@19.0.0-rc.3':
- resolution: {integrity: sha512-SNtTFkGHgvOLU71cJvr1kvX02ZeLF5N8jr3oQX6ToX7wQwWorjMF7YZ0StNK2+ADYKv1OypteLfjf+K3VcUYDA==}
+ '@angular-devkit/core@19.0.2':
+ resolution: {integrity: sha512-p5pTx9rAtJUfoa7BP6R5U7dGFWHrrgpYpVyF3jwqYIu0h1C0rJIyY8q/HlkvzFxgfWag1qRf15oANq3G9fqdwg==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
peerDependencies:
chokidar: ^4.0.0
@@ -232,69 +238,92 @@ packages:
resolution: {integrity: sha512-i/h2Oji5FhJMC7wDSnIl5XUe/qym+C1ZwScaATJwDyRLCUIynZkj5rLgdG/uK6l+H0PgvxigkF+akWpokkwW6w==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
- '@angular-devkit/schematics@19.0.0-rc.3':
- resolution: {integrity: sha512-g377hBz2c/jb2xw0wD77sN6IrdTKTBhfuanT6xT27llLf0e4r7gh7DMKteUF+sigYsR6jMUCwl/+Dne6LVF3hA==}
+ '@angular-devkit/schematics@19.0.2':
+ resolution: {integrity: sha512-bwq8ReC92gGFTd2BeNBWCnOqIKu2YKNvwMVc7dl+D154WO2gzCaK2J5nL97qm5EjoUoXgvFRs84ysSAnLFzBxQ==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
- '@angular-eslint/builder@18.4.1':
- resolution: {integrity: sha512-Ofkwd9Rg52K+AgvnV1RXYXVBGJvl5jD7+4dqwoprqXG7YKNTdHy5vqNZ5XDSMb26qjoZF7JC+IKruKFaON/ZaA==}
+ '@angular-eslint/builder@19.0.0-alpha.4':
+ resolution: {integrity: sha512-iSDl0Hs2fkJJH0aR/RQ80nmickY7o1xv+mucSw/Gy4YwFDJFU0FiV++1OxhjturuEXt3k+TJ115xe4DJa86BMw==}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '*'
- '@angular-eslint/bundled-angular-compiler@18.4.1':
- resolution: {integrity: sha512-gCQC0mgBO1bwHDXL9CUgHW+Rf1XGZCLAopoXnggwxGkBCx+oww507t+jrSOxdh+4OTKU4ZfmbtWd7Y8AeXns8w==}
+ '@angular-eslint/bundled-angular-compiler@18.4.2':
+ resolution: {integrity: sha512-K7pqmZI3Dl75zlLexyaM7bw4xdgk/3bhP1B6uqDKML9+vIIvccCR2bGvqFurqeFbJlMykzb3H4jytT+HpqV4tg==}
- '@angular-eslint/eslint-plugin-template@18.4.1':
- resolution: {integrity: sha512-sofnKpi6wOZ6avVfYYqB7sCgGgWF2HgCZfW+IAp1MtVD2FBa1zTSbbfIZ1I8Akpd22UXa4LKJd0TLwm5XHHkiQ==}
+ '@angular-eslint/bundled-angular-compiler@19.0.0-alpha.4':
+ resolution: {integrity: sha512-SS2FHqRaGslJzI+cTBNDC7xg/Zx5c0iIXZnpwGa8VjJ/8L82+PlRS+d9CTBhb8tMsR06ifUTK9ym2JQ3VmE2Cg==}
+
+ '@angular-eslint/eslint-plugin-template@19.0.0-alpha.4':
+ resolution: {integrity: sha512-YiFB+tyTZ/mj/w/5DLJHl9J1ABGaHNhGdXJzagI0ufqyrePR0wTYMIyJpIGWOMHr9E5nYPsVuHn+d08dG1R0aQ==}
peerDependencies:
'@typescript-eslint/types': ^7.11.0 || ^8.0.0
'@typescript-eslint/utils': ^7.11.0 || ^8.0.0
eslint: ^8.57.0 || ^9.0.0
typescript: '*'
- '@angular-eslint/eslint-plugin@18.4.1':
- resolution: {integrity: sha512-FoHwj+AFo8ONKb8wEK5qpo6uefuyklZlDqErJxeC3fpNIJzDe8PWBcJsuZt7Wwm/HeggWgt0Au6h+3IEa0V3BQ==}
+ '@angular-eslint/eslint-plugin@18.4.2':
+ resolution: {integrity: sha512-Oem4W2P54cPADN9rJenLj90rqDPUQWx5kZiz84FCnsSn5DBdsI5LGQoogNT9y3Jx/9VL/VGIMMA5B6qG+0hVlg==}
peerDependencies:
'@typescript-eslint/utils': ^7.11.0 || ^8.0.0
eslint: ^8.57.0 || ^9.0.0
typescript: '*'
- '@angular-eslint/schematics@18.4.1':
- resolution: {integrity: sha512-1+gGodwh+UevtEx9mzZbzP1uY/9NAGEbsn8jisG1TEPDby2wKScQj6U6JwGxoW/Dd/4SIeSdilruZPALkqha7g==}
+ '@angular-eslint/eslint-plugin@19.0.0-alpha.4':
+ resolution: {integrity: sha512-IhBeiUohYLsnUrSJ92riSrhfIkGefuXIrGTgBnagn887WFR45/Go5dIIivVfMGdvTg849dtLpBDXZrycHY3QFA==}
+ peerDependencies:
+ '@typescript-eslint/utils': ^7.11.0 || ^8.0.0
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '*'
+
+ '@angular-eslint/schematics@19.0.0-alpha.4':
+ resolution: {integrity: sha512-Xv8g2PbNqhm7igTnY3uuY511Fr+FVRBHG+ZHbcUPZT7YDBaFZRJezAzbbPLZ6GdqqhoQJPHdGuEvo22yKhKXag==}
+ peerDependencies:
+ '@angular-devkit/core': '>= 19.0.0 < 20.0.0'
+ '@angular-devkit/schematics': '>= 19.0.0 < 20.0.0'
+
+ '@angular-eslint/template-parser@18.4.2':
+ resolution: {integrity: sha512-KGjDLUxMsdjaxC+8VTxCG07Q6qshOTWMYTvp2LZ4QBySDQnQuFwsIJIJfU8jJwzJCkPKfVpnyuHggAn7fdYnxA==}
peerDependencies:
- '@angular-devkit/core': '>= 18.0.0 < 19.0.0'
- '@angular-devkit/schematics': '>= 18.0.0 < 19.0.0'
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '*'
- '@angular-eslint/template-parser@18.4.1':
- resolution: {integrity: sha512-LsStXVyso/89gQU5eiJebB/b1j+wrRtTLjk+ODVUTa7NGCCT7B7xI6ToTchkBEpSTHLT9pEQXHsHer3FymsQRQ==}
+ '@angular-eslint/template-parser@19.0.0-alpha.4':
+ resolution: {integrity: sha512-Mvy1kbnqoYBQFFpQtmBB/TkhmmoN97ruSv9xa3mpKzv8JlDdVCkIn7IdqLtzcLwGr+MGcPC7GFPl8o7q12N3BQ==}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '*'
- '@angular-eslint/utils@18.4.1':
- resolution: {integrity: sha512-F5UGE1J/CRmTbl8vjexQRwRglNqnJwdXCUejaG+qlGssSHoWcRB+ubbR/na3PdnzeJdBE6DkLYElXnOQZ6YKfg==}
+ '@angular-eslint/utils@18.4.2':
+ resolution: {integrity: sha512-+c0r33QSkAnGmu/DYAPfzJJk5QDX4TP2d6EFtsenrufqRkZqrOcK4Q5t61J92Ukkr03XoqTzTDSBjlwAfM56Rw==}
peerDependencies:
'@typescript-eslint/utils': ^7.11.0 || ^8.0.0
eslint: ^8.57.0 || ^9.0.0
typescript: '*'
- '@angular/animations@19.0.0-rc.3':
- resolution: {integrity: sha512-Ww/BZp/0pFd+pc6tJpQ3wKscY3nJ0UEh60Oe3UScj7KU2h595mIPLSMBzOUKxchZd1CMvYlUC0xO6GnntBF6Xw==}
+ '@angular-eslint/utils@19.0.0-alpha.4':
+ resolution: {integrity: sha512-6Pxqs3QqSPBcAkP8I/GYijoPoAmqOYqyQvJGvBWd1oKlA3EqmXSi7uaSUa6nUI6BiA8JEJZTBaSOP6O2oyK25Q==}
+ peerDependencies:
+ '@typescript-eslint/utils': ^7.11.0 || ^8.0.0
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '*'
+
+ '@angular/animations@19.0.1':
+ resolution: {integrity: sha512-1TZ3meVmoMuQwXaHSCeIGq8tmGcwobCQM2AQ6hfK+j6eyWTSx8BdWWi+Z1iIjiYFx3pJljQiWLAHULZ66Ep/GQ==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0}
peerDependencies:
- '@angular/core': 19.0.0-rc.3
+ '@angular/core': 19.0.1
- '@angular/build@19.0.0-rc.3':
- resolution: {integrity: sha512-SldDMnC5UVbjun3KzATMC3WvOCwOizX2OhRaIbTGouniTpnJwqs7g2kF4BbQAwZN/TomqYHq6rYrDLL0UBp2vA==}
+ '@angular/build@19.0.2':
+ resolution: {integrity: sha512-i2mSg9ZoPto3IMNi/HnP2ZOwvcmaPEKrS7EOYeu1m1W9InuZ55ssMqrjKpeohKVYHwep8QmFrmDERbqutaN2hg==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
peerDependencies:
- '@angular/compiler': ^19.0.0-next.9
- '@angular/compiler-cli': ^19.0.0-next.9
- '@angular/localize': ^19.0.0-next.9
- '@angular/platform-server': ^19.0.0-next.9
- '@angular/service-worker': ^19.0.0-next.9
- '@angular/ssr': ^19.0.0-rc.3
+ '@angular/compiler': ^19.0.0
+ '@angular/compiler-cli': ^19.0.0
+ '@angular/localize': ^19.0.0
+ '@angular/platform-server': ^19.0.0
+ '@angular/service-worker': ^19.0.0
+ '@angular/ssr': ^19.0.2
less: ^4.2.0
postcss: ^8.4.0
tailwindcss: ^2.0.0 || ^3.0.0
@@ -315,96 +344,96 @@ packages:
tailwindcss:
optional: true
- '@angular/cdk@19.0.0-rc.3':
- resolution: {integrity: sha512-MlYFgSLMQPU0Y6qteK+zb7e80eNNiBrVGRXcY9xtYbO0yTF+mrE64myCPbemKjyUFADzkmjIQoUCp+imwXelGw==}
+ '@angular/cdk@19.0.1':
+ resolution: {integrity: sha512-dIqYBQISvxlpXIU10625rURPjniQV1emXbFF6wAEE48iqx9mm9WZ11KZU4heqA3qp/betZYcVY2Hwc7fLKp4Uw==}
peerDependencies:
- '@angular/common': ^19.0.0-0 || ^19.1.0-0 || ^19.2.0-0 || ^19.3.0-0 || ^20.0.0-0
- '@angular/core': ^19.0.0-0 || ^19.1.0-0 || ^19.2.0-0 || ^19.3.0-0 || ^20.0.0-0
+ '@angular/common': ^19.0.0 || ^20.0.0
+ '@angular/core': ^19.0.0 || ^20.0.0
rxjs: ^6.5.3 || ^7.4.0
- '@angular/cli@19.0.0-rc.3':
- resolution: {integrity: sha512-lctAdgs+wmk1TPmd/OaxlgfRKz51kv69FtD+OjWV5YBFX92gOEfbYyE9eIJkFtkbcsUEKGCPii9uomG1texPlQ==}
+ '@angular/cli@19.0.2':
+ resolution: {integrity: sha512-TlPrs3hRkHWrQEKwHde9l2F4IgT5tWTx4zFcllzBh2dW9iRpqXSYRb82xNHsbopdAu4lXjsYl7JilV2DQPZEaA==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
hasBin: true
- '@angular/common@19.0.0-rc.3':
- resolution: {integrity: sha512-5vOFc2cpkb52DVKFTj66Cualf8TtCC7CdAhFQCWAZEIEV0JahGGuuYWKEZVbBkPRZ6jqB/MIGwnfrODCK7bHdA==}
+ '@angular/common@19.0.1':
+ resolution: {integrity: sha512-FWAyHlEhPeLHvNLuzSl2rlksK/fVVB5O3soBYOeiKScN1vlAdALbwPDIHhimhNFBV8kmtc144WjkcTxt8MK/4g==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0}
peerDependencies:
- '@angular/core': 19.0.0-rc.3
+ '@angular/core': 19.0.1
rxjs: ^6.5.3 || ^7.4.0
- '@angular/compiler-cli@19.0.0-rc.3':
- resolution: {integrity: sha512-eGYx/oYWqVw26WKmZNo3JTY0xleOydx+XMkqJWhQkhQJlrfZHlTXxkRQJHVgzrzhFov1/ERjHYlsIK61qfQ8Bg==}
+ '@angular/compiler-cli@19.0.1':
+ resolution: {integrity: sha512-dIpJCRPmmgmPyAqkOwhP4IEj+T5H4s3x39sCCBohqr2mlZcTXp/Fir8CXnMHlzawh4eXm4pvHjvh/bmMH4efrA==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0}
hasBin: true
peerDependencies:
- '@angular/compiler': 19.0.0-rc.3
+ '@angular/compiler': 19.0.1
typescript: '>=5.5 <5.7'
- '@angular/compiler@19.0.0-rc.3':
- resolution: {integrity: sha512-rzAHs0WyRKGSSo6e2VxAt/1pr/3y6ZBXxo1+wA0yzFKzr4zX7aTc/pEZOZKsrsoZd+GJvMXX21vRt4YNPxKx6Q==}
+ '@angular/compiler@19.0.1':
+ resolution: {integrity: sha512-loyI701+As+sWsE4yr9HpIPBqIohpNrGby/hsXtr+zJTMUWp/sKZlavctVtUsWWJhwHMevoybdgd3N9NY97F7g==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0}
peerDependencies:
- '@angular/core': 19.0.0-rc.3
+ '@angular/core': 19.0.1
peerDependenciesMeta:
'@angular/core':
optional: true
- '@angular/core@19.0.0-rc.3':
- resolution: {integrity: sha512-WDAdAwSGsKNCx66NY0t/Ht0bnaSetKhiveaoVIzNhNJ7bYnGrol/yD6XjVEEzbolw/blxRcfas2aLg9bv6TQfw==}
+ '@angular/core@19.0.1':
+ resolution: {integrity: sha512-+VpWcg2aC/dY9TM6fsj00enZ6RP5wpRqk/SeRe3UP3Je/n+vWIgHJTb1ZLNeOIvDaE86BhKPMwFS0QVjoEGQFA==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0}
peerDependencies:
rxjs: ^6.5.3 || ^7.4.0
zone.js: ~0.15.0
- '@angular/forms@19.0.0-rc.3':
- resolution: {integrity: sha512-rY1rTniZXEfTI+TIzw8aISAddTMdLtetiVzKlZmSGHyhik/E8McwQx3Oup2buEeLs2qOSrSkihK6cVwhvqlATQ==}
+ '@angular/forms@19.0.1':
+ resolution: {integrity: sha512-PNMQVi97ZK9X7fQeO1li6LxoL9U6v7ByC+4kj7xHAcOGaBCB+EJ/ZPKCKeaGn4G7mJd3iH8SMVzoUQc028KIcw==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0}
peerDependencies:
- '@angular/common': 19.0.0-rc.3
- '@angular/core': 19.0.0-rc.3
- '@angular/platform-browser': 19.0.0-rc.3
+ '@angular/common': 19.0.1
+ '@angular/core': 19.0.1
+ '@angular/platform-browser': 19.0.1
rxjs: ^6.5.3 || ^7.4.0
- '@angular/material@19.0.0-rc.3':
- resolution: {integrity: sha512-RL4o+WJVoaUVmPvPJoQ/Y8nAxopuJ2pTWtr8S1HosmiDIn0xVqqBSK9KWHtvHZ41nsXlH9r/4MeASOc0x0mnyQ==}
+ '@angular/material@19.0.1':
+ resolution: {integrity: sha512-pAZ+cgBUAJjXmwAY4u1NXuxcxJKHts0s7ZNpf6JGUu+yWArLOc/BwFTDO9Htzz2E82eMH417d1ny4fpYwdgIZg==}
peerDependencies:
- '@angular/animations': ^19.0.0-0 || ^19.1.0-0 || ^19.2.0-0 || ^19.3.0-0 || ^20.0.0-0
- '@angular/cdk': 19.0.0-rc.3
- '@angular/common': ^19.0.0-0 || ^19.1.0-0 || ^19.2.0-0 || ^19.3.0-0 || ^20.0.0-0
- '@angular/core': ^19.0.0-0 || ^19.1.0-0 || ^19.2.0-0 || ^19.3.0-0 || ^20.0.0-0
- '@angular/forms': ^19.0.0-0 || ^19.1.0-0 || ^19.2.0-0 || ^19.3.0-0 || ^20.0.0-0
- '@angular/platform-browser': ^19.0.0-0 || ^19.1.0-0 || ^19.2.0-0 || ^19.3.0-0 || ^20.0.0-0
+ '@angular/animations': ^19.0.0 || ^20.0.0
+ '@angular/cdk': 19.0.1
+ '@angular/common': ^19.0.0 || ^20.0.0
+ '@angular/core': ^19.0.0 || ^20.0.0
+ '@angular/forms': ^19.0.0 || ^20.0.0
+ '@angular/platform-browser': ^19.0.0 || ^20.0.0
rxjs: ^6.5.3 || ^7.4.0
- '@angular/platform-browser-dynamic@19.0.0-rc.3':
- resolution: {integrity: sha512-SUwQV6SHSfC1HdQGj/LzwW7qDmWZejlb22Ox+ECFZ+c8dEZj1blPdugOaLQkY+1Tnzt46zteNQruygVbckqZTg==}
+ '@angular/platform-browser-dynamic@19.0.1':
+ resolution: {integrity: sha512-A8sM0NTwZPFpv5kWSUeRhMENCw8kmBxR9CX9TMVeU6u9TP+IT3SFhUWhDQZNbmJAHhyAuk5B1gBJ/aoz0/OBcw==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0}
peerDependencies:
- '@angular/common': 19.0.0-rc.3
- '@angular/compiler': 19.0.0-rc.3
- '@angular/core': 19.0.0-rc.3
- '@angular/platform-browser': 19.0.0-rc.3
+ '@angular/common': 19.0.1
+ '@angular/compiler': 19.0.1
+ '@angular/core': 19.0.1
+ '@angular/platform-browser': 19.0.1
- '@angular/platform-browser@19.0.0-rc.3':
- resolution: {integrity: sha512-hPf/wdF9GccBSC5AfG7PXuzb8oG1YUIT16xdU9zekCLnCi6uWKuYzVMRnbXWKSWNNumK4SHI2sAB/vzH9XEzTA==}
+ '@angular/platform-browser@19.0.1':
+ resolution: {integrity: sha512-ycl6GsK5avKz2PKyKR8G3eqH5rWdzTqRfYStN+1Ufhopx9jmCQ9r0JSIekoHJ8W2KDZfojWp6f4izDMvKnUpvA==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0}
peerDependencies:
- '@angular/animations': 19.0.0-rc.3
- '@angular/common': 19.0.0-rc.3
- '@angular/core': 19.0.0-rc.3
+ '@angular/animations': 19.0.1
+ '@angular/common': 19.0.1
+ '@angular/core': 19.0.1
peerDependenciesMeta:
'@angular/animations':
optional: true
- '@angular/router@19.0.0-rc.3':
- resolution: {integrity: sha512-6OQ0440oa9CxB6v8YntQSAG5ap/cB19lY+KnWn78LVRJtOOfEIDB+xRm4/EtQiSUSdJjl+CkqVMRgxt/1xQ1uw==}
+ '@angular/router@19.0.1':
+ resolution: {integrity: sha512-/9f7RxVqOTASFhpqla7x9V58SE8Yv4SClKRikvv5Tn5EGDbSVR3DgGu6qENP57A2pVPW4Ho5er5KKT35HjhcFw==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0}
peerDependencies:
- '@angular/common': 19.0.0-rc.3
- '@angular/core': 19.0.0-rc.3
- '@angular/platform-browser': 19.0.0-rc.3
+ '@angular/common': 19.0.1
+ '@angular/core': 19.0.1
+ '@angular/platform-browser': 19.0.1
rxjs: ^6.5.3 || ^7.4.0
'@babel/code-frame@7.26.2':
@@ -1600,11 +1629,11 @@ packages:
resolution: {integrity: sha512-zM0mVWSXE0a0h9aKACLwKmD6nHcRiKrPpCfvaKqG1CqDEyjEawId0ocXxVzPMCAm6kkWr2P025msfxXEnt8UGQ==}
engines: {node: '>= 10'}
- '@ngtools/webpack@19.0.0-rc.3':
- resolution: {integrity: sha512-2QmiIZ+VOQOkUUdIs5nawAgMIhMnVq0bMlhwqFPzmhhcJaDCWZtla8F1XmEU6x5YYDKInhs510iGUTo5jUmVag==}
+ '@ngtools/webpack@19.0.2':
+ resolution: {integrity: sha512-wHAIItix6zAOczdLjY9Z/e4mtpBDSzBkN//N6GHoGtjtCSzqZg4uPg5KG7B5tpVb/u6IMRK+4hhu9Vu8lhzz8g==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
peerDependencies:
- '@angular/compiler-cli': ^19.0.0-next.0
+ '@angular/compiler-cli': ^19.0.0
typescript: '>=5.5 <5.7'
webpack: ^5.54.0
@@ -1849,8 +1878,8 @@ packages:
cpu: [x64]
os: [win32]
- '@schematics/angular@19.0.0-rc.3':
- resolution: {integrity: sha512-JAWtT5fGRHo94tq+tt3hNhGupefKAP6tyEVOCXvRo0yZ/2kZ3JvHxTDYrWdPoGswZWkxYLevDattMhiUJZ0VWg==}
+ '@schematics/angular@19.0.2':
+ resolution: {integrity: sha512-KPNKJRcuJ9kWctcW+g7WzmCEHpjNnYbNVyiU/MvKdQX0uhGXnXE13YMVfgYIf/0KeHcVp5dkAwg5dkmm9PGNTw==}
engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
'@sigstore/bundle@3.0.0':
@@ -1888,8 +1917,12 @@ packages:
resolution: {integrity: sha512-bZY04sWSn2YWAqcuY/fYy03ynARYHwn8xzYgdqqcHBXsBXhOc+bbWwHyLwW28XAA2NjzjMPZZAM3N5D09i+zEQ==}
engines: {node: '>=16', pnpm: '>=8.6.0'}
- '@thednp/shorty@2.0.7':
- resolution: {integrity: sha512-PQ388ZznrgnkikwkDCqqFfkGAYWXS2ijFmXD63Ej47Md6VrV5WJqhgQilhu3tSkzddtbDJlz4tQTj4RYVrWUoA==}
+ '@thednp/position-observer@1.0.5':
+ resolution: {integrity: sha512-3ceT4kl8okq4HMMqQ3+7UGosf6u5p6n95kvYUqtgJGTSE69LcU4ep5NjeSChEmvk/I9V/3tNMMlXYKCSWYq61Q==}
+ engines: {node: '>=16', pnpm: '>=8.6.0'}
+
+ '@thednp/shorty@2.0.9':
+ resolution: {integrity: sha512-btulzTMSxSQxNipN5iLMtw6MaTrZ3P0feRUX/rl2fZ1m31RI56PC967lnN5bwUCpZLzry0pl9QoCKlT3GtU+mw==}
engines: {node: '>=16', pnpm: '>=8.6.0'}
'@ts-morph/common@0.25.0':
@@ -1936,8 +1969,8 @@ packages:
'@types/express-serve-static-core@4.19.6':
resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==}
- '@types/express-serve-static-core@5.0.1':
- resolution: {integrity: sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==}
+ '@types/express-serve-static-core@5.0.2':
+ resolution: {integrity: sha512-vluaspfvWEtE4vcSDlKRNer52DvOGrB2xv6diXy6UKyKW0lqZiWHGNApSyxOv+8DE5Z27IzVvE7hNkxg7EXIcg==}
'@types/express@4.17.21':
resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==}
@@ -1966,8 +1999,8 @@ packages:
'@types/node-forge@1.3.11':
resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==}
- '@types/node@22.9.0':
- resolution: {integrity: sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==}
+ '@types/node@22.10.0':
+ resolution: {integrity: sha512-XC70cRZVElFHfIUB40FgZOBbgJYFKKMa5nb9lxcwYstFG/Mi+/Y0bGS+rs6Dmhmkpq4pnNiLiuZAbc02YCOnmA==}
'@types/qs@6.9.17':
resolution: {integrity: sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==}
@@ -1996,8 +2029,8 @@ packages:
'@types/ws@8.5.13':
resolution: {integrity: sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==}
- '@typescript-eslint/eslint-plugin@8.15.0':
- resolution: {integrity: sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==}
+ '@typescript-eslint/eslint-plugin@8.16.0':
+ resolution: {integrity: sha512-5YTHKV8MYlyMI6BaEG7crQ9BhSc8RxzshOReKwZwRWN0+XvvTOm+L/UYLCYxFpfwYuAAqhxiq4yae0CMFwbL7Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
'@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
@@ -2007,8 +2040,8 @@ packages:
typescript:
optional: true
- '@typescript-eslint/parser@8.15.0':
- resolution: {integrity: sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==}
+ '@typescript-eslint/parser@8.16.0':
+ resolution: {integrity: sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
@@ -2017,12 +2050,12 @@ packages:
typescript:
optional: true
- '@typescript-eslint/scope-manager@8.15.0':
- resolution: {integrity: sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==}
+ '@typescript-eslint/scope-manager@8.16.0':
+ resolution: {integrity: sha512-mwsZWubQvBki2t5565uxF0EYvG+FwdFb8bMtDuGQLdCCnGPrDEDvm1gtfynuKlnpzeBRqdFCkMf9jg1fnAK8sg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/type-utils@8.15.0':
- resolution: {integrity: sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==}
+ '@typescript-eslint/type-utils@8.16.0':
+ resolution: {integrity: sha512-IqZHGG+g1XCWX9NyqnI/0CX5LL8/18awQqmkZSl2ynn8F76j579dByc0jhfVSnSnhf7zv76mKBQv9HQFKvDCgg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
@@ -2031,12 +2064,12 @@ packages:
typescript:
optional: true
- '@typescript-eslint/types@8.15.0':
- resolution: {integrity: sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==}
+ '@typescript-eslint/types@8.16.0':
+ resolution: {integrity: sha512-NzrHj6thBAOSE4d9bsuRNMvk+BvaQvmY4dDglgkgGC0EW/tB3Kelnp3tAKH87GEwzoxgeQn9fNGRyFJM/xd+GQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/typescript-estree@8.15.0':
- resolution: {integrity: sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==}
+ '@typescript-eslint/typescript-estree@8.16.0':
+ resolution: {integrity: sha512-E2+9IzzXMc1iaBy9zmo+UYvluE3TW7bCGWSF41hVWUE01o8nzr1rvOQYSxelxr6StUvRcTMe633eY8mXASMaNw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '*'
@@ -2044,8 +2077,8 @@ packages:
typescript:
optional: true
- '@typescript-eslint/utils@8.15.0':
- resolution: {integrity: sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==}
+ '@typescript-eslint/utils@8.16.0':
+ resolution: {integrity: sha512-C1zRy/mOL8Pj157GiX4kaw7iyRLKfJXBR3L82hk5kS/GyHcOFmy4YUq/zfZti72I9wnuQtA/+xzft4wCC8PJdA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
@@ -2054,8 +2087,8 @@ packages:
typescript:
optional: true
- '@typescript-eslint/visitor-keys@8.15.0':
- resolution: {integrity: sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==}
+ '@typescript-eslint/visitor-keys@8.16.0':
+ resolution: {integrity: sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@vitejs/plugin-basic-ssl@1.1.0':
@@ -2180,13 +2213,18 @@ packages:
ajv@8.17.1:
resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==}
- angular-eslint@18.4.1:
- resolution: {integrity: sha512-tRy0SeWC2zoftEYTlUU6WLtzyxF7cjlodnnG40EO2PGPwRN2m+EWQn7de0RZz0MIYPl36px8gj9CztiHO2risA==}
+ angular-eslint@19.0.0-alpha.4:
+ resolution: {integrity: sha512-/7Jl/rCoflc5wkjkVCBIs1DDwr/vVJ8Rp4LgCofoIPSbAlrZ8SkS8oLoLTIbvhrM6kO9Gq5LnzL13Y//hNndsw==}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '*'
typescript-eslint: ^8.0.0
+ angularx-qrcode@19.0.0:
+ resolution: {integrity: sha512-uH1gO/X1hgSojZwgO3EmaXP+MvWCgZm5WGh3y1ZL2+VMstEGEMtJGZTyR645fB7ABF2ZIBUMB9h/SKvGJQX/zQ==}
+ peerDependencies:
+ '@angular/core': ^19.0.0
+
ansi-colors@4.1.3:
resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
engines: {node: '>=6'}
@@ -2328,8 +2366,8 @@ packages:
boolbase@1.0.0:
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
- bootstrap.native@5.0.13:
- resolution: {integrity: sha512-SiiTxaK3LjuOjPaXEnDBQNY3w0t28Qdx6I8drortuFg6Ch3q6cWoOxlFHThcGOPewziVarQAA4WPE00GFQmbWQ==}
+ bootstrap.native@5.1.1:
+ resolution: {integrity: sha512-QlFMbaCSo1AvfoiiI3jdJk8Rh3BZIXh7UjVcR9/wo+aVTZqOrCrePA4f2chpXLZxwbHitWyMgl1CJSSSqqx8/w==}
engines: {node: '>=16', pnpm: '>=8.6.0'}
brace-expansion@1.1.11:
@@ -2384,8 +2422,12 @@ packages:
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
engines: {node: '>= 6'}
- caniuse-lite@1.0.30001680:
- resolution: {integrity: sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==}
+ camelcase@5.3.1:
+ resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
+ engines: {node: '>=6'}
+
+ caniuse-lite@1.0.30001684:
+ resolution: {integrity: sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==}
ccount@2.0.1:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
@@ -2451,6 +2493,9 @@ packages:
resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==}
engines: {node: '>= 12'}
+ cliui@6.0.0:
+ resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
+
cliui@7.0.4:
resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
@@ -2640,6 +2685,10 @@ packages:
decache@4.6.2:
resolution: {integrity: sha512-2LPqkLeu8XWHU8qNCS3kcF6sCcb5zIzvWaAHYSvPfwhdd7mHuah29NssMzrTYyHN4F5oFy2ko9OBYxegtU0FEw==}
+ decamelize@1.2.0:
+ resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
+ engines: {node: '>=0.10.0'}
+
decode-named-character-reference@1.0.2:
resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==}
@@ -2706,6 +2755,9 @@ packages:
didyoumean@1.2.2:
resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
+ dijkstrajs@1.0.3:
+ resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==}
+
dlv@1.1.3:
resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
@@ -2741,8 +2793,8 @@ packages:
ee-first@1.1.1:
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
- electron-to-chromium@1.5.63:
- resolution: {integrity: sha512-ddeXKuY9BHo/mw145axlyWjlJ1UBt4WK3AlvkT7W2AbqfRQoacVoRUCF6wL3uIx/8wT9oLKXzI+rFqHHscByaA==}
+ electron-to-chromium@1.5.65:
+ resolution: {integrity: sha512-PWVzBjghx7/wop6n22vS2MLU8tKGd4Q91aCEGhG/TYmW6PP5OcSXcdnxTe1NNt0T66N8D6jxh4kC8UsdzOGaIw==}
emitter-component@1.1.2:
resolution: {integrity: sha512-QdXO3nXOzZB4pAjM0n6ZE+R9/+kPpECA/XSELIcc54NeYVnBqIk+4DFiBgK+8QbV3mdvTG6nedl7dTYgO+5wDw==}
@@ -2905,8 +2957,8 @@ packages:
peerDependencies:
eslint: '>=6.0.0'
- eslint-plugin-jsdoc@50.5.0:
- resolution: {integrity: sha512-xTkshfZrUbiSHXBwZ/9d5ulZ2OcHXxSvm/NPo494H/hadLRJwOq5PMV0EUpMqsb9V+kQo+9BAgi6Z7aJtdBp2A==}
+ eslint-plugin-jsdoc@50.6.0:
+ resolution: {integrity: sha512-tCNp4fR79Le3dYTPB0dKEv7yFyvGkUCa+Z3yuTrrNGGOxBlXo9Pn0PEgroOZikUQOGjxoGMVKNjrOHcYEdfszg==}
engines: {node: '>=18'}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
@@ -3068,6 +3120,10 @@ packages:
resolution: {integrity: sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==}
engines: {node: '>=14.16'}
+ find-up@4.1.0:
+ resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
+ engines: {node: '>=8'}
+
find-up@5.0.0:
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
engines: {node: '>=10'}
@@ -3240,8 +3296,8 @@ packages:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
- hosted-git-info@8.0.0:
- resolution: {integrity: sha512-4nw3vOVR+vHUOT8+U4giwe2tcGv+R3pwwRidUe67DoMBTjhrfr6rZYJVVwdkBE+Um050SG+X9tf0Jo4fOpn01w==}
+ hosted-git-info@8.0.2:
+ resolution: {integrity: sha512-sYKnA7eGln5ov8T8gnYlkSOxFJvywzEx9BueN6xo/GKO8PGiI6uK6xx+DIGe45T3bdVjLAQDQW1aicT8z8JwQg==}
engines: {node: ^18.17.0 || >=20.5.0}
hpack.js@2.1.6:
@@ -3322,8 +3378,8 @@ packages:
resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==}
engines: {node: '>=10.18'}
- i18next@23.16.5:
- resolution: {integrity: sha512-KTlhE3EP9x6pPTAW7dy0WKIhoCpfOGhRQlO+jttQLgzVaoOjWwBWramu7Pp0i+8wDNduuzXfe3kkVbzrKyrbTA==}
+ i18next@23.16.8:
+ resolution: {integrity: sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==}
iconv-lite@0.4.24:
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
@@ -3359,8 +3415,8 @@ packages:
engines: {node: '>=0.10.0'}
hasBin: true
- immutable@5.0.2:
- resolution: {integrity: sha512-1NU7hWZDkV7hJ4PJ9dur9gTNQ4ePNPN4k9/0YhwjzykTi/+3Q5pF93YU5QoVj8BuOnhLgaY8gs0U2pj4kSYVcw==}
+ immutable@5.0.3:
+ resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==}
import-fresh@3.3.0:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
@@ -3407,8 +3463,8 @@ packages:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'}
- is-bun-module@1.2.1:
- resolution: {integrity: sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==}
+ is-bun-module@1.3.0:
+ resolution: {integrity: sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==}
is-core-module@2.15.1:
resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==}
@@ -3614,6 +3670,10 @@ packages:
resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==}
engines: {'0': node >= 0.2.0}
+ jwt-decode@4.0.0:
+ resolution: {integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==}
+ engines: {node: '>=18'}
+
karma-chrome-launcher@3.2.0:
resolution: {integrity: sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q==}
@@ -3716,6 +3776,10 @@ packages:
resolution: {integrity: sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==}
engines: {node: '>= 12.13.0'}
+ locate-path@5.0.0:
+ resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
+ engines: {node: '>=8'}
+
locate-path@6.0.0:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
@@ -3932,8 +3996,8 @@ packages:
micromark-util-sanitize-uri@2.0.1:
resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}
- micromark-util-subtokenize@2.0.2:
- resolution: {integrity: sha512-xKxhkB62vwHUuuxHe9Xqty3UaAsizV2YKq5OV344u3hFBbf8zIYrhYOWhAQb94MtMPkjTOzzjJ/hid9/dR5vFA==}
+ micromark-util-subtokenize@2.0.3:
+ resolution: {integrity: sha512-VXJJuNxYWSoYL6AJ6OQECCFGhIU2GGHMw8tahogePBrjkG8aCCas3ibkp7RnVOSTClg2is05/R7maAhF1XyQMg==}
micromark-util-symbol@2.0.1:
resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}
@@ -4098,8 +4162,8 @@ packages:
mz@2.7.0:
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
- nanoid@3.3.7:
- resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
+ nanoid@3.3.8:
+ resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
@@ -4173,8 +4237,8 @@ packages:
resolution: {integrity: sha512-IxaQZDMsqfQ2Lz37VvyyEtKLe8FsRZuysmedy/N06TU1RyVppYKXrO4xIhR0F+7ubIBox6Q7nir6fQI3ej39iA==}
engines: {node: ^18.17.0 || >=20.5.0}
- npm-install-checks@7.1.0:
- resolution: {integrity: sha512-bkTildVlofeMX7wiOaWk3PlW7YcBXAuEc7TWpOxwUgalG5ZvgT/ms+6OX9zt7iGLv4+VhKbRZhpOfgQJzk1YAw==}
+ npm-install-checks@7.1.1:
+ resolution: {integrity: sha512-u6DCwbow5ynAX5BdiHQ9qvexme4U3qHW3MWe5NqH+NeBm0LbiH6zvGjNNew1fY+AZZUtVHbOPF3j7mJxbUzpXg==}
engines: {node: ^18.17.0 || >=20.5.0}
npm-normalize-package-bin@4.0.0:
@@ -4219,6 +4283,10 @@ packages:
obuf@1.1.2:
resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==}
+ oidc-client-ts@3.1.0:
+ resolution: {integrity: sha512-IDopEXjiwjkmJLYZo6BTlvwOtnlSniWZkKZoXforC/oLZHC9wkIxd25Kwtmo5yKFMMVcsp3JY6bhcNJqdYk8+g==}
+ engines: {node: '>=18'}
+
on-finished@2.3.0:
resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==}
engines: {node: '>= 0.8'}
@@ -4273,6 +4341,10 @@ packages:
resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==}
engines: {node: '>=0.10.0'}
+ p-limit@2.3.0:
+ resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
+ engines: {node: '>=6'}
+
p-limit@3.1.0:
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
engines: {node: '>=10'}
@@ -4281,6 +4353,10 @@ packages:
resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ p-locate@4.1.0:
+ resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
+ engines: {node: '>=8'}
+
p-locate@5.0.0:
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
engines: {node: '>=10'}
@@ -4301,6 +4377,10 @@ packages:
resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==}
engines: {node: '>=16.17'}
+ p-try@2.2.0:
+ resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
+ engines: {node: '>=6'}
+
package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
@@ -4411,6 +4491,10 @@ packages:
resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==}
engines: {node: '>=14.16'}
+ pngjs@5.0.0:
+ resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==}
+ engines: {node: '>=10.13.0'}
+
postcss-import@15.1.0:
resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
engines: {node: '>=14.0.0'}
@@ -4504,8 +4588,8 @@ packages:
resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==}
engines: {node: '>=6.0.0'}
- prettier-plugin-tailwindcss@0.6.8:
- resolution: {integrity: sha512-dGu3kdm7SXPkiW4nzeWKCl3uoImdd5CTZEJGxyypEPL37Wj0HT2pLqjrvSei1nTeuQfO4PUfjeW5cTUNRLZ4sA==}
+ prettier-plugin-tailwindcss@0.6.9:
+ resolution: {integrity: sha512-r0i3uhaZAXYP0At5xGfJH876W3HHGHDp+LCRUJrs57PBeQ6mYHMwr25KH8NPX44F2yGTvdnH7OqCshlQx183Eg==}
engines: {node: '>=14.21.3'}
peerDependencies:
'@ianvs/prettier-plugin-sort-imports': '*'
@@ -4619,6 +4703,11 @@ packages:
resolution: {integrity: sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==}
engines: {node: '>=0.9'}
+ qrcode@1.5.4:
+ resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==}
+ engines: {node: '>=10.13.0'}
+ hasBin: true
+
qs@6.13.0:
resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==}
engines: {node: '>=0.6'}
@@ -4674,15 +4763,15 @@ packages:
regex-parser@2.3.0:
resolution: {integrity: sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==}
- regexpu-core@6.1.1:
- resolution: {integrity: sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==}
+ regexpu-core@6.2.0:
+ resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==}
engines: {node: '>=4'}
regjsgen@0.8.0:
resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==}
- regjsparser@0.11.2:
- resolution: {integrity: sha512-3OGZZ4HoLJkkAZx/48mTXJNlmqTGOzc0o9OWQPuWpkOlXXPbyN6OafCcoXUnBqE2D3f/T5L+pWc1kdEmnfnRsA==}
+ regjsparser@0.12.0:
+ resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==}
hasBin: true
require-directory@2.1.1:
@@ -4693,6 +4782,9 @@ packages:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
+ require-main-filename@2.0.0:
+ resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
+
requires-port@1.0.0:
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
@@ -4843,6 +4935,9 @@ packages:
resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==}
engines: {node: '>= 0.8.0'}
+ set-blocking@2.0.0:
+ resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
+
set-function-length@1.2.2:
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
engines: {node: '>= 0.4'}
@@ -5148,8 +5243,8 @@ packages:
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
hasBin: true
- ts-api-utils@1.4.0:
- resolution: {integrity: sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==}
+ ts-api-utils@1.4.2:
+ resolution: {integrity: sha512-ZF5gQIQa/UmzfvxbHZI3JXN0/Jt+vnAfAviNRAMc491laiK6YCLpCW9ft8oaCRFOTxCZtUTE6XB0ZQAe3olntw==}
engines: {node: '>=16'}
peerDependencies:
typescript: '>=4.2.0'
@@ -5182,8 +5277,8 @@ packages:
typed-assert@1.0.9:
resolution: {integrity: sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==}
- typescript-eslint@8.15.0:
- resolution: {integrity: sha512-wY4FRGl0ZI+ZU4Jo/yjdBu0lVTSML58pu6PgGtJmCufvzfV565pUF6iACQt092uFOd49iLOTX/sEVmHtbSrS+w==}
+ typescript-eslint@8.16.0:
+ resolution: {integrity: sha512-wDkVmlY6O2do4V+lZd0GtRfbtXbeD0q9WygwXXSJnC1xorE8eqyC2L1tJimqpSeFrOzRlYtWnUp/uzgHQOgfBQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
@@ -5206,8 +5301,8 @@ packages:
engines: {node: '>=0.8.0'}
hasBin: true
- undici-types@6.19.8:
- resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
+ undici-types@6.20.0:
+ resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
unicode-canonical-property-names-ecmascript@2.0.1:
resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==}
@@ -5417,6 +5512,9 @@ packages:
resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==}
engines: {node: '>=0.8.0'}
+ which-module@2.0.1:
+ resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
+
which@1.3.1:
resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==}
hasBin: true
@@ -5493,6 +5591,9 @@ packages:
utf-8-validate:
optional: true
+ y18n@4.0.3:
+ resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
+
y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
@@ -5507,11 +5608,15 @@ packages:
resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
engines: {node: '>=18'}
- yaml@2.6.0:
- resolution: {integrity: sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==}
+ yaml@2.6.1:
+ resolution: {integrity: sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==}
engines: {node: '>= 14'}
hasBin: true
+ yargs-parser@18.1.3:
+ resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
+ engines: {node: '>=6'}
+
yargs-parser@20.2.9:
resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
engines: {node: '>=10'}
@@ -5520,6 +5625,10 @@ packages:
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
engines: {node: '>=12'}
+ yargs@15.4.1:
+ resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
+ engines: {node: '>=8'}
+
yargs@16.2.0:
resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
engines: {node: '>=10'}
@@ -5557,21 +5666,21 @@ snapshots:
'@jridgewell/gen-mapping': 0.3.5
'@jridgewell/trace-mapping': 0.3.25
- '@angular-devkit/architect@0.1900.0-rc.3(chokidar@4.0.1)':
+ '@angular-devkit/architect@0.1900.2(chokidar@4.0.1)':
dependencies:
- '@angular-devkit/core': 19.0.0-rc.3(chokidar@4.0.1)
+ '@angular-devkit/core': 19.0.2(chokidar@4.0.1)
rxjs: 7.8.1
transitivePeerDependencies:
- chokidar
- '@angular-devkit/build-angular@19.0.0-rc.3(@angular/compiler-cli@19.0.0-rc.3(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3))(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@types/node@22.9.0)(chokidar@4.0.1)(karma@6.4.4)(tailwindcss@3.4.15)(typescript@5.6.3)(vite@5.4.11(@types/node@22.9.0)(less@4.2.0)(sass@1.80.7)(terser@5.36.0))':
+ '@angular-devkit/build-angular@19.0.2(@angular/compiler-cli@19.0.1(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3))(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@types/node@22.10.0)(chokidar@4.0.1)(karma@6.4.4)(tailwindcss@3.4.15)(typescript@5.6.3)(vite@5.4.11(@types/node@22.10.0)(less@4.2.0)(sass@1.80.7)(terser@5.36.0))':
dependencies:
'@ampproject/remapping': 2.3.0
- '@angular-devkit/architect': 0.1900.0-rc.3(chokidar@4.0.1)
- '@angular-devkit/build-webpack': 0.1900.0-rc.3(chokidar@4.0.1)(webpack-dev-server@5.1.0(webpack@5.96.1))(webpack@5.96.1(esbuild@0.24.0))
- '@angular-devkit/core': 19.0.0-rc.3(chokidar@4.0.1)
- '@angular/build': 19.0.0-rc.3(@angular/compiler-cli@19.0.0-rc.3(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3))(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@types/node@22.9.0)(chokidar@4.0.1)(less@4.2.0)(postcss@8.4.49)(tailwindcss@3.4.15)(terser@5.36.0)(typescript@5.6.3)
- '@angular/compiler-cli': 19.0.0-rc.3(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3)
+ '@angular-devkit/architect': 0.1900.2(chokidar@4.0.1)
+ '@angular-devkit/build-webpack': 0.1900.2(chokidar@4.0.1)(webpack-dev-server@5.1.0(webpack@5.96.1))(webpack@5.96.1(esbuild@0.24.0))
+ '@angular-devkit/core': 19.0.2(chokidar@4.0.1)
+ '@angular/build': 19.0.2(@angular/compiler-cli@19.0.1(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3))(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@types/node@22.10.0)(chokidar@4.0.1)(less@4.2.0)(postcss@8.4.49)(tailwindcss@3.4.15)(terser@5.36.0)(typescript@5.6.3)
+ '@angular/compiler-cli': 19.0.1(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3)
'@babel/core': 7.26.0
'@babel/generator': 7.26.2
'@babel/helper-annotate-as-pure': 7.25.9
@@ -5582,8 +5691,8 @@ snapshots:
'@babel/preset-env': 7.26.0(@babel/core@7.26.0)
'@babel/runtime': 7.26.0
'@discoveryjs/json-ext': 0.6.3
- '@ngtools/webpack': 19.0.0-rc.3(@angular/compiler-cli@19.0.0-rc.3(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3))(typescript@5.6.3)(webpack@5.96.1(esbuild@0.24.0))
- '@vitejs/plugin-basic-ssl': 1.1.0(vite@5.4.11(@types/node@22.9.0)(less@4.2.0)(sass@1.80.7)(terser@5.36.0))
+ '@ngtools/webpack': 19.0.2(@angular/compiler-cli@19.0.1(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3))(typescript@5.6.3)(webpack@5.96.1(esbuild@0.24.0))
+ '@vitejs/plugin-basic-ssl': 1.1.0(vite@5.4.11(@types/node@22.10.0)(less@4.2.0)(sass@1.80.7)(terser@5.36.0))
ansi-colors: 4.1.3
autoprefixer: 10.4.20(postcss@8.4.49)
babel-loader: 9.2.1(@babel/core@7.26.0)(webpack@5.96.1(esbuild@0.24.0))
@@ -5647,9 +5756,9 @@ snapshots:
- vite
- webpack-cli
- '@angular-devkit/build-webpack@0.1900.0-rc.3(chokidar@4.0.1)(webpack-dev-server@5.1.0(webpack@5.96.1))(webpack@5.96.1(esbuild@0.24.0))':
+ '@angular-devkit/build-webpack@0.1900.2(chokidar@4.0.1)(webpack-dev-server@5.1.0(webpack@5.96.1))(webpack@5.96.1(esbuild@0.24.0))':
dependencies:
- '@angular-devkit/architect': 0.1900.0-rc.3(chokidar@4.0.1)
+ '@angular-devkit/architect': 0.1900.2(chokidar@4.0.1)
rxjs: 7.8.1
webpack: 5.96.1(esbuild@0.24.0)
webpack-dev-server: 5.1.0(webpack@5.96.1)
@@ -5667,7 +5776,7 @@ snapshots:
optionalDependencies:
chokidar: 4.0.1
- '@angular-devkit/core@19.0.0-rc.3(chokidar@4.0.1)':
+ '@angular-devkit/core@19.0.2(chokidar@4.0.1)':
dependencies:
ajv: 8.17.1
ajv-formats: 3.0.1(ajv@8.17.1)
@@ -5688,9 +5797,9 @@ snapshots:
transitivePeerDependencies:
- chokidar
- '@angular-devkit/schematics@19.0.0-rc.3(chokidar@4.0.1)':
+ '@angular-devkit/schematics@19.0.2(chokidar@4.0.1)':
dependencies:
- '@angular-devkit/core': 19.0.0-rc.3(chokidar@4.0.1)
+ '@angular-devkit/core': 19.0.2(chokidar@4.0.1)
jsonc-parser: 3.3.1
magic-string: 0.30.12
ora: 5.4.1
@@ -5698,38 +5807,48 @@ snapshots:
transitivePeerDependencies:
- chokidar
- '@angular-eslint/builder@18.4.1(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
+ '@angular-eslint/builder@19.0.0-alpha.4(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
dependencies:
eslint: 9.15.0(jiti@1.21.6)
typescript: 5.6.3
- '@angular-eslint/bundled-angular-compiler@18.4.1': {}
+ '@angular-eslint/bundled-angular-compiler@18.4.2': {}
+
+ '@angular-eslint/bundled-angular-compiler@19.0.0-alpha.4': {}
- '@angular-eslint/eslint-plugin-template@18.4.1(@typescript-eslint/types@8.15.0)(@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
+ '@angular-eslint/eslint-plugin-template@19.0.0-alpha.4(@typescript-eslint/types@8.16.0)(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
dependencies:
- '@angular-eslint/bundled-angular-compiler': 18.4.1
- '@angular-eslint/utils': 18.4.1(@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
- '@typescript-eslint/types': 8.15.0
- '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@angular-eslint/bundled-angular-compiler': 19.0.0-alpha.4
+ '@angular-eslint/utils': 19.0.0-alpha.4(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@typescript-eslint/types': 8.16.0
+ '@typescript-eslint/utils': 8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
aria-query: 5.3.2
axobject-query: 4.1.0
eslint: 9.15.0(jiti@1.21.6)
typescript: 5.6.3
- '@angular-eslint/eslint-plugin@18.4.1(@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
+ '@angular-eslint/eslint-plugin@18.4.2(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
dependencies:
- '@angular-eslint/bundled-angular-compiler': 18.4.1
- '@angular-eslint/utils': 18.4.1(@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
- '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@angular-eslint/bundled-angular-compiler': 18.4.2
+ '@angular-eslint/utils': 18.4.2(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@typescript-eslint/utils': 8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
eslint: 9.15.0(jiti@1.21.6)
typescript: 5.6.3
- '@angular-eslint/schematics@18.4.1(@angular-devkit/core@19.0.0-rc.3(chokidar@4.0.1))(@angular-devkit/schematics@19.0.0-rc.3(chokidar@4.0.1))(@typescript-eslint/types@8.15.0)(@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
+ '@angular-eslint/eslint-plugin@19.0.0-alpha.4(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
dependencies:
- '@angular-devkit/core': 19.0.0-rc.3(chokidar@4.0.1)
- '@angular-devkit/schematics': 19.0.0-rc.3(chokidar@4.0.1)
- '@angular-eslint/eslint-plugin': 18.4.1(@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
- '@angular-eslint/eslint-plugin-template': 18.4.1(@typescript-eslint/types@8.15.0)(@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@angular-eslint/bundled-angular-compiler': 19.0.0-alpha.4
+ '@angular-eslint/utils': 19.0.0-alpha.4(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@typescript-eslint/utils': 8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ eslint: 9.15.0(jiti@1.21.6)
+ typescript: 5.6.3
+
+ '@angular-eslint/schematics@19.0.0-alpha.4(@angular-devkit/core@19.0.2(chokidar@4.0.1))(@angular-devkit/schematics@19.0.2(chokidar@4.0.1))(@typescript-eslint/types@8.16.0)(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
+ dependencies:
+ '@angular-devkit/core': 19.0.2(chokidar@4.0.1)
+ '@angular-devkit/schematics': 19.0.2(chokidar@4.0.1)
+ '@angular-eslint/eslint-plugin': 19.0.0-alpha.4(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@angular-eslint/eslint-plugin-template': 19.0.0-alpha.4(@typescript-eslint/types@8.16.0)(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
ignore: 6.0.2
semver: 7.6.3
strip-json-comments: 3.1.1
@@ -5739,37 +5858,51 @@ snapshots:
- eslint
- typescript
- '@angular-eslint/template-parser@18.4.1(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
+ '@angular-eslint/template-parser@18.4.2(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
+ dependencies:
+ '@angular-eslint/bundled-angular-compiler': 18.4.2
+ eslint: 9.15.0(jiti@1.21.6)
+ eslint-scope: 8.2.0
+ typescript: 5.6.3
+
+ '@angular-eslint/template-parser@19.0.0-alpha.4(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
dependencies:
- '@angular-eslint/bundled-angular-compiler': 18.4.1
+ '@angular-eslint/bundled-angular-compiler': 19.0.0-alpha.4
eslint: 9.15.0(jiti@1.21.6)
eslint-scope: 8.2.0
typescript: 5.6.3
- '@angular-eslint/utils@18.4.1(@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
+ '@angular-eslint/utils@18.4.2(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
dependencies:
- '@angular-eslint/bundled-angular-compiler': 18.4.1
- '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@angular-eslint/bundled-angular-compiler': 18.4.2
+ '@typescript-eslint/utils': 8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
eslint: 9.15.0(jiti@1.21.6)
typescript: 5.6.3
- '@angular/animations@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))':
+ '@angular-eslint/utils@19.0.0-alpha.4(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
dependencies:
- '@angular/core': 19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)
+ '@angular-eslint/bundled-angular-compiler': 19.0.0-alpha.4
+ '@typescript-eslint/utils': 8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ eslint: 9.15.0(jiti@1.21.6)
+ typescript: 5.6.3
+
+ '@angular/animations@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))':
+ dependencies:
+ '@angular/core': 19.0.1(rxjs@7.8.1)(zone.js@0.15.0)
tslib: 2.8.1
- '@angular/build@19.0.0-rc.3(@angular/compiler-cli@19.0.0-rc.3(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3))(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@types/node@22.9.0)(chokidar@4.0.1)(less@4.2.0)(postcss@8.4.49)(tailwindcss@3.4.15)(terser@5.36.0)(typescript@5.6.3)':
+ '@angular/build@19.0.2(@angular/compiler-cli@19.0.1(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3))(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@types/node@22.10.0)(chokidar@4.0.1)(less@4.2.0)(postcss@8.4.49)(tailwindcss@3.4.15)(terser@5.36.0)(typescript@5.6.3)':
dependencies:
'@ampproject/remapping': 2.3.0
- '@angular-devkit/architect': 0.1900.0-rc.3(chokidar@4.0.1)
- '@angular/compiler': 19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))
- '@angular/compiler-cli': 19.0.0-rc.3(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3)
+ '@angular-devkit/architect': 0.1900.2(chokidar@4.0.1)
+ '@angular/compiler': 19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))
+ '@angular/compiler-cli': 19.0.1(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3)
'@babel/core': 7.26.0
'@babel/helper-annotate-as-pure': 7.25.9
'@babel/helper-split-export-declaration': 7.24.7
'@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.0)
- '@inquirer/confirm': 5.0.2(@types/node@22.9.0)
- '@vitejs/plugin-basic-ssl': 1.1.0(vite@5.4.11(@types/node@22.9.0)(less@4.2.0)(sass@1.80.7)(terser@5.36.0))
+ '@inquirer/confirm': 5.0.2(@types/node@22.10.0)
+ '@vitejs/plugin-basic-ssl': 1.1.0(vite@5.4.11(@types/node@22.10.0)(less@4.2.0)(sass@1.80.7)(terser@5.36.0))
beasties: 0.1.0
browserslist: 4.24.2
esbuild: 0.24.0
@@ -5786,7 +5919,7 @@ snapshots:
sass: 1.80.7
semver: 7.6.3
typescript: 5.6.3
- vite: 5.4.11(@types/node@22.9.0)(less@4.2.0)(sass@1.80.7)(terser@5.36.0)
+ vite: 5.4.11(@types/node@22.10.0)(less@4.2.0)(sass@1.80.7)(terser@5.36.0)
watchpack: 2.4.2
optionalDependencies:
less: 4.2.0
@@ -5803,23 +5936,23 @@ snapshots:
- supports-color
- terser
- '@angular/cdk@19.0.0-rc.3(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)':
+ '@angular/cdk@19.0.1(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)':
dependencies:
- '@angular/common': 19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
- '@angular/core': 19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)
+ '@angular/common': 19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
+ '@angular/core': 19.0.1(rxjs@7.8.1)(zone.js@0.15.0)
rxjs: 7.8.1
tslib: 2.8.1
optionalDependencies:
parse5: 7.2.1
- '@angular/cli@19.0.0-rc.3(@types/node@22.9.0)(chokidar@4.0.1)':
+ '@angular/cli@19.0.2(@types/node@22.10.0)(chokidar@4.0.1)':
dependencies:
- '@angular-devkit/architect': 0.1900.0-rc.3(chokidar@4.0.1)
- '@angular-devkit/core': 19.0.0-rc.3(chokidar@4.0.1)
- '@angular-devkit/schematics': 19.0.0-rc.3(chokidar@4.0.1)
- '@inquirer/prompts': 7.1.0(@types/node@22.9.0)
- '@listr2/prompt-adapter-inquirer': 2.0.18(@inquirer/prompts@7.1.0(@types/node@22.9.0))
- '@schematics/angular': 19.0.0-rc.3(chokidar@4.0.1)
+ '@angular-devkit/architect': 0.1900.2(chokidar@4.0.1)
+ '@angular-devkit/core': 19.0.2(chokidar@4.0.1)
+ '@angular-devkit/schematics': 19.0.2(chokidar@4.0.1)
+ '@inquirer/prompts': 7.1.0(@types/node@22.10.0)
+ '@listr2/prompt-adapter-inquirer': 2.0.18(@inquirer/prompts@7.1.0(@types/node@22.10.0))
+ '@schematics/angular': 19.0.2(chokidar@4.0.1)
'@yarnpkg/lockfile': 1.1.0
ini: 5.0.0
jsonc-parser: 3.3.1
@@ -5837,15 +5970,15 @@ snapshots:
- chokidar
- supports-color
- '@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)':
+ '@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)':
dependencies:
- '@angular/core': 19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)
+ '@angular/core': 19.0.1(rxjs@7.8.1)(zone.js@0.15.0)
rxjs: 7.8.1
tslib: 2.8.1
- '@angular/compiler-cli@19.0.0-rc.3(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3)':
+ '@angular/compiler-cli@19.0.1(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3)':
dependencies:
- '@angular/compiler': 19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))
+ '@angular/compiler': 19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))
'@babel/core': 7.26.0
'@jridgewell/sourcemap-codec': 1.5.0
chokidar: 4.0.1
@@ -5858,58 +5991,58 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))':
+ '@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))':
dependencies:
tslib: 2.8.1
optionalDependencies:
- '@angular/core': 19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)
+ '@angular/core': 19.0.1(rxjs@7.8.1)(zone.js@0.15.0)
- '@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)':
+ '@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)':
dependencies:
rxjs: 7.8.1
tslib: 2.8.1
zone.js: 0.15.0
- '@angular/forms@19.0.0-rc.3(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.0.0-rc.3(@angular/animations@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1)':
+ '@angular/forms@19.0.1(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.0.1(@angular/animations@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1)':
dependencies:
- '@angular/common': 19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
- '@angular/core': 19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)
- '@angular/platform-browser': 19.0.0-rc.3(@angular/animations@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))
+ '@angular/common': 19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
+ '@angular/core': 19.0.1(rxjs@7.8.1)(zone.js@0.15.0)
+ '@angular/platform-browser': 19.0.1(@angular/animations@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))
rxjs: 7.8.1
tslib: 2.8.1
- '@angular/material@19.0.0-rc.3(2ggkf5bmbgan54h663qv7i4v7a)':
+ '@angular/material@19.0.1(caeb6eiffeog75fr4ymtnaa34q)':
dependencies:
- '@angular/animations': 19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))
- '@angular/cdk': 19.0.0-rc.3(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
- '@angular/common': 19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
- '@angular/core': 19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)
- '@angular/forms': 19.0.0-rc.3(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.0.0-rc.3(@angular/animations@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1)
- '@angular/platform-browser': 19.0.0-rc.3(@angular/animations@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))
+ '@angular/animations': 19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))
+ '@angular/cdk': 19.0.1(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
+ '@angular/common': 19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
+ '@angular/core': 19.0.1(rxjs@7.8.1)(zone.js@0.15.0)
+ '@angular/forms': 19.0.1(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.0.1(@angular/animations@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1)
+ '@angular/platform-browser': 19.0.1(@angular/animations@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))
rxjs: 7.8.1
tslib: 2.8.1
- '@angular/platform-browser-dynamic@19.0.0-rc.3(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.0.0-rc.3(@angular/animations@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))':
+ '@angular/platform-browser-dynamic@19.0.1(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.0.1(@angular/animations@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))':
dependencies:
- '@angular/common': 19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
- '@angular/compiler': 19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))
- '@angular/core': 19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)
- '@angular/platform-browser': 19.0.0-rc.3(@angular/animations@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))
+ '@angular/common': 19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
+ '@angular/compiler': 19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))
+ '@angular/core': 19.0.1(rxjs@7.8.1)(zone.js@0.15.0)
+ '@angular/platform-browser': 19.0.1(@angular/animations@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))
tslib: 2.8.1
- '@angular/platform-browser@19.0.0-rc.3(@angular/animations@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))':
+ '@angular/platform-browser@19.0.1(@angular/animations@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))':
dependencies:
- '@angular/common': 19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
- '@angular/core': 19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)
+ '@angular/common': 19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
+ '@angular/core': 19.0.1(rxjs@7.8.1)(zone.js@0.15.0)
tslib: 2.8.1
optionalDependencies:
- '@angular/animations': 19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))
+ '@angular/animations': 19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))
- '@angular/router@19.0.0-rc.3(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.0.0-rc.3(@angular/animations@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1)':
+ '@angular/router@19.0.1(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(@angular/platform-browser@19.0.1(@angular/animations@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(rxjs@7.8.1)':
dependencies:
- '@angular/common': 19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
- '@angular/core': 19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)
- '@angular/platform-browser': 19.0.0-rc.3(@angular/animations@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0))
+ '@angular/common': 19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1)
+ '@angular/core': 19.0.1(rxjs@7.8.1)(zone.js@0.15.0)
+ '@angular/platform-browser': 19.0.1(@angular/animations@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(@angular/common@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0))
rxjs: 7.8.1
tslib: 2.8.1
@@ -6018,14 +6151,14 @@ snapshots:
dependencies:
'@babel/core': 7.25.8
'@babel/helper-annotate-as-pure': 7.25.9
- regexpu-core: 6.1.1
+ regexpu-core: 6.2.0
semver: 6.3.1
'@babel/helper-create-regexp-features-plugin@7.25.9(@babel/core@7.26.0)':
dependencies:
'@babel/core': 7.26.0
'@babel/helper-annotate-as-pure': 7.25.9
- regexpu-core: 6.1.1
+ regexpu-core: 6.2.0
semver: 6.3.1
'@babel/helper-define-polyfill-provider@0.6.3(@babel/core@7.25.8)':
@@ -7127,7 +7260,7 @@ snapshots:
'@babel/preset-env': 7.25.8(@babel/core@7.25.8)
'@compodoc/live-server': 1.2.3
'@compodoc/ngd-transformer': 2.1.3
- bootstrap.native: 5.0.13
+ bootstrap.native: 5.1.1
cheerio: 1.0.0-rc.12
chokidar: 4.0.1
colors: 1.4.0
@@ -7141,7 +7274,7 @@ snapshots:
glob: 11.0.0
handlebars: 4.7.8
html-entities: 2.5.2
- i18next: 23.16.5
+ i18next: 23.16.8
json5: 2.2.3
lodash: 4.17.21
loglevel: 1.9.2
@@ -7406,25 +7539,25 @@ snapshots:
'@humanwhocodes/retry@0.4.1': {}
- '@inquirer/checkbox@4.0.2(@types/node@22.9.0)':
+ '@inquirer/checkbox@4.0.2(@types/node@22.10.0)':
dependencies:
- '@inquirer/core': 10.1.0(@types/node@22.9.0)
+ '@inquirer/core': 10.1.0(@types/node@22.10.0)
'@inquirer/figures': 1.0.8
- '@inquirer/type': 3.0.1(@types/node@22.9.0)
- '@types/node': 22.9.0
+ '@inquirer/type': 3.0.1(@types/node@22.10.0)
+ '@types/node': 22.10.0
ansi-escapes: 4.3.2
yoctocolors-cjs: 2.1.2
- '@inquirer/confirm@5.0.2(@types/node@22.9.0)':
+ '@inquirer/confirm@5.0.2(@types/node@22.10.0)':
dependencies:
- '@inquirer/core': 10.1.0(@types/node@22.9.0)
- '@inquirer/type': 3.0.1(@types/node@22.9.0)
- '@types/node': 22.9.0
+ '@inquirer/core': 10.1.0(@types/node@22.10.0)
+ '@inquirer/type': 3.0.1(@types/node@22.10.0)
+ '@types/node': 22.10.0
- '@inquirer/core@10.1.0(@types/node@22.9.0)':
+ '@inquirer/core@10.1.0(@types/node@22.10.0)':
dependencies:
'@inquirer/figures': 1.0.8
- '@inquirer/type': 3.0.1(@types/node@22.9.0)
+ '@inquirer/type': 3.0.1(@types/node@22.10.0)
ansi-escapes: 4.3.2
cli-width: 4.1.0
mute-stream: 2.0.0
@@ -7435,76 +7568,76 @@ snapshots:
transitivePeerDependencies:
- '@types/node'
- '@inquirer/editor@4.1.0(@types/node@22.9.0)':
+ '@inquirer/editor@4.1.0(@types/node@22.10.0)':
dependencies:
- '@inquirer/core': 10.1.0(@types/node@22.9.0)
- '@inquirer/type': 3.0.1(@types/node@22.9.0)
- '@types/node': 22.9.0
+ '@inquirer/core': 10.1.0(@types/node@22.10.0)
+ '@inquirer/type': 3.0.1(@types/node@22.10.0)
+ '@types/node': 22.10.0
external-editor: 3.1.0
- '@inquirer/expand@4.0.2(@types/node@22.9.0)':
+ '@inquirer/expand@4.0.2(@types/node@22.10.0)':
dependencies:
- '@inquirer/core': 10.1.0(@types/node@22.9.0)
- '@inquirer/type': 3.0.1(@types/node@22.9.0)
- '@types/node': 22.9.0
+ '@inquirer/core': 10.1.0(@types/node@22.10.0)
+ '@inquirer/type': 3.0.1(@types/node@22.10.0)
+ '@types/node': 22.10.0
yoctocolors-cjs: 2.1.2
'@inquirer/figures@1.0.8': {}
- '@inquirer/input@4.0.2(@types/node@22.9.0)':
+ '@inquirer/input@4.0.2(@types/node@22.10.0)':
dependencies:
- '@inquirer/core': 10.1.0(@types/node@22.9.0)
- '@inquirer/type': 3.0.1(@types/node@22.9.0)
- '@types/node': 22.9.0
+ '@inquirer/core': 10.1.0(@types/node@22.10.0)
+ '@inquirer/type': 3.0.1(@types/node@22.10.0)
+ '@types/node': 22.10.0
- '@inquirer/number@3.0.2(@types/node@22.9.0)':
+ '@inquirer/number@3.0.2(@types/node@22.10.0)':
dependencies:
- '@inquirer/core': 10.1.0(@types/node@22.9.0)
- '@inquirer/type': 3.0.1(@types/node@22.9.0)
- '@types/node': 22.9.0
+ '@inquirer/core': 10.1.0(@types/node@22.10.0)
+ '@inquirer/type': 3.0.1(@types/node@22.10.0)
+ '@types/node': 22.10.0
- '@inquirer/password@4.0.2(@types/node@22.9.0)':
+ '@inquirer/password@4.0.2(@types/node@22.10.0)':
dependencies:
- '@inquirer/core': 10.1.0(@types/node@22.9.0)
- '@inquirer/type': 3.0.1(@types/node@22.9.0)
- '@types/node': 22.9.0
+ '@inquirer/core': 10.1.0(@types/node@22.10.0)
+ '@inquirer/type': 3.0.1(@types/node@22.10.0)
+ '@types/node': 22.10.0
ansi-escapes: 4.3.2
- '@inquirer/prompts@7.1.0(@types/node@22.9.0)':
- dependencies:
- '@inquirer/checkbox': 4.0.2(@types/node@22.9.0)
- '@inquirer/confirm': 5.0.2(@types/node@22.9.0)
- '@inquirer/editor': 4.1.0(@types/node@22.9.0)
- '@inquirer/expand': 4.0.2(@types/node@22.9.0)
- '@inquirer/input': 4.0.2(@types/node@22.9.0)
- '@inquirer/number': 3.0.2(@types/node@22.9.0)
- '@inquirer/password': 4.0.2(@types/node@22.9.0)
- '@inquirer/rawlist': 4.0.2(@types/node@22.9.0)
- '@inquirer/search': 3.0.2(@types/node@22.9.0)
- '@inquirer/select': 4.0.2(@types/node@22.9.0)
- '@types/node': 22.9.0
-
- '@inquirer/rawlist@4.0.2(@types/node@22.9.0)':
- dependencies:
- '@inquirer/core': 10.1.0(@types/node@22.9.0)
- '@inquirer/type': 3.0.1(@types/node@22.9.0)
- '@types/node': 22.9.0
+ '@inquirer/prompts@7.1.0(@types/node@22.10.0)':
+ dependencies:
+ '@inquirer/checkbox': 4.0.2(@types/node@22.10.0)
+ '@inquirer/confirm': 5.0.2(@types/node@22.10.0)
+ '@inquirer/editor': 4.1.0(@types/node@22.10.0)
+ '@inquirer/expand': 4.0.2(@types/node@22.10.0)
+ '@inquirer/input': 4.0.2(@types/node@22.10.0)
+ '@inquirer/number': 3.0.2(@types/node@22.10.0)
+ '@inquirer/password': 4.0.2(@types/node@22.10.0)
+ '@inquirer/rawlist': 4.0.2(@types/node@22.10.0)
+ '@inquirer/search': 3.0.2(@types/node@22.10.0)
+ '@inquirer/select': 4.0.2(@types/node@22.10.0)
+ '@types/node': 22.10.0
+
+ '@inquirer/rawlist@4.0.2(@types/node@22.10.0)':
+ dependencies:
+ '@inquirer/core': 10.1.0(@types/node@22.10.0)
+ '@inquirer/type': 3.0.1(@types/node@22.10.0)
+ '@types/node': 22.10.0
yoctocolors-cjs: 2.1.2
- '@inquirer/search@3.0.2(@types/node@22.9.0)':
+ '@inquirer/search@3.0.2(@types/node@22.10.0)':
dependencies:
- '@inquirer/core': 10.1.0(@types/node@22.9.0)
+ '@inquirer/core': 10.1.0(@types/node@22.10.0)
'@inquirer/figures': 1.0.8
- '@inquirer/type': 3.0.1(@types/node@22.9.0)
- '@types/node': 22.9.0
+ '@inquirer/type': 3.0.1(@types/node@22.10.0)
+ '@types/node': 22.10.0
yoctocolors-cjs: 2.1.2
- '@inquirer/select@4.0.2(@types/node@22.9.0)':
+ '@inquirer/select@4.0.2(@types/node@22.10.0)':
dependencies:
- '@inquirer/core': 10.1.0(@types/node@22.9.0)
+ '@inquirer/core': 10.1.0(@types/node@22.10.0)
'@inquirer/figures': 1.0.8
- '@inquirer/type': 3.0.1(@types/node@22.9.0)
- '@types/node': 22.9.0
+ '@inquirer/type': 3.0.1(@types/node@22.10.0)
+ '@types/node': 22.10.0
ansi-escapes: 4.3.2
yoctocolors-cjs: 2.1.2
@@ -7512,9 +7645,9 @@ snapshots:
dependencies:
mute-stream: 1.0.0
- '@inquirer/type@3.0.1(@types/node@22.9.0)':
+ '@inquirer/type@3.0.1(@types/node@22.10.0)':
dependencies:
- '@types/node': 22.9.0
+ '@types/node': 22.10.0
'@isaacs/cliui@8.0.2':
dependencies:
@@ -7571,9 +7704,9 @@ snapshots:
'@leichtgewicht/ip-codec@2.0.5': {}
- '@listr2/prompt-adapter-inquirer@2.0.18(@inquirer/prompts@7.1.0(@types/node@22.9.0))':
+ '@listr2/prompt-adapter-inquirer@2.0.18(@inquirer/prompts@7.1.0(@types/node@22.10.0))':
dependencies:
- '@inquirer/prompts': 7.1.0(@types/node@22.9.0)
+ '@inquirer/prompts': 7.1.0(@types/node@22.10.0)
'@inquirer/type': 1.5.5
'@lmdb/lmdb-darwin-arm64@3.1.5':
@@ -7680,9 +7813,9 @@ snapshots:
'@napi-rs/nice-win32-x64-msvc': 1.0.1
optional: true
- '@ngtools/webpack@19.0.0-rc.3(@angular/compiler-cli@19.0.0-rc.3(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3))(typescript@5.6.3)(webpack@5.96.1(esbuild@0.24.0))':
+ '@ngtools/webpack@19.0.2(@angular/compiler-cli@19.0.1(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3))(typescript@5.6.3)(webpack@5.96.1(esbuild@0.24.0))':
dependencies:
- '@angular/compiler-cli': 19.0.0-rc.3(@angular/compiler@19.0.0-rc.3(@angular/core@19.0.0-rc.3(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3)
+ '@angular/compiler-cli': 19.0.1(@angular/compiler@19.0.1(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)))(typescript@5.6.3)
typescript: 5.6.3
webpack: 5.96.1(esbuild@0.24.0)
@@ -7753,7 +7886,7 @@ snapshots:
dependencies:
'@npmcli/git': 6.0.1
glob: 10.4.5
- hosted-git-info: 8.0.0
+ hosted-git-info: 8.0.2
json-parse-even-better-errors: 4.0.0
normalize-package-data: 7.0.0
proc-log: 5.0.0
@@ -7899,10 +8032,10 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.26.0':
optional: true
- '@schematics/angular@19.0.0-rc.3(chokidar@4.0.1)':
+ '@schematics/angular@19.0.2(chokidar@4.0.1)':
dependencies:
- '@angular-devkit/core': 19.0.0-rc.3(chokidar@4.0.1)
- '@angular-devkit/schematics': 19.0.0-rc.3(chokidar@4.0.1)
+ '@angular-devkit/core': 19.0.2(chokidar@4.0.1)
+ '@angular-devkit/schematics': 19.0.2(chokidar@4.0.1)
jsonc-parser: 3.3.1
transitivePeerDependencies:
- chokidar
@@ -7945,7 +8078,11 @@ snapshots:
'@thednp/event-listener@2.0.8': {}
- '@thednp/shorty@2.0.7': {}
+ '@thednp/position-observer@1.0.5':
+ dependencies:
+ '@thednp/shorty': 2.0.9
+
+ '@thednp/shorty@2.0.9': {}
'@ts-morph/common@0.25.0':
dependencies:
@@ -7963,26 +8100,26 @@ snapshots:
'@types/body-parser@1.19.5':
dependencies:
'@types/connect': 3.4.38
- '@types/node': 22.9.0
+ '@types/node': 22.10.0
'@types/bonjour@3.5.13':
dependencies:
- '@types/node': 22.9.0
+ '@types/node': 22.10.0
'@types/connect-history-api-fallback@1.5.4':
dependencies:
- '@types/express-serve-static-core': 5.0.1
- '@types/node': 22.9.0
+ '@types/express-serve-static-core': 5.0.2
+ '@types/node': 22.10.0
'@types/connect@3.4.38':
dependencies:
- '@types/node': 22.9.0
+ '@types/node': 22.10.0
'@types/cookie@0.4.1': {}
'@types/cors@2.8.17':
dependencies:
- '@types/node': 22.9.0
+ '@types/node': 22.10.0
'@types/debug@4.1.12':
dependencies:
@@ -8002,14 +8139,14 @@ snapshots:
'@types/express-serve-static-core@4.19.6':
dependencies:
- '@types/node': 22.9.0
+ '@types/node': 22.10.0
'@types/qs': 6.9.17
'@types/range-parser': 1.2.7
'@types/send': 0.17.4
- '@types/express-serve-static-core@5.0.1':
+ '@types/express-serve-static-core@5.0.2':
dependencies:
- '@types/node': 22.9.0
+ '@types/node': 22.10.0
'@types/qs': 6.9.17
'@types/range-parser': 1.2.7
'@types/send': 0.17.4
@@ -8025,7 +8162,7 @@ snapshots:
'@types/http-proxy@1.17.15':
dependencies:
- '@types/node': 22.9.0
+ '@types/node': 22.10.0
'@types/jasmine@5.1.4': {}
@@ -8041,11 +8178,11 @@ snapshots:
'@types/node-forge@1.3.11':
dependencies:
- '@types/node': 22.9.0
+ '@types/node': 22.10.0
- '@types/node@22.9.0':
+ '@types/node@22.10.0':
dependencies:
- undici-types: 6.19.8
+ undici-types: 6.20.0
'@types/qs@6.9.17': {}
@@ -8056,7 +8193,7 @@ snapshots:
'@types/send@0.17.4':
dependencies:
'@types/mime': 1.3.5
- '@types/node': 22.9.0
+ '@types/node': 22.10.0
'@types/serve-index@1.9.4':
dependencies:
@@ -8065,43 +8202,43 @@ snapshots:
'@types/serve-static@1.15.7':
dependencies:
'@types/http-errors': 2.0.4
- '@types/node': 22.9.0
+ '@types/node': 22.10.0
'@types/send': 0.17.4
'@types/sockjs@0.3.36':
dependencies:
- '@types/node': 22.9.0
+ '@types/node': 22.10.0
'@types/unist@3.0.3': {}
'@types/ws@8.5.13':
dependencies:
- '@types/node': 22.9.0
+ '@types/node': 22.10.0
- '@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
+ '@typescript-eslint/eslint-plugin@8.16.0(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
- '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
- '@typescript-eslint/scope-manager': 8.15.0
- '@typescript-eslint/type-utils': 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
- '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
- '@typescript-eslint/visitor-keys': 8.15.0
+ '@typescript-eslint/parser': 8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@typescript-eslint/scope-manager': 8.16.0
+ '@typescript-eslint/type-utils': 8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@typescript-eslint/utils': 8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@typescript-eslint/visitor-keys': 8.16.0
eslint: 9.15.0(jiti@1.21.6)
graphemer: 1.4.0
ignore: 5.3.2
natural-compare: 1.4.0
- ts-api-utils: 1.4.0(typescript@5.6.3)
+ ts-api-utils: 1.4.2(typescript@5.6.3)
optionalDependencies:
typescript: 5.6.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
+ '@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
dependencies:
- '@typescript-eslint/scope-manager': 8.15.0
- '@typescript-eslint/types': 8.15.0
- '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.6.3)
- '@typescript-eslint/visitor-keys': 8.15.0
+ '@typescript-eslint/scope-manager': 8.16.0
+ '@typescript-eslint/types': 8.16.0
+ '@typescript-eslint/typescript-estree': 8.16.0(typescript@5.6.3)
+ '@typescript-eslint/visitor-keys': 8.16.0
debug: 4.3.7
eslint: 9.15.0(jiti@1.21.6)
optionalDependencies:
@@ -8109,60 +8246,60 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/scope-manager@8.15.0':
+ '@typescript-eslint/scope-manager@8.16.0':
dependencies:
- '@typescript-eslint/types': 8.15.0
- '@typescript-eslint/visitor-keys': 8.15.0
+ '@typescript-eslint/types': 8.16.0
+ '@typescript-eslint/visitor-keys': 8.16.0
- '@typescript-eslint/type-utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
+ '@typescript-eslint/type-utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
dependencies:
- '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.6.3)
- '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@typescript-eslint/typescript-estree': 8.16.0(typescript@5.6.3)
+ '@typescript-eslint/utils': 8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
debug: 4.3.7
eslint: 9.15.0(jiti@1.21.6)
- ts-api-utils: 1.4.0(typescript@5.6.3)
+ ts-api-utils: 1.4.2(typescript@5.6.3)
optionalDependencies:
typescript: 5.6.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/types@8.15.0': {}
+ '@typescript-eslint/types@8.16.0': {}
- '@typescript-eslint/typescript-estree@8.15.0(typescript@5.6.3)':
+ '@typescript-eslint/typescript-estree@8.16.0(typescript@5.6.3)':
dependencies:
- '@typescript-eslint/types': 8.15.0
- '@typescript-eslint/visitor-keys': 8.15.0
+ '@typescript-eslint/types': 8.16.0
+ '@typescript-eslint/visitor-keys': 8.16.0
debug: 4.3.7
fast-glob: 3.3.2
is-glob: 4.0.3
minimatch: 9.0.5
semver: 7.6.3
- ts-api-utils: 1.4.0(typescript@5.6.3)
+ ts-api-utils: 1.4.2(typescript@5.6.3)
optionalDependencies:
typescript: 5.6.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
+ '@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)':
dependencies:
'@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0(jiti@1.21.6))
- '@typescript-eslint/scope-manager': 8.15.0
- '@typescript-eslint/types': 8.15.0
- '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.6.3)
+ '@typescript-eslint/scope-manager': 8.16.0
+ '@typescript-eslint/types': 8.16.0
+ '@typescript-eslint/typescript-estree': 8.16.0(typescript@5.6.3)
eslint: 9.15.0(jiti@1.21.6)
optionalDependencies:
typescript: 5.6.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/visitor-keys@8.15.0':
+ '@typescript-eslint/visitor-keys@8.16.0':
dependencies:
- '@typescript-eslint/types': 8.15.0
+ '@typescript-eslint/types': 8.16.0
eslint-visitor-keys: 4.2.0
- '@vitejs/plugin-basic-ssl@1.1.0(vite@5.4.11(@types/node@22.9.0)(less@4.2.0)(sass@1.80.7)(terser@5.36.0))':
+ '@vitejs/plugin-basic-ssl@1.1.0(vite@5.4.11(@types/node@22.10.0)(less@4.2.0)(sass@1.80.7)(terser@5.36.0))':
dependencies:
- vite: 5.4.11(@types/node@22.9.0)(less@4.2.0)(sass@1.80.7)(terser@5.36.0)
+ vite: 5.4.11(@types/node@22.10.0)(less@4.2.0)(sass@1.80.7)(terser@5.36.0)
'@webassemblyjs/ast@1.14.1':
dependencies:
@@ -8306,22 +8443,28 @@ snapshots:
json-schema-traverse: 1.0.0
require-from-string: 2.0.2
- angular-eslint@18.4.1(@angular-devkit/core@19.0.0-rc.3(chokidar@4.0.1))(@angular-devkit/schematics@19.0.0-rc.3(chokidar@4.0.1))(@typescript-eslint/types@8.15.0)(@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript-eslint@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(typescript@5.6.3):
+ angular-eslint@19.0.0-alpha.4(@angular-devkit/core@19.0.2(chokidar@4.0.1))(@angular-devkit/schematics@19.0.2(chokidar@4.0.1))(@typescript-eslint/types@8.16.0)(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript-eslint@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(typescript@5.6.3):
dependencies:
- '@angular-eslint/builder': 18.4.1(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
- '@angular-eslint/eslint-plugin': 18.4.1(@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
- '@angular-eslint/eslint-plugin-template': 18.4.1(@typescript-eslint/types@8.15.0)(@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
- '@angular-eslint/schematics': 18.4.1(@angular-devkit/core@19.0.0-rc.3(chokidar@4.0.1))(@angular-devkit/schematics@19.0.0-rc.3(chokidar@4.0.1))(@typescript-eslint/types@8.15.0)(@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
- '@angular-eslint/template-parser': 18.4.1(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@angular-eslint/builder': 19.0.0-alpha.4(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@angular-eslint/eslint-plugin': 19.0.0-alpha.4(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@angular-eslint/eslint-plugin-template': 19.0.0-alpha.4(@typescript-eslint/types@8.16.0)(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@angular-eslint/schematics': 19.0.0-alpha.4(@angular-devkit/core@19.0.2(chokidar@4.0.1))(@angular-devkit/schematics@19.0.2(chokidar@4.0.1))(@typescript-eslint/types@8.16.0)(@typescript-eslint/utils@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@angular-eslint/template-parser': 19.0.0-alpha.4(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
eslint: 9.15.0(jiti@1.21.6)
typescript: 5.6.3
- typescript-eslint: 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ typescript-eslint: 8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
transitivePeerDependencies:
- '@angular-devkit/core'
- '@angular-devkit/schematics'
- '@typescript-eslint/types'
- '@typescript-eslint/utils'
+ angularx-qrcode@19.0.0(@angular/core@19.0.1(rxjs@7.8.1)(zone.js@0.15.0)):
+ dependencies:
+ '@angular/core': 19.0.1(rxjs@7.8.1)(zone.js@0.15.0)
+ qrcode: 1.5.4
+ tslib: 2.8.1
+
ansi-colors@4.1.3: {}
ansi-escapes@4.3.2:
@@ -8370,7 +8513,7 @@ snapshots:
autoprefixer@10.4.20(postcss@8.4.49):
dependencies:
browserslist: 4.24.2
- caniuse-lite: 1.0.30001680
+ caniuse-lite: 1.0.30001684
fraction.js: 4.3.7
normalize-range: 0.1.2
picocolors: 1.1.1
@@ -8493,10 +8636,11 @@ snapshots:
boolbase@1.0.0: {}
- bootstrap.native@5.0.13:
+ bootstrap.native@5.1.1:
dependencies:
'@thednp/event-listener': 2.0.8
- '@thednp/shorty': 2.0.7
+ '@thednp/position-observer': 1.0.5
+ '@thednp/shorty': 2.0.9
brace-expansion@1.1.11:
dependencies:
@@ -8513,8 +8657,8 @@ snapshots:
browserslist@4.24.2:
dependencies:
- caniuse-lite: 1.0.30001680
- electron-to-chromium: 1.5.63
+ caniuse-lite: 1.0.30001684
+ electron-to-chromium: 1.5.65
node-releases: 2.0.18
update-browserslist-db: 1.1.1(browserslist@4.24.2)
@@ -8575,7 +8719,9 @@ snapshots:
camelcase-css@2.0.1: {}
- caniuse-lite@1.0.30001680: {}
+ camelcase@5.3.1: {}
+
+ caniuse-lite@1.0.30001684: {}
ccount@2.0.1: {}
@@ -8648,6 +8794,12 @@ snapshots:
cli-width@4.1.0: {}
+ cliui@6.0.0:
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 6.2.0
+
cliui@7.0.4:
dependencies:
string-width: 4.2.3
@@ -8822,6 +8974,8 @@ snapshots:
dependencies:
callsite: 1.0.0
+ decamelize@1.2.0: {}
+
decode-named-character-reference@1.0.2:
dependencies:
character-entities: 2.0.2
@@ -8873,6 +9027,8 @@ snapshots:
didyoumean@1.2.2: {}
+ dijkstrajs@1.0.3: {}
+
dlv@1.1.3: {}
dns-packet@5.6.1:
@@ -8912,7 +9068,7 @@ snapshots:
ee-first@1.1.1: {}
- electron-to-chromium@1.5.63: {}
+ electron-to-chromium@1.5.65: {}
emitter-component@1.1.2: {}
@@ -8943,7 +9099,7 @@ snapshots:
dependencies:
'@types/cookie': 0.4.1
'@types/cors': 2.8.17
- '@types/node': 22.9.0
+ '@types/node': 22.10.0
accepts: 1.3.8
base64id: 2.0.0
cookie: 0.7.2
@@ -9067,16 +9223,16 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6)):
+ eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6)):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.3.7
enhanced-resolve: 5.17.1
eslint: 9.15.0(jiti@1.21.6)
- eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6)))(eslint@9.15.0(jiti@1.21.6))
+ eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6)))(eslint@9.15.0(jiti@1.21.6))
fast-glob: 3.3.2
get-tsconfig: 4.8.1
- is-bun-module: 1.2.1
+ is-bun-module: 1.3.0
is-glob: 4.0.3
transitivePeerDependencies:
- '@typescript-eslint/parser'
@@ -9084,23 +9240,23 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
- eslint-module-utils@2.12.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6)))(eslint@9.15.0(jiti@1.21.6)):
+ eslint-module-utils@2.12.0(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6)))(eslint@9.15.0(jiti@1.21.6)):
dependencies:
debug: 3.2.7
optionalDependencies:
- '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@typescript-eslint/parser': 8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
eslint: 9.15.0(jiti@1.21.6)
eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))
+ eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))
transitivePeerDependencies:
- supports-color
- eslint-plugin-boundaries@5.0.1(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6)))(eslint@9.15.0(jiti@1.21.6)):
+ eslint-plugin-boundaries@5.0.1(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6)))(eslint@9.15.0(jiti@1.21.6)):
dependencies:
chalk: 4.1.2
eslint: 9.15.0(jiti@1.21.6)
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6)))(eslint@9.15.0(jiti@1.21.6))
+ eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6)))(eslint@9.15.0(jiti@1.21.6))
micromatch: 4.0.8
transitivePeerDependencies:
- '@typescript-eslint/parser'
@@ -9108,7 +9264,7 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
- eslint-plugin-jsdoc@50.5.0(eslint@9.15.0(jiti@1.21.6)):
+ eslint-plugin-jsdoc@50.6.0(eslint@9.15.0(jiti@1.21.6)):
dependencies:
'@es-joy/jsdoccomment': 0.49.0
are-docs-informative: 0.0.2
@@ -9357,6 +9513,11 @@ snapshots:
common-path-prefix: 3.0.0
pkg-dir: 7.0.0
+ find-up@4.1.0:
+ dependencies:
+ locate-path: 5.0.0
+ path-exists: 4.0.0
+
find-up@5.0.0:
dependencies:
locate-path: 6.0.0
@@ -9527,7 +9688,7 @@ snapshots:
dependencies:
function-bind: 1.1.2
- hosted-git-info@8.0.0:
+ hosted-git-info@8.0.2:
dependencies:
lru-cache: 10.4.3
@@ -9637,7 +9798,7 @@ snapshots:
hyperdyperid@1.2.0: {}
- i18next@23.16.5:
+ i18next@23.16.8:
dependencies:
'@babel/runtime': 7.26.0
@@ -9666,7 +9827,7 @@ snapshots:
image-size@0.5.5:
optional: true
- immutable@5.0.2: {}
+ immutable@5.0.3: {}
import-fresh@3.3.0:
dependencies:
@@ -9703,7 +9864,7 @@ snapshots:
dependencies:
binary-extensions: 2.3.0
- is-bun-module@1.2.1:
+ is-bun-module@1.3.0:
dependencies:
semver: 7.6.3
@@ -9830,7 +9991,7 @@ snapshots:
jest-worker@27.5.1:
dependencies:
- '@types/node': 22.9.0
+ '@types/node': 22.10.0
merge-stream: 2.0.0
supports-color: 8.1.1
@@ -9876,6 +10037,8 @@ snapshots:
jsonparse@1.3.1: {}
+ jwt-decode@4.0.0: {}
+
karma-chrome-launcher@3.2.0:
dependencies:
which: 1.3.1
@@ -10023,6 +10186,10 @@ snapshots:
loader-utils@3.3.1: {}
+ locate-path@5.0.0:
+ dependencies:
+ p-locate: 4.1.0
+
locate-path@6.0.0:
dependencies:
p-locate: 5.0.0
@@ -10269,7 +10436,7 @@ snapshots:
micromark-util-html-tag-name: 2.0.1
micromark-util-normalize-identifier: 2.0.1
micromark-util-resolve-all: 2.0.1
- micromark-util-subtokenize: 2.0.2
+ micromark-util-subtokenize: 2.0.3
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.1
@@ -10412,7 +10579,7 @@ snapshots:
micromark-util-encode: 2.0.1
micromark-util-symbol: 2.0.1
- micromark-util-subtokenize@2.0.2:
+ micromark-util-subtokenize@2.0.3:
dependencies:
devlop: 1.1.0
micromark-util-chunked: 2.0.1
@@ -10439,7 +10606,7 @@ snapshots:
micromark-util-normalize-identifier: 2.0.1
micromark-util-resolve-all: 2.0.1
micromark-util-sanitize-uri: 2.0.1
- micromark-util-subtokenize: 2.0.2
+ micromark-util-subtokenize: 2.0.3
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.1
transitivePeerDependencies:
@@ -10596,7 +10763,7 @@ snapshots:
object-assign: 4.1.1
thenify-all: 1.6.0
- nanoid@3.3.7: {}
+ nanoid@3.3.8: {}
natural-compare@1.4.0: {}
@@ -10652,7 +10819,7 @@ snapshots:
normalize-package-data@7.0.0:
dependencies:
- hosted-git-info: 8.0.0
+ hosted-git-info: 8.0.2
semver: 7.6.3
validate-npm-package-license: 3.0.4
@@ -10664,7 +10831,7 @@ snapshots:
dependencies:
npm-normalize-package-bin: 4.0.0
- npm-install-checks@7.1.0:
+ npm-install-checks@7.1.1:
dependencies:
semver: 7.6.3
@@ -10672,7 +10839,7 @@ snapshots:
npm-package-arg@12.0.0:
dependencies:
- hosted-git-info: 8.0.0
+ hosted-git-info: 8.0.2
proc-log: 5.0.0
semver: 7.6.3
validate-npm-package-name: 6.0.0
@@ -10683,7 +10850,7 @@ snapshots:
npm-pick-manifest@10.0.0:
dependencies:
- npm-install-checks: 7.1.0
+ npm-install-checks: 7.1.1
npm-normalize-package-bin: 4.0.0
npm-package-arg: 12.0.0
semver: 7.6.3
@@ -10717,6 +10884,10 @@ snapshots:
obuf@1.1.2: {}
+ oidc-client-ts@3.1.0:
+ dependencies:
+ jwt-decode: 4.0.0
+
on-finished@2.3.0:
dependencies:
ee-first: 1.1.1
@@ -10785,6 +10956,10 @@ snapshots:
os-tmpdir@1.0.2: {}
+ p-limit@2.3.0:
+ dependencies:
+ p-try: 2.2.0
+
p-limit@3.1.0:
dependencies:
yocto-queue: 0.1.0
@@ -10793,6 +10968,10 @@ snapshots:
dependencies:
yocto-queue: 1.1.1
+ p-locate@4.1.0:
+ dependencies:
+ p-limit: 2.3.0
+
p-locate@5.0.0:
dependencies:
p-limit: 3.1.0
@@ -10813,6 +10992,8 @@ snapshots:
is-network-error: 1.1.0
retry: 0.13.1
+ p-try@2.2.0: {}
+
package-json-from-dist@1.0.1: {}
pacote@20.0.0:
@@ -10928,6 +11109,8 @@ snapshots:
dependencies:
find-up: 6.3.0
+ pngjs@5.0.0: {}
+
postcss-import@15.1.0(postcss@8.4.49):
dependencies:
postcss: 8.4.49
@@ -10943,7 +11126,7 @@ snapshots:
postcss-load-config@4.0.2(postcss@8.4.49):
dependencies:
lilconfig: 3.1.2
- yaml: 2.6.0
+ yaml: 2.6.1
optionalDependencies:
postcss: 8.4.49
@@ -11000,7 +11183,7 @@ snapshots:
postcss@8.4.49:
dependencies:
- nanoid: 3.3.7
+ nanoid: 3.3.8
picocolors: 1.1.1
source-map-js: 1.2.1
@@ -11010,7 +11193,7 @@ snapshots:
dependencies:
fast-diff: 1.3.0
- prettier-plugin-tailwindcss@0.6.8(prettier@3.3.3):
+ prettier-plugin-tailwindcss@0.6.9(prettier@3.3.3):
dependencies:
prettier: 3.3.3
@@ -11056,6 +11239,12 @@ snapshots:
qjobs@1.2.0: {}
+ qrcode@1.5.4:
+ dependencies:
+ dijkstrajs: 1.0.3
+ pngjs: 5.0.0
+ yargs: 15.4.1
+
qs@6.13.0:
dependencies:
side-channel: 1.0.6
@@ -11117,18 +11306,18 @@ snapshots:
regex-parser@2.3.0: {}
- regexpu-core@6.1.1:
+ regexpu-core@6.2.0:
dependencies:
regenerate: 1.4.2
regenerate-unicode-properties: 10.2.0
regjsgen: 0.8.0
- regjsparser: 0.11.2
+ regjsparser: 0.12.0
unicode-match-property-ecmascript: 2.0.0
unicode-match-property-value-ecmascript: 2.2.0
regjsgen@0.8.0: {}
- regjsparser@0.11.2:
+ regjsparser@0.12.0:
dependencies:
jsesc: 3.0.2
@@ -11136,6 +11325,8 @@ snapshots:
require-from-string@2.0.2: {}
+ require-main-filename@2.0.0: {}
+
requires-port@1.0.0: {}
resolve-from@4.0.0: {}
@@ -11232,7 +11423,7 @@ snapshots:
sass@1.80.7:
dependencies:
chokidar: 4.0.1
- immutable: 5.0.2
+ immutable: 5.0.3
source-map-js: 1.2.1
optionalDependencies:
'@parcel/watcher': 2.5.0
@@ -11327,6 +11518,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ set-blocking@2.0.0: {}
+
set-function-length@1.2.2:
dependencies:
define-data-property: 1.1.4
@@ -11700,7 +11893,7 @@ snapshots:
tree-kill@1.2.2: {}
- ts-api-utils@1.4.0(typescript@5.6.3):
+ ts-api-utils@1.4.2(typescript@5.6.3):
dependencies:
typescript: 5.6.3
@@ -11734,11 +11927,11 @@ snapshots:
typed-assert@1.0.9: {}
- typescript-eslint@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3):
+ typescript-eslint@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3):
dependencies:
- '@typescript-eslint/eslint-plugin': 8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
- '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
- '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@typescript-eslint/eslint-plugin': 8.16.0(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3))(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@typescript-eslint/parser': 8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
+ '@typescript-eslint/utils': 8.16.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.6.3)
eslint: 9.15.0(jiti@1.21.6)
optionalDependencies:
typescript: 5.6.3
@@ -11752,7 +11945,7 @@ snapshots:
uglify-js@3.19.3:
optional: true
- undici-types@6.19.8: {}
+ undici-types@6.20.0: {}
unicode-canonical-property-names-ecmascript@2.0.1: {}
@@ -11845,13 +12038,13 @@ snapshots:
moment: 2.30.1
propagating-hammerjs: 1.5.0
- vite@5.4.11(@types/node@22.9.0)(less@4.2.0)(sass@1.80.7)(terser@5.36.0):
+ vite@5.4.11(@types/node@22.10.0)(less@4.2.0)(sass@1.80.7)(terser@5.36.0):
dependencies:
esbuild: 0.21.5
postcss: 8.4.49
rollup: 4.26.0
optionalDependencies:
- '@types/node': 22.9.0
+ '@types/node': 22.10.0
fsevents: 2.3.3
less: 4.2.0
sass: 1.80.7
@@ -11975,6 +12168,8 @@ snapshots:
websocket-extensions@0.1.4: {}
+ which-module@2.0.1: {}
+
which@1.3.1:
dependencies:
isexe: 2.0.0
@@ -12031,6 +12226,8 @@ snapshots:
ws@8.18.0: {}
+ y18n@4.0.3: {}
+
y18n@5.0.8: {}
yallist@3.1.1: {}
@@ -12039,12 +12236,31 @@ snapshots:
yallist@5.0.0: {}
- yaml@2.6.0: {}
+ yaml@2.6.1: {}
+
+ yargs-parser@18.1.3:
+ dependencies:
+ camelcase: 5.3.1
+ decamelize: 1.2.0
yargs-parser@20.2.9: {}
yargs-parser@21.1.1: {}
+ yargs@15.4.1:
+ dependencies:
+ cliui: 6.0.0
+ decamelize: 1.2.0
+ find-up: 4.1.0
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ require-main-filename: 2.0.0
+ set-blocking: 2.0.0
+ string-width: 4.2.3
+ which-module: 2.0.1
+ y18n: 4.0.3
+ yargs-parser: 18.1.3
+
yargs@16.2.0:
dependencies:
cliui: 7.0.4
diff --git a/src/app/app.component.html b/src/app/app.component.html
index 9c67d58..0e8137f 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -4,6 +4,7 @@
+
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index e23ece9..70ff7c2 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -1,5 +1,6 @@
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
+import { ShowSessionComponent } from '@app/portal/features/show-session/show-session.component';
import { SiteFooterComponent } from '@app/portal/features/site-footer/site-footer.component';
import { SiteHeaderComponent } from '@app/portal/features/site-header/site-header.component';
@@ -8,7 +9,12 @@ import { SiteHeaderComponent } from '@app/portal/features/site-header/site-heade
*/
@Component({
selector: 'app-root',
- imports: [RouterOutlet, SiteHeaderComponent, SiteFooterComponent],
+ imports: [
+ RouterOutlet,
+ SiteHeaderComponent,
+ SiteFooterComponent,
+ ShowSessionComponent,
+ ],
templateUrl: './app.component.html',
})
export class AppComponent {}
diff --git a/src/app/app.config.ts b/src/app/app.config.ts
index d13efa4..cc73d7e 100644
--- a/src/app/app.config.ts
+++ b/src/app/app.config.ts
@@ -2,10 +2,24 @@ import {
ApplicationConfig,
provideExperimentalZonelessChangeDetection,
} from '@angular/core';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
import { provideRouter } from '@angular/router';
+import {
+ HTTP_INTERCEPTORS,
+ provideHttpClient,
+ withFetch,
+ withInterceptorsFromDi,
+} from '@angular/common/http';
+import { CsrfInterceptor } from '@app/auth/services/csrf.service';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
- providers: [provideExperimentalZonelessChangeDetection(), provideRouter(routes)],
+ providers: [
+ provideExperimentalZonelessChangeDetection(),
+ provideRouter(routes),
+ provideHttpClient(withFetch(), withInterceptorsFromDi()),
+ provideNoopAnimations(),
+ { provide: HTTP_INTERCEPTORS, useClass: CsrfInterceptor, multi: true },
+ ],
};
diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts
index e300ac5..601740b 100644
--- a/src/app/app.routes.ts
+++ b/src/app/app.routes.ts
@@ -1,5 +1,8 @@
/* eslint-disable jsdoc/require-jsdoc */
+import { inject } from '@angular/core';
import { Routes } from '@angular/router';
+import { AuthService } from '@app/auth/services/auth.service';
+
export const routes: Routes = [
{
path: '',
@@ -15,4 +18,33 @@ export const routes: Routes = [
(m) => m.MetadataBrowserComponent,
),
},
+ // routes used in the authentication flows
+ {
+ path: 'oauth/callback',
+ canActivate: [() => inject(AuthService).oidcRedirect()],
+ children: [],
+ },
+ // TODO: add guards to the following routes that check the expected state
+ // TODO: also add deactivation guards to these routes
+ {
+ path: 'register',
+ loadComponent: () =>
+ import('./auth/features/register/register.component').then(
+ (m) => m.RegisterComponent,
+ ),
+ },
+ {
+ path: 'setup-totp',
+ loadComponent: () =>
+ import('./auth/features/setup-totp/setup-totp.component').then(
+ (m) => m.SetupTotpComponent,
+ ),
+ },
+ {
+ path: 'confirm-totp',
+ loadComponent: () =>
+ import('./auth/features/confirm-totp/confirm-totp.component').then(
+ (m) => m.ConfirmTotpComponent,
+ ),
+ },
];
diff --git a/src/app/auth/features/confirm-totp/confirm-totp.component.html b/src/app/auth/features/confirm-totp/confirm-totp.component.html
new file mode 100644
index 0000000..0601f46
--- /dev/null
+++ b/src/app/auth/features/confirm-totp/confirm-totp.component.html
@@ -0,0 +1,22 @@
+Two-factor authentication
+
+Please enter the 6-digit authentication code generated by your authenticator app
+
+
+ Authentication Code
+
+
+
+Submit
+
+@if (verificationError) {
+ The entered authentication code was not valid.
+}
+
+Get new 2FA setup
diff --git a/src/app/auth/features/confirm-totp/confirm-totp.component.spec.ts b/src/app/auth/features/confirm-totp/confirm-totp.component.spec.ts
new file mode 100644
index 0000000..b12e963
--- /dev/null
+++ b/src/app/auth/features/confirm-totp/confirm-totp.component.spec.ts
@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ConfirmTotpComponent } from './confirm-totp.component';
+
+describe('ConfirmTotpComponent', () => {
+ let component: ConfirmTotpComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [ConfirmTotpComponent],
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(ConfirmTotpComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/auth/features/confirm-totp/confirm-totp.component.ts b/src/app/auth/features/confirm-totp/confirm-totp.component.ts
new file mode 100644
index 0000000..e269e98
--- /dev/null
+++ b/src/app/auth/features/confirm-totp/confirm-totp.component.ts
@@ -0,0 +1,72 @@
+import { Component, inject } from '@angular/core';
+import {
+ FormControl,
+ FormsModule,
+ ReactiveFormsModule,
+ Validators,
+} from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { AuthService } from '@app/auth/services/auth.service';
+
+// TODO: Polish this component
+
+/**
+ * TOTP confirmation page
+ */
+@Component({
+ selector: 'app-confirm-totp',
+ imports: [
+ FormsModule,
+ ReactiveFormsModule,
+ MatButtonModule,
+ MatFormFieldModule,
+ MatInputModule,
+ ],
+ templateUrl: './confirm-totp.component.html',
+})
+export class ConfirmTotpComponent {
+ #authService = inject(AuthService);
+
+ codeControl = new FormControl('', [
+ Validators.required,
+ Validators.pattern(/^\d{6}$/),
+ ]);
+
+ verificationError = false;
+
+ /**
+ * Input handler for the TOTP code
+ */
+ onInput(): void {
+ this.verificationError = false;
+ }
+
+ /**
+ * Submit authentication code
+ */
+ async onSubmit(): Promise {
+ this.verificationError = false;
+ const code = this.codeControl.value;
+ if (!code) return;
+ const verified = await this.#authService.verifyTotpCode(code);
+ if (verified) {
+ console.info('Successfully authenticated.');
+ // add toast message here
+ this.#authService.redirectAfterLogin();
+ } else {
+ // maybe add toast message here
+ console.error('Failed to authenticate.');
+ this.codeControl.reset();
+ this.verificationError = true;
+ }
+ }
+
+ /**
+ * Set status to "lost token" and redirect to token setup
+ */
+ onLostToken(): void {
+ this.#authService.lostTotpSetup();
+ }
+}
diff --git a/src/app/auth/features/register/register.component.html b/src/app/auth/features/register/register.component.html
new file mode 100644
index 0000000..0c30abe
--- /dev/null
+++ b/src/app/auth/features/register/register.component.html
@@ -0,0 +1,66 @@
+Registration with GHGA
+@let u = user();
+@switch (u) {
+ @case (undefined) {
+ Loading...
+ }
+ @case (null) {
+ You are currently not logged in.
+ Go back to the home page.
+ }
+ @default {
+ Welcome, {{ u.full_name }}!
+
+ @if (u.id) {
+ @if (u.state === 'NeedsReRegistration') {
+ Your contact information has changed since you last registered.
+ }
+ Please confirm that the information given below is correct.
+ } @else {
+ Since you haven't used our data portal before, we ask you to confirm your user
+ data and register with us.
+ }
+
+
+ Name:
+ {{ u.name }}
+
+
+ E-Mail:
+ {{ u.email }}
+
+
+ Life Science ID:
+ {{ u.ext_id }}
+
+
+ Academic title:
+
+
+ @for (title of allTitles; track title) {
+ {{ title || '–' }}
+ }
+
+
+
+
+
+ I accept the
+ terms of use
+ and the
+
+ privacy policy .
+
+
+ Cancel and log out
+
+ {{ u?.id ? 'Confirm' : 'Register' }}
+
+ }
+}
diff --git a/src/app/auth/features/register/register.component.scss b/src/app/auth/features/register/register.component.scss
new file mode 100644
index 0000000..c42a18c
--- /dev/null
+++ b/src/app/auth/features/register/register.component.scss
@@ -0,0 +1,5 @@
+.label {
+ display: inline-block;
+ font-weight: bold;
+ min-width: 9em;
+}
diff --git a/src/app/auth/features/register/register.component.spec.ts b/src/app/auth/features/register/register.component.spec.ts
new file mode 100644
index 0000000..54d1433
--- /dev/null
+++ b/src/app/auth/features/register/register.component.spec.ts
@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { RegisterComponent } from './register.component';
+
+describe('RegisterComponent', () => {
+ let component: RegisterComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [RegisterComponent],
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(RegisterComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/auth/features/register/register.component.ts b/src/app/auth/features/register/register.component.ts
new file mode 100644
index 0000000..fc1bb66
--- /dev/null
+++ b/src/app/auth/features/register/register.component.ts
@@ -0,0 +1,81 @@
+import { Component, effect, inject } from '@angular/core';
+import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { MatCheckboxModule } from '@angular/material/checkbox';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatSelectModule } from '@angular/material/select';
+
+import { AcademicTitle, UserBasicData } from '@app/auth/models/user';
+
+import { MatButtonModule } from '@angular/material/button';
+import { AuthService } from '@app/auth/services/auth.service';
+
+// TODO: Polish this component
+
+/**
+ * User registration page
+ */
+@Component({
+ selector: 'app-register',
+ imports: [
+ FormsModule,
+ ReactiveFormsModule,
+ MatButtonModule,
+ MatCheckboxModule,
+ MatFormFieldModule,
+ MatSelectModule,
+ ],
+ templateUrl: './register.component.html',
+ styleUrl: './register.component.scss',
+})
+export class RegisterComponent {
+ #authService = inject(AuthService);
+
+ user = this.#authService.user;
+
+ allTitles: AcademicTitle[] = [null, 'Dr.', 'Prof.'];
+
+ titleControl = new FormControl(null);
+
+ accepted = false;
+
+ /**
+ * Initialize the registration component
+ */
+ constructor() {
+ // if a re-registering user already has a title,
+ // then set it as value in the control
+ effect(() => {
+ const title = this.user()?.title;
+ if (title) {
+ this.titleControl.setValue(title);
+ }
+ });
+ }
+
+ /**
+ * Cancel registration and log out
+ */
+ async cancel(): Promise {
+ await this.#authService.logout();
+ }
+
+ /**
+ * Submit registration form
+ */
+ async register(): Promise {
+ if (!this.accepted) return;
+ const user = this.user();
+ if (!user) return;
+ const title = this.titleControl.value || null;
+ const { id, ext_id, name, email } = user;
+ const data: UserBasicData = { name, email, title };
+ const ok = await this.#authService.register(id || null, ext_id, data);
+ if (ok) {
+ // add toast message or dialog here
+ console.info('Registration was successful.');
+ } else {
+ // add toast message here
+ console.error('Registration failed.');
+ }
+ }
+}
diff --git a/src/app/auth/features/setup-totp/setup-totp.component.html b/src/app/auth/features/setup-totp/setup-totp.component.html
new file mode 100644
index 0000000..27cc1a9
--- /dev/null
+++ b/src/app/auth/features/setup-totp/setup-totp.component.html
@@ -0,0 +1,61 @@
+Set up two-factor authentication
+
+@if (isLoading()) {
+ Loading...
+} @else if (isNewlyRegistered()) {
+ Thank you for registering in the GHGA data portal.
+
+ For additional security when accessing protected data with the GHGA data portal, we
+ are using two-factor authentication and verification of your identity via a contact
+ address that is separate from your primary E-Mail contact address.
+
+ Continue
+} @else if (hasLostToken() && !lostTokenConfirmed()) {
+
+ In the case that you lost your phone or the setup of your authenticator app, you can
+ create a new authentication code setup.
+
+
+ However, all contact addresses that had been verified before will need to be
+ verified again.
+
+ Continue
+ Cancel
+} @else {
+ @let uri = setupUri() | async;
+ @if (uri) {
+
+ The two-factor authentication means that we require you to enter an additional
+ 6-digit authentication code after you logged in via LS Login. This code can be
+ produced by an authenticator app such as Aegis, Microsoft Authenticator or Google
+ Authenticator, which you can install on your mobile phone.
+
+
+ In order to set up the authenticator app to produce the authentication codes for
+ the GHGA data portal, please scan this QR code with your authenticator app:
+
+
+
+ @if (showManualSetup) {
+ Hide
+ } @else {
+ Show
+ }
+ manual setup instructions
+
+ @if (showManualSetup) {
+
+ If you have trouble scanning the QR Code, please manually input the following
+ setup key in your authenticator app:
+
+
+ Copy the setup key
+ }
+ Continue
+ } @else if (uri === undefined) {
+ Generating the TOTP setup...
+ } @else {
+ Error setting up two-factor authentication.
+ Go back to the home page.
+ }
+}
diff --git a/src/app/auth/features/setup-totp/setup-totp.component.spec.ts b/src/app/auth/features/setup-totp/setup-totp.component.spec.ts
new file mode 100644
index 0000000..80d09b2
--- /dev/null
+++ b/src/app/auth/features/setup-totp/setup-totp.component.spec.ts
@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SetupTotpComponent } from './setup-totp.component';
+
+describe('SetupTotpComponent', () => {
+ let component: SetupTotpComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [SetupTotpComponent],
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(SetupTotpComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/auth/features/setup-totp/setup-totp.component.ts b/src/app/auth/features/setup-totp/setup-totp.component.ts
new file mode 100644
index 0000000..8eeec27
--- /dev/null
+++ b/src/app/auth/features/setup-totp/setup-totp.component.ts
@@ -0,0 +1,82 @@
+import { CommonModule } from '@angular/common';
+import { Component, computed, inject, signal } from '@angular/core';
+import { MatButtonModule } from '@angular/material/button';
+import { AuthService } from '@app/auth/services/auth.service';
+import { QRCodeComponent } from 'angularx-qrcode';
+
+// TODO: Polish this component
+// TODO: Maybe show another warning or different text when state is "LostTotpToken"
+
+/**
+ * TOTP setup page
+ */
+@Component({
+ selector: 'app-setup-totp',
+ imports: [CommonModule, QRCodeComponent, MatButtonModule],
+ templateUrl: './setup-totp.component.html',
+})
+export class SetupTotpComponent {
+ #authService = inject(AuthService);
+ #sessionState = this.#authService.sessionState;
+
+ isLoading = this.#authService.isUndetermined;
+
+ isNewlyRegistered = computed(() => this.#sessionState() === 'Registered');
+
+ hasLostToken = computed(() => this.#sessionState() === 'LostTotpToken');
+
+ lostTokenConfirmed = signal(false);
+
+ /**
+ * Get the provisioning URI as a signal
+ */
+ setupUri = computed(async () => {
+ const state = this.#sessionState();
+ if (!['NeedsTotpToken', 'LostTotpToken'].includes(state)) return null;
+ const uri = await this.#authService.createTotpToken();
+ return uri;
+ });
+
+ showManualSetup = false;
+
+ /**
+ * Confirm the registration status and proceed with the TOTP setup
+ */
+ confirmRegistration(): void {
+ this.#authService.needsTotpSetup();
+ }
+
+ /**
+ * Cancel the recreation of a lost TOTP token
+ */
+ cancelLostToken(): void {
+ this.#authService.completeTotpSetup();
+ }
+
+ /**
+ * Get the actual secret from the query parameter in the URI
+ * @param uri The provisioning URI containing the secret
+ * @returns just the secret from the URI
+ */
+ getSecret(uri: string): string {
+ return new URLSearchParams(uri.substring(uri.indexOf('?'))).get('secret')!;
+ }
+
+ /**
+ * Copy the secret to the clipboard
+ * @param uri The provisioning URI containing the secret
+ */
+ copySecret(uri: string): void {
+ navigator.clipboard.writeText(this.getSecret(uri));
+ }
+
+ /**
+ * Complete the TOTP setup
+ *
+ * Assume that the user has added the TOTP token to the authenticator
+ * and continue with the TOTP confirmation step.
+ */
+ completeSetup(): void {
+ this.#authService.completeTotpSetup();
+ }
+}
diff --git a/src/app/auth/models/user.ts b/src/app/auth/models/user.ts
new file mode 100644
index 0000000..7e9b87a
--- /dev/null
+++ b/src/app/auth/models/user.ts
@@ -0,0 +1,54 @@
+/**
+ * All possible states of the user session
+ */
+export type LoginState =
+ | 'Undetermined' // the state is not yet determined
+ | 'LoggedOut' // the user is logged out
+ | 'LoggedIn' // the user is logged in with first factor
+ | 'NeedsRegistration' // the user needs to register (backend state)
+ | 'NeedsReRegistration' // the user needs to re-register (backend state)
+ | 'Registered' // the user is registered (backend state)
+ | 'NeedsTotpToken' // the user needs to set up TOTP (frontend state only)
+ | 'LostTotpToken' // the user has lost the TOTP token (frontend state only)
+ | 'NewTotpToken' // a new TOTP token has just been created (backend state)
+ | 'HasTotpToken' // a TOTP token exists but not yet authenticated (backend state)
+ | 'Authenticated'; // user is fully authenticated with second factor (backend state)
+
+/**
+ * All possible academic titles
+ */
+export type AcademicTitle = null | 'Dr.' | 'Prof.';
+
+/**
+ * Basic data of a user
+ */
+export interface UserBasicData {
+ name: string;
+ title?: AcademicTitle;
+ email: string;
+}
+
+/**
+ * Basic data of a registered user
+ */
+export interface UserRegisteredData extends UserBasicData {
+ ext_id: string;
+}
+
+/**
+ * User session interface
+ *
+ * Contains all data describing the user and the user session.
+ *
+ * Note that this is different from the low-level oidcUser object,
+ * which does not contain the user data from the backend.
+ */
+export interface User extends UserRegisteredData {
+ id?: string;
+ full_name: string;
+ state: LoginState;
+ role?: string;
+ csrf: string;
+ timeout?: number;
+ extends?: number;
+}
diff --git a/src/app/auth/services/auth.service.spec.ts b/src/app/auth/services/auth.service.spec.ts
new file mode 100644
index 0000000..f1251ca
--- /dev/null
+++ b/src/app/auth/services/auth.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { AuthService } from './auth.service';
+
+describe('AuthService', () => {
+ let service: AuthService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(AuthService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/src/app/auth/services/auth.service.ts b/src/app/auth/services/auth.service.ts
new file mode 100644
index 0000000..c346e64
--- /dev/null
+++ b/src/app/auth/services/auth.service.ts
@@ -0,0 +1,459 @@
+import {
+ HttpClient,
+ HttpHeaders,
+ HttpParams,
+ HttpResponse,
+} from '@angular/common/http';
+import { computed, inject, Injectable, signal } from '@angular/core';
+import { Router } from '@angular/router';
+import { ConfigService } from '@app/shared/services/config.service';
+import type { OidcMetadata, UserManagerSettings } from 'oidc-client-ts';
+import {
+ Log as OidcLog,
+ User as OidcUser,
+ UserManager as OidcUserManager,
+} from 'oidc-client-ts';
+import { catchError, firstValueFrom, map, Observable, of } from 'rxjs';
+import { LoginState, User, UserBasicData } from '../models/user';
+import { CsrfService } from './csrf.service';
+
+/**
+ * Authentication service
+ *
+ * This service provides the OIDC and 2FA related functionality
+ * and keeps track of the state of the user session.
+ */
+@Injectable({ providedIn: 'root' })
+export class AuthService {
+ #config = inject(ConfigService);
+ #http = inject(HttpClient);
+ #router = inject(Router);
+ #csrf = inject(CsrfService);
+ #userSignal = signal(undefined);
+
+ #redirectAfterLogin = '/';
+
+ #oidcUserManager: OidcUserManager;
+
+ #authUrl = this.#config.authUrl;
+ #loginUrl = `${this.#authUrl}/rpc/login`;
+ #logoutUrl = `${this.#authUrl}/rpc/logout`;
+ #verifyTotpUrl = `${this.#authUrl}/rpc/verify-totp`;
+ #totpTokenUrl = `${this.#authUrl}/totp-token`;
+ #usersUrl = `${this.#authUrl}/users`;
+
+ /**
+ * Get the current user session as a signal
+ *
+ * Null means that the user is not logged in (state is 'Anonymous'), while
+ * undefined means that the session has not yet been loaded (state 'Undetermined').
+ */
+ user = computed(() => this.#userSignal());
+
+ /**
+ * Check whether the session state is known as a signal
+ */
+ isDetermined = computed(() => this.user() !== undefined);
+
+ /**
+ * Check whether the session state is still loading as a signal
+ */
+ isUndetermined = computed(() => this.user() === undefined);
+
+ /**
+ * Check whether the user has been logged in with first factor as a signal
+ */
+ isLoggedIn = computed(() => !!this.user());
+
+ /**
+ * Check whether the user has been logged out as a signal
+ */
+ isLoggedOut = computed(() => this.user() === null);
+
+ /**
+ * Check whether the user is fully authenticated with second factor as a signal
+ */
+ isAuthenticated = computed(() => this.user()?.state == 'Authenticated');
+
+ /**
+ * Get the current user session state as a signal
+ */
+ sessionState = computed(() => {
+ const state = this.user()?.state;
+ return state || (state === null ? 'LoggedOut' : 'Undetermined');
+ });
+
+ /**
+ * Get the full name of the current user (with title) as a signal
+ */
+ fullName = computed(() => this.user()?.full_name);
+
+ /**
+ * Initialize the authentication service
+ */
+ constructor() {
+ this.#oidcUserManager = new OidcUserManager(this.getOidcSettings());
+
+ OidcLog.setLogger(console);
+ OidcLog.setLevel(OidcLog.INFO); // set to DEBUG for more output
+
+ /**
+ * On page load we must also load the user session from the server.
+ * We can only skip this when this is the callback page, since int
+ * this case the session is loaded with oidcRedirect().
+ */
+ if (window.location.pathname !== '/oauth/callback') {
+ this.#loadUserSession();
+ }
+ }
+
+ /**
+ * Gets the OIDC related settings
+ *
+ * These settings are derived from the application configuration
+ * and transformed into a UserManagerSettings object.
+ * @returns the settings as a UserManagerSettings object
+ */
+ private getOidcSettings(): UserManagerSettings {
+ const config = this.#config;
+
+ const settings: UserManagerSettings = {
+ authority: config.oidcAuthorityUrl,
+ client_id: config.oidcClientId,
+ redirect_uri: config.oidcRedirectUrl,
+ response_type: 'code',
+ scope: config.oidcScope,
+ loadUserInfo: false,
+ automaticSilentRenew: false,
+ };
+
+ const metadata: Partial = {
+ issuer: config.oidcAuthorityUrl,
+ authorization_endpoint: config.oidcAuthorizationUrl,
+ token_endpoint: config.oidcTokenUrl,
+ userinfo_endpoint: config.oidcUserInfoUrl,
+ };
+
+ /**
+ * If the "use_discovery" is true, we use the OIDC discovery mechanism
+ * to provide the metadata, and only seed it with the configured settings.
+ * Note that this requires an additional request and will only
+ * work if the origin header for a registered client is passed.
+ */
+ if (config.oidcUseDiscovery) {
+ settings.metadataSeed = metadata;
+ } else {
+ settings.metadata = metadata;
+ }
+
+ return settings;
+ }
+
+ /**
+ * Initiate login via OIDC
+ *
+ * This returns a promise to trigger a redirect of the current window
+ * to the authorization endpoint of the OIDC provider.
+ */
+ async login(): Promise {
+ this.#redirectAfterLogin = location.pathname;
+ this.#oidcUserManager.signinRedirect();
+ }
+
+ /**
+ * Handle OIDC redirect callback
+ *
+ * This method can be used as a canActivate guard for the OAuth callback route.
+ * @returns always false to prevent the route from being activated
+ */
+ async oidcRedirect(): Promise {
+ if (await this.#oidcUserManager.getUser()) return false; // already logged in
+ let oidcUser: OidcUser | undefined;
+ let errorMessage: string | undefined;
+ try {
+ oidcUser = await this.#oidcUserManager.signinCallback();
+ } catch (e) {
+ errorMessage = e instanceof Error ? e.message : String(e);
+ }
+
+ if (oidcUser) {
+ if (!oidcUser.profile?.sub) {
+ errorMessage = 'No OpenID connect user';
+ } else if (oidcUser.expired) {
+ errorMessage = 'OpenID connect login expired';
+ } else if (!oidcUser.access_token) {
+ errorMessage = 'No OpenID connect access token';
+ }
+ }
+
+ if (!oidcUser || errorMessage) {
+ if (!errorMessage) {
+ errorMessage = 'OpenID connect login failed';
+ }
+ console.error(errorMessage); // TODO: also add a toast message
+ return false;
+ }
+
+ this.#loadUserSession(oidcUser.access_token);
+ return false;
+ }
+
+ /**
+ * Login user via OIDC
+ *
+ * This returns a promise to trigger a redirect of the current window
+ * to the authorization endpoint of the OIDC provider.
+ */
+ async logout(): Promise {
+ if (this.#userSignal()) {
+ firstValueFrom(
+ this.#http.post(this.#logoutUrl, null).pipe(
+ map(() => true),
+ catchError(() => of(false)),
+ ),
+ ).then(async () => {
+ await this.#oidcUserManager.removeUser();
+ this.#userSignal.set(null);
+ this.#csrf.token = null;
+ this.#redirectAfterLogin = '/';
+ this.#router.navigate(['/']);
+ });
+ }
+ }
+
+ /**
+ * Move session state
+ * @param state the new state to set
+ */
+ #setNewState(state: LoginState): void {
+ this.#userSignal.update((user) => {
+ if (user && user.state !== state) {
+ user = { ...user, state };
+ }
+ return user;
+ });
+ }
+
+ /**
+ * Get the deserialized user session from a JSON-formatted string.
+ * @param session the session as a JSON-formatted string or null
+ * @returns the parsed user or null if no session or undefined if error
+ */
+ #parseUserFromSession(session: string): User | null | undefined {
+ if (!session) return null;
+ let user: User | null;
+ try {
+ user = JSON.parse(session || 'null');
+ if (!user) return null;
+ if (!(user.ext_id && user.name && user.email)) {
+ throw new Error('Missing properties in user session');
+ }
+ } catch (error) {
+ console.error('Cannot parse user session:', session, error);
+ return undefined;
+ }
+ if (!user.full_name) {
+ user.full_name = (user.title ? user.title + ' ' : '') + user.name;
+ }
+ return user;
+ }
+
+ /**
+ * Load the current user session
+ *
+ * This method is called on startup to fetch the user session from the backend.
+ *
+ * It is also called to check when a state change was triggered and we need to
+ * wait for and verify that the backend has actually updated the user session.
+ * @param accessToken the access token to use for logging in
+ */
+ async #loadUserSession(accessToken: string | undefined = undefined): Promise {
+ console.debug('Loading user session...');
+ const userSignal = this.#userSignal;
+ let headers = new HttpHeaders();
+ if (accessToken) headers = headers.set('X-Authorization', `Bearer ${accessToken}`);
+ this.#http
+ .post(this.#loginUrl, null, { observe: 'response', headers })
+ .pipe(
+ // map to user or null if not found or undefined if error
+ map((response: HttpResponse) => {
+ if (response.status !== 204 || response.body) return undefined;
+ const session = response.headers.get('X-Session');
+ if (!session) return undefined;
+ return this.#parseUserFromSession(session);
+ }),
+ catchError((error) =>
+ of([401, 403, 404].includes(error?.status) ? null : undefined),
+ ),
+ )
+ .subscribe((user: User | null | undefined) => {
+ if (user) {
+ console.debug('User session loaded:', user);
+ userSignal.set(user);
+ this.#csrf.token = user.csrf;
+ const router = this.#router;
+ switch (user.state) {
+ case 'NeedsRegistration':
+ case 'NeedsReRegistration':
+ router.navigate(['/register']);
+ break;
+ case 'Registered':
+ router.navigate(['/setup-totp']);
+ break;
+ case 'NewTotpToken':
+ case 'HasTotpToken':
+ router.navigate(['/confirm-totp']);
+ break;
+ }
+ } else {
+ if (accessToken || user === undefined) {
+ console.error('Failed to load user session');
+ // TODO: also add a toast message
+ }
+ this.#oidcUserManager.removeUser();
+ userSignal.set(user);
+ this.#csrf.token = null;
+ }
+ });
+ }
+
+ /**
+ * Wait for the backend user session to change the state
+ * @param state the state that is expected to change
+ * @param maxAttempts the maximum number of attempts to wait for the state
+ * @returns a promise that resolves to the last reached state
+ */
+ async #waitForStateChange(
+ state: LoginState,
+ maxAttempts: number = 5,
+ ): Promise {
+ const newState = this.sessionState();
+ if (newState !== state) return newState;
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
+ const wait = (1 << attempt) * 50; // exponential backoff
+ await new Promise((resolve) => setTimeout(resolve, wait));
+ await this.#loadUserSession();
+ const newState = this.sessionState();
+ if (newState !== state) return newState;
+ }
+ return state;
+ }
+
+ /**
+ * Register or re-register a user
+ * @param id the internal user ID or null for new users
+ * @param ext_id the external user ID (can be null for registered users)
+ * @param basicData the basic user data to register or re-register
+ * @returns a promise that resolves to true if the code is valid
+ */
+ async register(
+ id: string | null,
+ ext_id: string | null,
+ basicData: UserBasicData,
+ ): Promise {
+ if (!id && !ext_id) return false;
+ const state = this.sessionState();
+ let url = this.#usersUrl;
+ let rpc: Observable;
+ if (id) {
+ if (state !== 'NeedsReRegistration') return false;
+ rpc = this.#http.put(`${url}/${id}`, basicData);
+ } else {
+ if (state !== 'NeedsRegistration') return false;
+ if (!ext_id) return false;
+ rpc = this.#http.post(url, { ...basicData, ext_id });
+ }
+ await firstValueFrom(rpc);
+ const newState = await this.#waitForStateChange(state);
+ return (
+ newState != state &&
+ !['LoggedOut', 'LoggedIn', 'NeedsRegistration', 'NeedsReRegistration'].includes(
+ newState,
+ )
+ );
+ }
+
+ /**
+ * Create a TOTP token
+ * @returns a promise that resolves to the provisioning URI or null
+ */
+ async createTotpToken(): Promise {
+ const state = this.sessionState();
+ if (!['NeedsTotpToken', 'LostTotpToken'].includes(state)) return null;
+ let params = new HttpParams();
+ if (state == 'LostTotpToken') {
+ params = params.set('force', 'true');
+ }
+ return firstValueFrom(
+ this.#http.post<{ uri: string }>(this.#totpTokenUrl, null, { params }).pipe(
+ map(({ uri }) => {
+ console.info('TOTP token created');
+ return uri || null;
+ }),
+ catchError(() => {
+ console.error('Failed to create TOTP token');
+ return of(null);
+ }),
+ ),
+ );
+ }
+
+ /**
+ * Move state to "needs TOTP token" and continue with setup
+ */
+ needsTotpSetup(): void {
+ this.#setNewState('NeedsTotpToken');
+ }
+
+ /**
+ * Move state to "lost TOTP token" and proceed with setup
+ */
+ lostTotpSetup(): void {
+ this.#setNewState('LostTotpToken');
+ this.#router.navigate(['/setup-totp']);
+ }
+
+ /**
+ * Move state to "has TOTP token" and proceed with confirmation
+ */
+ completeTotpSetup(): void {
+ this.#setNewState('HasTotpToken');
+ this.#router.navigate(['/confirm-totp']);
+ }
+
+ /**
+ * Verify the given TOTP code
+ * @param code the 6-digit TOTP code to verify
+ * @returns a promise that resolves to true if the code is valid
+ */
+ async verifyTotpCode(code: string): Promise {
+ const state = this.sessionState();
+ if (!['NewTotpToken', 'HasTotpToken'].includes(state)) return false;
+ let headers = new HttpHeaders();
+ headers = headers.set('X-Authorization', `Bearer TOTP:${code}`);
+ if (!code || code.length !== 6 || !/^\d{6}$/.test(code)) {
+ console.error('Invalid TOTP code');
+ return false;
+ }
+ return firstValueFrom(
+ this.#http.post(this.#verifyTotpUrl, null, { headers }).pipe(
+ map(() => {
+ console.info('TOTP code verified');
+ this.#setNewState('Authenticated');
+ return true;
+ }),
+ catchError(() => {
+ console.error('Failed to verify TOTP code');
+ return of(false);
+ }),
+ ),
+ );
+ }
+
+ /**
+ * Redirect back to the original page after login
+ */
+ redirectAfterLogin() {
+ this.#router.navigate([this.#redirectAfterLogin]);
+ }
+}
diff --git a/src/app/auth/services/csrf.service.ts b/src/app/auth/services/csrf.service.ts
new file mode 100644
index 0000000..57b3e9d
--- /dev/null
+++ b/src/app/auth/services/csrf.service.ts
@@ -0,0 +1,46 @@
+import {
+ HttpEvent,
+ HttpHandler,
+ HttpInterceptor,
+ HttpRequest,
+} from '@angular/common/http';
+import { inject, Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+
+/**
+ * A tiny service that just holds the CSRF token
+ *
+ * This is used by both the auth service and the CSRF interceptor.
+ */
+@Injectable({ providedIn: 'root' })
+export class CsrfService {
+ token: string | null = null;
+}
+
+/**
+ * Custom CSRF Interceptor
+ */
+@Injectable()
+export class CsrfInterceptor implements HttpInterceptor {
+ #csrf = inject(CsrfService);
+
+ /**
+ * Intercept all HTTP requests and add the CSRF token if needed
+ * @param req the outgoing request object to handle
+ * @param next the next interceptor in the chain
+ * @returns an observable of the HTTP event
+ */
+ intercept(
+ req: HttpRequest,
+ next: HttpHandler,
+ ): Observable> {
+ const method = req.method;
+ if (method && /^(POST|PUT|PATCH|DELETE)$/.test(method)) {
+ const csrfToken = this.#csrf.token;
+ if (csrfToken) {
+ req = req.clone({ setHeaders: { 'X-CSRF-Token': csrfToken } });
+ }
+ }
+ return next.handle(req);
+ }
+}
diff --git a/src/app/portal/features/home-page/home-page.component.html b/src/app/portal/features/home-page/home-page.component.html
index ce85e00..68c39d9 100644
--- a/src/app/portal/features/home-page/home-page.component.html
+++ b/src/app/portal/features/home-page/home-page.component.html
@@ -15,7 +15,3 @@
Infrastructure initiative (NFDI) and by the contributing institutions. More at
www.ghga.de.
-
- Just to show that we can access the config, this is the MASS URL:
- {{ massUrl }}
-
diff --git a/src/app/portal/features/home-page/home-page.component.ts b/src/app/portal/features/home-page/home-page.component.ts
index 22dc4b0..0362110 100644
--- a/src/app/portal/features/home-page/home-page.component.ts
+++ b/src/app/portal/features/home-page/home-page.component.ts
@@ -1,5 +1,4 @@
-import { Component, inject } from '@angular/core';
-import { ConfigService } from '@app/shared/services/config.service';
+import { Component } from '@angular/core';
/**
* This is the home page component
@@ -9,8 +8,4 @@ import { ConfigService } from '@app/shared/services/config.service';
imports: [],
templateUrl: './home-page.component.html',
})
-export class HomePageComponent {
- #config = inject(ConfigService);
-
- massUrl = this.#config.massUrl; // just to show that we can access the config service
-}
+export class HomePageComponent {}
diff --git a/src/app/portal/features/show-session/show-session.component.html b/src/app/portal/features/show-session/show-session.component.html
new file mode 100644
index 0000000..13c75e1
--- /dev/null
+++ b/src/app/portal/features/show-session/show-session.component.html
@@ -0,0 +1,5 @@
+
+ Developer note: Currently logged in as
+ {{ fullName() || 'Guest' }}
+ in session state {{ sessionState() }} .
+
diff --git a/src/app/portal/features/show-session/show-session.component.spec.ts b/src/app/portal/features/show-session/show-session.component.spec.ts
new file mode 100644
index 0000000..42a5ba9
--- /dev/null
+++ b/src/app/portal/features/show-session/show-session.component.spec.ts
@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ShowSessionComponent } from './show-session.component';
+
+describe('ShowSessionComponent', () => {
+ let component: ShowSessionComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [ShowSessionComponent],
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(ShowSessionComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/portal/features/show-session/show-session.component.ts b/src/app/portal/features/show-session/show-session.component.ts
new file mode 100644
index 0000000..d0c5f16
--- /dev/null
+++ b/src/app/portal/features/show-session/show-session.component.ts
@@ -0,0 +1,19 @@
+import { Component, inject } from '@angular/core';
+import { AuthService } from '@app/auth/services/auth.service';
+
+/**
+ * Show user session information
+ *
+ * TODO: Only used for testing, remove this component later!
+ */
+@Component({
+ selector: 'app-show-session',
+ imports: [],
+ templateUrl: './show-session.component.html',
+})
+export class ShowSessionComponent {
+ #authService = inject(AuthService);
+
+ fullName = this.#authService.fullName;
+ sessionState = this.#authService.sessionState;
+}
diff --git a/src/app/portal/features/site-header/site-header.component.html b/src/app/portal/features/site-header/site-header.component.html
index 5e7fe0b..7dc2a5c 100644
--- a/src/app/portal/features/site-header/site-header.component.html
+++ b/src/app/portal/features/site-header/site-header.component.html
@@ -2,8 +2,12 @@
GHGA Logo
- Home Browse
- Login Button
+ Home
+ Browse
+
+ @if (isLoggedIn()) {
+ Logout
+ } @else {
+ Login
+ }
diff --git a/src/app/portal/features/site-header/site-header.component.ts b/src/app/portal/features/site-header/site-header.component.ts
index 689a8dc..b06c686 100644
--- a/src/app/portal/features/site-header/site-header.component.ts
+++ b/src/app/portal/features/site-header/site-header.component.ts
@@ -1,7 +1,9 @@
-import { Component } from '@angular/core';
+import { Component, inject } from '@angular/core';
+import { MatButtonModule } from '@angular/material/button';
import { MatNavList } from '@angular/material/list';
import { MatToolbarModule } from '@angular/material/toolbar';
import { RouterLink } from '@angular/router';
+import { AuthService } from '@app/auth/services/auth.service';
/**
* This is the site header component
@@ -10,6 +12,24 @@ import { RouterLink } from '@angular/router';
selector: 'app-site-header',
templateUrl: './site-header.component.html',
standalone: true,
- imports: [MatToolbarModule, MatNavList, RouterLink],
+ imports: [MatToolbarModule, MatNavList, MatButtonModule, RouterLink],
})
-export class SiteHeaderComponent {}
+export class SiteHeaderComponent {
+ #authService = inject(AuthService);
+
+ isLoggedIn = this.#authService.isLoggedIn;
+
+ /**
+ * User login
+ */
+ onLogin(): void {
+ this.#authService.login();
+ }
+
+ /**
+ * User logout
+ */
+ onLogout(): void {
+ this.#authService.logout();
+ }
+}
diff --git a/src/app/shared/services/config.service.ts b/src/app/shared/services/config.service.ts
index 80320f9..6054ddb 100644
--- a/src/app/shared/services/config.service.ts
+++ b/src/app/shared/services/config.service.ts
@@ -1,8 +1,18 @@
import { Injectable } from '@angular/core';
interface Config {
+ base_url: string;
+ auth_url: string;
mass_url: string;
metldata_url: string;
+ oidc_client_id: string;
+ oidc_redirect_url: string;
+ oidc_scope: string;
+ oidc_authority_url: string;
+ oidc_authorization_url: string;
+ oidc_token_url: string;
+ oidc_userinfo_url: string;
+ oidc_use_discovery: boolean;
}
declare global {
@@ -11,6 +21,24 @@ declare global {
}
}
+/**
+ * Removes an end slash to a URL if needed
+ * @param url - a URL that might not end with a slash
+ * @returns the URL without an end slash
+ */
+function sansEndSlash(url: string): string {
+ return url.endsWith('/') ? url.slice(0, -1) : url;
+}
+
+/**
+ * Adds an end slash to a URL if needed
+ * @param url - a URL that might not end with a slash
+ * @returns the URL with an end slash
+ */
+function withEndSlash(url: string): string {
+ return url.endsWith('/') ? url : url + '/';
+}
+
/**
* The config service provides access to the configuration of the application.
*/
@@ -26,20 +54,104 @@ export class ConfigService {
constructor() {
this.#config = window.config;
}
+ /**
+ * Gets the application base URL from the config object
+ * @returns the application base URL sans end slash
+ */
+ get baseUrl(): string {
+ return sansEndSlash(this.#config.base_url);
+ }
+
+ /**
+ * Gets the auth service URL from the config object.
+ * @returns the auth service URL sans end slash
+ */
+ get authUrl(): string {
+ return new URL(this.#config.auth_url, withEndSlash(this.#config.base_url)).href;
+ }
/**
- * Gets the mass url from the config object.
- * @returns the mass url as a string
+ * Gets the MASS URL from the config object.
+ * @returns the MASS URL sans end slash
*/
get massUrl(): string {
- return this.#config.mass_url;
+ return new URL(this.#config.mass_url, withEndSlash(this.#config.base_url)).href;
}
/**
- * Gets the metldataUrl from the config object.
- * @returns the metldataUrl as a string
+ * Gets the metldata service URL from the config object
+ * @returns the metldata service URL sans slash
*/
get metldataUrl(): string {
- return this.#config.metldata_url;
+ return new URL(this.#config.metldata_url, withEndSlash(this.#config.base_url)).href;
+ }
+
+ /**
+ * Gets the OIDC client ID from the config object
+ * @returns the OIDC client ID
+ */
+ get oidcClientId(): string {
+ return this.#config.oidc_client_id;
+ }
+
+ /**
+ * Gets the OIDC redirect URL from the config object
+ * @returns the OIDC redirect URL
+ */
+ get oidcRedirectUrl(): string {
+ return new URL(this.#config.oidc_redirect_url, withEndSlash(this.baseUrl)).href;
+ }
+
+ /**
+ * Gets the OIDC scope from the config object
+ * @returns the OIDC scope
+ */
+ get oidcScope(): string {
+ return this.#config.oidc_scope;
+ }
+
+ /**
+ * Gets the OIDC authority URL from the config object
+ * @returns the OIDC authority URL
+ */
+ get oidcAuthorityUrl(): string {
+ return this.#config.oidc_authority_url;
+ }
+
+ /**
+ * Gets the OIDC authorization URL from the config object
+ * @returns the OIDC authorization URL
+ */
+ get oidcAuthorizationUrl(): string {
+ return new URL(
+ this.#config.oidc_authorization_url,
+ withEndSlash(this.oidcAuthorityUrl),
+ ).href;
+ }
+
+ /**
+ * Gets the OIDC token URL from the config object
+ * @returns the OIDC token URL
+ */
+ get oidcTokenUrl(): string {
+ return new URL(this.#config.oidc_token_url, withEndSlash(this.oidcAuthorityUrl))
+ .href;
+ }
+
+ /**
+ * Gets the OIDC userinfo URL from the config object
+ * @returns the OIDC userinfo URL
+ */
+ get oidcUserInfoUrl(): string {
+ return new URL(this.#config.oidc_userinfo_url, withEndSlash(this.oidcAuthorityUrl))
+ .href;
+ }
+
+ /**
+ * Checks whether OIDC discovery shall be used
+ * @returns true if OIDC discovery shall be used
+ */
+ get oidcUseDiscovery(): boolean {
+ return this.#config.oidc_use_discovery;
}
}
diff --git a/tsconfig.json b/tsconfig.json
index 95c6439..20bacef 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -22,12 +22,13 @@
"@app/*": [
"src/app/*"
]
- }
+ },
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
+ "strictStandalone": true,
"strictTemplates": true
}
}
\ No newline at end of file