From 67e2fe1c07f5e9d92cf9bd8f325155e3d14f7ea4 Mon Sep 17 00:00:00 2001 From: Brandy Smith <6577830+brandyscarney@users.noreply.github.com> Date: Fri, 23 Oct 2026 10:59:58 -0400 Subject: [PATCH 1/2] chore(lint): add eslint and prettier with ionic configs and CI workflow --- .github/CONTRIBUTING.md | 2 + .github/workflows/CI.yml | 23 +- .gitignore | 3 +- .vscode/extensions.json | 8 + eslint.config.js | 42 +- package-lock.json | 1377 +++++++++++------ package.json | 20 +- renovate.json | 12 +- src/app/app.component.html | 147 +- src/app/app.component.spec.ts | 14 +- src/app/app.component.ts | 59 +- src/app/app.routes.ts | 20 +- src/app/pages/about-popover/about-popover.ts | 18 +- src/app/pages/about/about.html | 57 +- src/app/pages/about/about.ts | 49 +- src/app/pages/account/account.ts | 29 +- src/app/pages/login/login.html | 8 +- src/app/pages/login/login.ts | 5 +- src/app/pages/map/map.ts | 49 +- .../schedule-filter/schedule-filter.html | 6 +- .../schedule-filter/schedule-filter.spec.ts | 27 +- .../pages/schedule-filter/schedule-filter.ts | 53 +- src/app/pages/schedule/schedule.html | 33 +- src/app/pages/schedule/schedule.ts | 105 +- .../pages/session-detail/session-detail.html | 7 +- .../pages/session-detail/session-detail.ts | 55 +- src/app/pages/signup/signup.html | 4 +- src/app/pages/signup/signup.ts | 10 +- .../pages/speaker-detail/speaker-detail.html | 16 +- .../pages/speaker-detail/speaker-detail.ts | 50 +- src/app/pages/speaker-list/speaker-list.html | 15 +- .../pages/speaker-list/speaker-list.spec.ts | 10 +- src/app/pages/speaker-list/speaker-list.ts | 49 +- src/app/pages/support/support.ts | 39 +- src/app/pages/tabs-page/routes.ts | 31 +- src/app/pages/tabs-page/tabs-page.spec.ts | 8 +- src/app/pages/tabs-page/tabs-page.ts | 19 +- src/app/pages/tutorial/tutorial.html | 18 +- src/app/pages/tutorial/tutorial.spec.ts | 13 +- src/app/pages/tutorial/tutorial.ts | 21 +- .../providers/can-deactivate-support.guard.ts | 17 +- src/app/providers/check-tutorial.guard.ts | 4 +- src/app/providers/conference.service.ts | 37 +- src/app/providers/location.service.ts | 38 +- src/app/providers/user.service.ts | 4 +- src/index.html | 17 +- src/main.ts | 24 +- src/test.ts | 15 +- 48 files changed, 1456 insertions(+), 1231 deletions(-) create mode 100644 .vscode/extensions.json diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index e262bb637..932c4d217 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -53,6 +53,8 @@ Talk to us before creating a PR that refactors the code or directory structure o Make sure to follow the existing code style as much as possible. +Code is linted with ESLint and formatted with Prettier, and pull requests must pass `npm run lint`. Run `npm run lint:fix` to fix what can be fixed automatically. + * No underscores prefixing JS functions. * Use flat Sass: * **Don't** use [BEM conventions](https://css-tricks.com/bem-101/) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 811af68a5..641290c5b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -7,6 +7,23 @@ name: Install Dependencies, Lint, Build and Test on: [pull_request] jobs: + lint: + name: Lint + # Lint once on Linux. Windows runners check out with CRLF line endings, + # which Prettier would report as formatting changes. + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Use Node.js 24 + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: 24 + - name: Install Dependencies + run: npm ci + - name: Lint + run: npm run lint + test: name: Test on node ${{ matrix.node_version }} and ${{ matrix.os }} runs-on: ${{ matrix.os }} @@ -21,15 +38,13 @@ jobs: os: [windows-latest, macOS-latest] steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Use Node.js ${{ matrix.node_version }} - uses: actions/setup-node@v7 + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: ${{ matrix.node_version }} - name: Install Dependencies run: npm ci - - name: Lint - run: npm run lint - name: Build run: npm run build -- --configuration=production - name: Test diff --git a/.gitignore b/.gitignore index a738475a0..3a185e48c 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,8 @@ www/ log.txt *.sublime-project *.sublime-workspace -.vscode/ +.vscode/* +!.vscode/extensions.json npm-debug.log* .firebase/ .idea/ diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..2fbec7bf5 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,8 @@ +{ + "recommendations": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "Angular.ng-template", + "Webnative.webnative" + ] +} diff --git a/eslint.config.js b/eslint.config.js index 252846d00..cb0233c52 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,38 +1,29 @@ // @ts-check -const eslint = require('@eslint/js'); -const tseslint = require('typescript-eslint'); +const ionic = require('@ionic/eslint-config/recommended'); const angular = require('angular-eslint'); +const { defineConfig } = require('eslint/config'); -module.exports = tseslint.config( +module.exports = defineConfig([ { - ignores: ['www/**', 'dist/**', 'coverage/**', '.angular/**'], + ignores: ['www/**', 'dist/**', 'coverage/**', '.angular/**', 'android/**', 'ios/**'], }, + ionic, { files: ['**/*.ts'], - extends: [ - eslint.configs.recommended, - ...tseslint.configs.recommended, - ...angular.configs.tsRecommended, - ], + extends: [angular.configs.tsRecommended], processor: angular.processInlineTemplates, rules: { + // Ionic's base level; `recommended` makes it an error, which is meant for libraries. + '@typescript-eslint/explicit-module-boundary-types': 'warn', '@typescript-eslint/explicit-member-accessibility': 'off', '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/no-inferrable-types': [ - 'error', - { ignoreParameters: true }, - ], + '@typescript-eslint/no-inferrable-types': ['error', { ignoreParameters: true }], '@typescript-eslint/no-non-null-assertion': 'error', '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/member-ordering': [ 'error', { - default: [ - 'static-field', - 'instance-field', - 'static-method', - 'instance-method', - ], + default: ['static-field', 'instance-field', 'static-method', 'instance-method'], }, ], '@typescript-eslint/naming-convention': [ @@ -47,23 +38,16 @@ module.exports = tseslint.config( '@angular-eslint/no-output-rename': 'error', '@angular-eslint/use-lifecycle-interface': 'error', '@angular-eslint/use-pipe-transform-interface': 'error', - quotes: ['error', 'single'], - semi: ['error', 'always'], - 'max-len': ['error', { code: 140 }], 'no-console': 'off', curly: 'error', eqeqeq: 'error', 'no-empty': 'off', - 'arrow-parens': ['error', 'as-needed'], 'object-shorthand': 'error', - 'eol-last': 'error', - 'no-multiple-empty-lines': ['error', { max: 1 }], - 'no-trailing-spaces': 'error', }, }, { files: ['**/*.html'], - extends: [...angular.configs.templateRecommended], + extends: [angular.configs.templateRecommended], rules: {}, - } -); + }, +]); diff --git a/package-lock.json b/package-lock.json index 6a70fb12d..a86ecdeed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,15 +48,16 @@ "@angular/compiler-cli": "^22.0.2", "@angular/language-service": "^22.0.2", "@capacitor/cli": "^8.0.0", - "@eslint/js": "^9.20.0", "@ionic/angular-toolkit": "^13.0.0", "@ionic/cli": "7.2.1", + "@ionic/eslint-config": "^0.5.0", + "@ionic/prettier-config": "^4.0.0", "@ionic/storage": "^3.0.6", "@types/jasmine": "~5.1.0", "@types/leaflet": "^1.9.17", "@types/node": "^12.11.1", - "angular-eslint": "^22.0.0", - "eslint": "^9.20.0", + "angular-eslint": "^22.6.0", + "eslint": "^10.13.0", "istanbul-lib-instrument": "^6.0.3", "jasmine-core": "~5.13.0", "jasmine-spec-reporter": "~5.0.0", @@ -65,13 +66,14 @@ "karma-coverage-istanbul-reporter": "~3.0.2", "karma-jasmine": "~5.1.0", "karma-jasmine-html-reporter": "~2.3.0", + "prettier": "^3.9.10", "puppeteer": "^11.0.0", "stylelint": "15.11.0", "stylelint-config-standard-scss": "7.0.1", "stylelint-order": "6.0.4", "ts-node": "8.10.2", "typescript": "~6.0.3", - "typescript-eslint": "^8.62.0" + "typescript-eslint": "^8.72.0" }, "engines": { "node": "24.x" @@ -2467,9 +2469,9 @@ } }, "node_modules/@angular-eslint/builder": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-22.2.0.tgz", - "integrity": "sha512-X5r6JG2VC0aZBayHM9tJYZIF5KWBo2opC4uHndhZqQqb3TmX/KYlgbMlTC4HIAXQlTXfTNbjHW8mhhAwGOaNMA==", + "version": "22.6.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-22.6.0.tgz", + "integrity": "sha512-Zn9yjLtUYKd9HF5UZXKqLKuvdYFejVuTJHQ0gFt4pjWDRvb16Lgc8EzeGyYTsc9MNnyFAmHeDTs2dtlFITSDBg==", "dev": true, "license": "MIT", "dependencies": { @@ -2481,15 +2483,22 @@ "typescript": "*" } }, + "node_modules/@angular-eslint/bundled-angular-compiler": { + "version": "22.6.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-22.6.0.tgz", + "integrity": "sha512-OOoWbFG3JOsdY9/qiY2YdXJFZNVg3jPb09OTHQvBir0CLIdEnudKePVs0JxlKL1Yl05ibvwolo+/Ewfmp5Gqvg==", + "dev": true, + "license": "MIT" + }, "node_modules/@angular-eslint/eslint-plugin": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-22.2.0.tgz", - "integrity": "sha512-ceA/aluyI7LKii+IaIjhoVCqJ3oPKC+3kqUf/DpWrgVsCbbLoW+iXCQVqMnlDZG1lagpLaqe6cIbVaH897yjPA==", + "version": "22.6.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-22.6.0.tgz", + "integrity": "sha512-zLQSfwNiOaWYp1IRQh4TlgBbUmaGm0OWNEO98E2U9DstHJTPTghRwG4wZX4Ly/YOYsb3WU06pD1/cCRUYHRgmw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "22.2.0", - "@angular-eslint/utils": "22.2.0", + "@angular-eslint/bundled-angular-compiler": "22.6.0", + "@angular-eslint/utils": "22.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { @@ -2498,80 +2507,50 @@ "typescript": "*" } }, - "node_modules/@angular-eslint/eslint-plugin/node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-22.2.0.tgz", - "integrity": "sha512-JYjUXcnZCMg23HXvHnaGcMvVF0WP9b/n9I9Oz3zY+lH2A2HkcCUYnTg3lhDghZfCcermNaz+JvXp88NX+cgA6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@angular-eslint/eslint-plugin/node_modules/@angular-eslint/utils": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-22.2.0.tgz", - "integrity": "sha512-hAAMlPhaoLI0W4CmICrLp58Jm0pMs4OBL/DYvjFu7cdoey0fRMRBiHV1Fw5lT1oHtLjsFj0n6TzvpbjGYkaYvw==", + "node_modules/@angular-eslint/eslint-plugin-template": { + "version": "22.6.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-22.6.0.tgz", + "integrity": "sha512-e3ueYzr1ARovQtoBaiAeYtLR3MLIeJNKA46LBwKbRhVl1S8L1FiwYsWJvx0lRvcgdFWFt+WrSXeTxuc0ITW9eA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "22.2.0" + "@angular-eslint/bundled-angular-compiler": "22.6.0", + "@angular-eslint/utils": "22.6.0", + "aria-query": "5.3.2", + "axobject-query": "4.1.0" }, "peerDependencies": { + "@angular-eslint/template-parser": "22.6.0", + "@typescript-eslint/types": "^8.0.0", "@typescript-eslint/utils": "^8.0.0", "eslint": "^9.0.0 || ^10.0.0", "typescript": "*" } }, "node_modules/@angular-eslint/schematics": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-22.2.0.tgz", - "integrity": "sha512-KDtjpkAUOO+wK9J5HtRQtS5lwn5UHGMLEPVFznwrK+5hrNGN9LzfAzDhAHA9y+YoplqGK/Romm4v0384e+BiWw==", + "version": "22.6.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-22.6.0.tgz", + "integrity": "sha512-rLZkMWuUxIc8IZlf3TDPkLreVAmPDAJmzqziwnBzXM8slb1xumU4yXsNk8A8nQAua4Sr1IcBKBRJKydSg8fHFg==", "dev": true, "license": "MIT", "dependencies": { "@angular-devkit/core": ">= 22.0.0 < 23.0.0", "@angular-devkit/schematics": ">= 22.0.0 < 23.0.0", - "@angular-eslint/eslint-plugin": "22.2.0", - "@angular-eslint/eslint-plugin-template": "22.2.0", - "ignore": "7.0.6", + "@angular-eslint/eslint-plugin": "22.6.0", + "@angular-eslint/eslint-plugin-template": "22.6.0", + "ignore": "7.0.12", "semver": "7.8.5", "strip-json-comments": "3.1.1" } }, - "node_modules/@angular-eslint/schematics/node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-22.2.0.tgz", - "integrity": "sha512-JYjUXcnZCMg23HXvHnaGcMvVF0WP9b/n9I9Oz3zY+lH2A2HkcCUYnTg3lhDghZfCcermNaz+JvXp88NX+cgA6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@angular-eslint/schematics/node_modules/@angular-eslint/eslint-plugin-template": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-22.2.0.tgz", - "integrity": "sha512-v/X8/QJXWXaOkU8chmIPWu/86JAca5Tje6EFIf3G2VOxxuGzDpCPPuAKLBclhK+dtFHuJnqKYKZOfcdXqzj9eg==", + "node_modules/@angular-eslint/template-parser": { + "version": "22.6.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-22.6.0.tgz", + "integrity": "sha512-QmrW5T9Sb8ve2cgEGtkhDujp7ENRnXkqT+nCxLK0rZkbPXET+i1svLxuc4tzyVJpceYo772EzMyQuJbNqiH/cA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "22.2.0", - "@angular-eslint/utils": "22.2.0", - "aria-query": "5.3.2", - "axobject-query": "4.1.0" - }, - "peerDependencies": { - "@angular-eslint/template-parser": "22.2.0", - "@typescript-eslint/types": "^8.0.0", - "@typescript-eslint/utils": "^8.0.0", - "eslint": "^9.0.0 || ^10.0.0", - "typescript": "*" - } - }, - "node_modules/@angular-eslint/schematics/node_modules/@angular-eslint/template-parser": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-22.2.0.tgz", - "integrity": "sha512-RCDEzYRFIV8UPWsAgj8v8ryKwXq+wAmEHqMJRqMdAGXRWrxziWvCxI7nCsj74u/11GXZKSAz3SQmwfkdWiZEQA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "22.2.0", + "@angular-eslint/bundled-angular-compiler": "22.6.0", "eslint-scope": "9.1.2" }, "peerDependencies": { @@ -2579,14 +2558,14 @@ "typescript": "*" } }, - "node_modules/@angular-eslint/schematics/node_modules/@angular-eslint/utils": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-22.2.0.tgz", - "integrity": "sha512-hAAMlPhaoLI0W4CmICrLp58Jm0pMs4OBL/DYvjFu7cdoey0fRMRBiHV1Fw5lT1oHtLjsFj0n6TzvpbjGYkaYvw==", + "node_modules/@angular-eslint/utils": { + "version": "22.6.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-22.6.0.tgz", + "integrity": "sha512-Nd5pZGgkBTvcCNMBt88iG6r/Tzk1XTWHpQQccwYUWYhz4PMim0yyXAEvqAabxag8S9iLPUEufpaOw20OOxNJ3w==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "22.2.0" + "@angular-eslint/bundled-angular-compiler": "22.6.0" }, "peerDependencies": { "@typescript-eslint/utils": "^8.0.0", @@ -2594,26 +2573,6 @@ "typescript": "*" } }, - "node_modules/@angular-eslint/schematics/node_modules/eslint-scope": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", - "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "@types/esrecurse": "^4.3.1", - "@types/estree": "^1.0.8", - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/@angular/cli": { "version": "22.1.6", "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-22.1.6.tgz", @@ -3828,6 +3787,67 @@ "node": ">=6.9.0" } }, + "node_modules/@cacheable/memory": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.2.0.tgz", + "integrity": "sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cacheable/utils": "^2.5.0", + "@keyv/bigmap": "^1.3.1", + "hookified": "^1.15.1", + "keyv": "^5.6.0" + } + }, + "node_modules/@cacheable/memory/node_modules/@keyv/bigmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz", + "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hashery": "^1.4.0", + "hookified": "^1.15.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "keyv": "^5.6.0" + } + }, + "node_modules/@cacheable/memory/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, + "node_modules/@cacheable/utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.5.0.tgz", + "integrity": "sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hashery": "^1.5.1", + "keyv": "^5.6.0" + } + }, + "node_modules/@cacheable/utils/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, "node_modules/@capacitor/android": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@capacitor/android/-/android-8.5.3.tgz", @@ -4645,165 +4665,89 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", - "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.7", + "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", - "minimatch": "^3.1.5" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" + "minimatch": "^10.2.4" }, "engines": { - "node": "*" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/config-helpers": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", - "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz", + "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.17.0" + "@eslint/core": "^1.2.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/core": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.7.tgz", - "integrity": "sha512-F42g89Qd5oAWtp0k0nnSrjziAKza7w8SVT4mStc18LZMaRb4J1HQAHLCalEtDCxrTuksx7NU9qsmeLwpOfPqWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.14.0", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.3.2", - "minimatch": "^3.1.5", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", - "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/js": { - "version": "9.39.5", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz", - "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", "dev": true, "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, "node_modules/@eslint/object-schema": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", - "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", - "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.3.tgz", + "integrity": "sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.17.0", + "@eslint/core": "^1.2.1", "levn": "^0.4.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@hapi/hoek": { @@ -5141,6 +5085,33 @@ "node": ">= 16" } }, + "node_modules/@ionic/eslint-config": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@ionic/eslint-config/-/eslint-config-0.5.0.tgz", + "integrity": "sha512-faT0ErI1LqlTJCSpIf+O9qGePbZFMVhoxUKK3xFrAgYE4gR9y8Lsa1lnEq3O5A60PUAi4upVxz+wxjZZ48mXuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint/js": "^10.0.0", + "@typescript-eslint/eslint-plugin": "^8.56.0", + "@typescript-eslint/parser": "^8.56.0", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-import-x": "^4.17.1" + }, + "peerDependencies": { + "eslint": "^10.0.0" + } + }, + "node_modules/@ionic/prettier-config": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@ionic/prettier-config/-/prettier-config-4.0.0.tgz", + "integrity": "sha512-0DqL6CggVdgeJAWOLPUT73rF1VD5p0tVlCpC5GXz5vTIUBxNwsJ5085Q7wXjKiE5Odx3aOHGTcuRWCawFsLFag==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "prettier": "^2.4.0 || ^3.0.0" + } + }, "node_modules/@ionic/storage": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/@ionic/storage/-/storage-3.0.6.tgz", @@ -5818,6 +5789,13 @@ "tslib": "2" } }, + "node_modules/@keyv/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", + "dev": true, + "license": "MIT" + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", @@ -8169,17 +8147,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.71.2.tgz", - "integrity": "sha512-K72/pvT7qpm8q3k8G5u93NCSN1RcLxX5h7Gw0bQpbMXviBHeY6Nx1WEwmk9wP+eKTSQ8ecxvcgt/ZX/rB938xQ==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.72.0.tgz", + "integrity": "sha512-aysKgysPX9XOv/dk95UkvUDe++Q3n3dJPG9CEWT3RUccxfkPJ+Qn6nhKPDhZXU6Ofo9kgwGWwKyQCnZIXTgngg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.71.2", - "@typescript-eslint/type-utils": "8.71.2", - "@typescript-eslint/utils": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2", + "@typescript-eslint/scope-manager": "8.72.0", + "@typescript-eslint/type-utils": "8.72.0", + "@typescript-eslint/utils": "8.72.0", + "@typescript-eslint/visitor-keys": "8.72.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -8192,22 +8170,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.71.2", + "@typescript-eslint/parser": "^8.72.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.71.2.tgz", - "integrity": "sha512-aTtmZjp/x3gsGHkDs04/1I8kNogBJkpQaeGaN0PfiG43NzDEmW2n+OP5im9wfsvyX0yP1UZWBrAGtDBfH9jEVw==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.72.0.tgz", + "integrity": "sha512-0O+x3ynciD6zuXb1CKSu165haQV6ey53DKhHHUnujP7U+XlltJG+/keT0Xhd1HXCze+IHf7Tvt39ovyepX/LNw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.71.2", - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2", + "@typescript-eslint/scope-manager": "8.72.0", + "@typescript-eslint/types": "8.72.0", + "@typescript-eslint/typescript-estree": "8.72.0", + "@typescript-eslint/visitor-keys": "8.72.0", "debug": "^4.4.3" }, "engines": { @@ -8223,14 +8201,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.71.2.tgz", - "integrity": "sha512-Pd68GsLVh5ZXlcEccFPdhSOvtHZ/2WU0XsA8zmXOS3F158lVlcTLhfQ6qvtL1RzbMie0Kp8xtbVwAg4nejKPHw==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.72.0.tgz", + "integrity": "sha512-bzHngBbmIgzj6TsTjVUCntGx6FFLgE7mPjpO0PzHycOaZHXqS43XnrkFIHRS16LLr/xO6FHSXG3GJFo/F4bSBQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.71.2", - "@typescript-eslint/types": "^8.71.2", + "@typescript-eslint/tsconfig-utils": "^8.72.0", + "@typescript-eslint/types": "^8.72.0", "debug": "^4.4.3" }, "engines": { @@ -8245,14 +8223,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.71.2.tgz", - "integrity": "sha512-YF4wgg5iUX5Obywoac27B56FhozMNFhdJSbh11H5GBAwmBtfyRhmgTQqW9tRNNmHDvsZ2CX6UGzoz+YfYn2Leg==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.72.0.tgz", + "integrity": "sha512-JewPyJOYcXBSAS7PIgufscHOwZqhTGyBRiQJhhuDln66tMchxvvt7nJ90JKKIoOelmdHA3kAQbm9cEUHc4JSEA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2" + "@typescript-eslint/types": "8.72.0", + "@typescript-eslint/visitor-keys": "8.72.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -8263,9 +8241,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.71.2.tgz", - "integrity": "sha512-jz49TAWokm/7yWD9/o837nYax9DyALxIPOImdImvVzo6canBCZYzin8zJyqNR5k1j9K1DE0bVvr0XYB+99uAdg==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.72.0.tgz", + "integrity": "sha512-0vbxCf7xLVPSjcOdm6eQbgViH8EDJ8xnl1laLT9yoqSz2YmcSfSg5Vdl0JUvZf6rcuJ0ZivJIuMD4edTg8obaA==", "dev": true, "license": "MIT", "engines": { @@ -8280,15 +8258,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.71.2.tgz", - "integrity": "sha512-cC8UaalCViJkb3rH/xLIvidEwoFRtMZMUqDjjJMGEKaTFwYRHYBcoczlEGHuvkHEO8svRDrgZ0yQgOArFmwang==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.72.0.tgz", + "integrity": "sha512-gEXxmmbSTSOVTC37IYYvremOM31v+UN2W772bJxmVYPhAOPSUxtacyb7wkm1EhkYKU6KzFJsdU44DCV4to0LWw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2", - "@typescript-eslint/utils": "8.71.2", + "@typescript-eslint/types": "8.72.0", + "@typescript-eslint/typescript-estree": "8.72.0", + "@typescript-eslint/utils": "8.72.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -8305,9 +8283,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.71.2.tgz", - "integrity": "sha512-y5Ukl3oVp7e/VGxqIoEXoeb/Roj71PAJ4WG/N/RGj+eeDvKRLM15kGr9MijLbN0i03S52zxu31Z98E5gWChJKw==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.72.0.tgz", + "integrity": "sha512-Adfoy59kxNEjT5E5fnyrp7GpHYuWs8ONbdohu4ez6IU46qDq8LltG90tLmkucZB2uhYL8mqBjtXqGd8yhfjXqQ==", "dev": true, "license": "MIT", "engines": { @@ -8319,16 +8297,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.71.2.tgz", - "integrity": "sha512-DgNOEsl4pdYzwSL+N/Cl33tX1Hlw3FvId73LnKXfq7jnrF2viOEn7X+P7RBkkSWCVm92gnWd28GIC5vJuLREeA==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.72.0.tgz", + "integrity": "sha512-gwLfFgWcw15tN2KXDCJvxEOQjPn+P3j/n3eSqkZ5sX4VpW9Cosodr+tWwBZRvJT3TcKx6HnPRGZMCNAiP1Xhug==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.71.2", - "@typescript-eslint/tsconfig-utils": "8.71.2", - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2", + "@typescript-eslint/project-service": "8.72.0", + "@typescript-eslint/tsconfig-utils": "8.72.0", + "@typescript-eslint/types": "8.72.0", + "@typescript-eslint/visitor-keys": "8.72.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -8347,16 +8325,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.71.2.tgz", - "integrity": "sha512-RyKa1G1M9rKHDhrk+HJtiF1MvLD5Ux2JW3TSkzw+02pRALdpJb+QzG1Y5em+LvCgzGwgg8H7mBRFKljNz7ImPw==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.72.0.tgz", + "integrity": "sha512-0up3oArJZBYnzOaEXKo8DmI43QvMZyPoFEt9LWzRJcyl/RcJjfKKPebknN1VbTgXBf3M/KggUh5uUMdURLnseg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.71.2", - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2" + "@typescript-eslint/scope-manager": "8.72.0", + "@typescript-eslint/types": "8.72.0", + "@typescript-eslint/typescript-estree": "8.72.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -8371,13 +8349,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.71.2.tgz", - "integrity": "sha512-zozlN0UA32bSG2zkKAgQyRYSbEISVoyU6vvkKYo2aSny74D8Jh4e+POkJ6Lk0dlezZi5x7TtD+88Xb06IB8nhg==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.72.0.tgz", + "integrity": "sha512-E2mroviasaWecDzTGiGMtuEguuLVOeRggnrIn93CJuxYJzQBHbyymlT08aVQydbBal5538o+JkBKXh2sRuCyIA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/types": "8.72.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -8401,6 +8379,383 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", + "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz", + "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz", + "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz", + "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz", + "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz", + "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz", + "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz", + "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz", + "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz", + "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz", + "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz", + "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz", + "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz", + "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz", + "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz", + "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-openharmony-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz", + "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz", + "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", + "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz", + "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz", + "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@webassemblyjs/ast": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", @@ -8718,19 +9073,19 @@ } }, "node_modules/angular-eslint": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/angular-eslint/-/angular-eslint-22.2.0.tgz", - "integrity": "sha512-66myS9hmanwiRlOiEwfF126jypqwiD+zc2/9dcq8zZjadXRa83Znf3KPp/4kSmSsWmDei9FgYArSmdOkPuMJQA==", + "version": "22.6.0", + "resolved": "https://registry.npmjs.org/angular-eslint/-/angular-eslint-22.6.0.tgz", + "integrity": "sha512-nHjnadgrM54bz6tq/1EJqAg1mZCjJLyunitINdpPk+07Iz5MkJc4F1smeYshqfhH0i9+HOyJ4c7eA419O970Pw==", "dev": true, "license": "MIT", "dependencies": { "@angular-devkit/core": ">= 22.0.0 < 23.0.0", "@angular-devkit/schematics": ">= 22.0.0 < 23.0.0", - "@angular-eslint/builder": "22.2.0", - "@angular-eslint/eslint-plugin": "22.2.0", - "@angular-eslint/eslint-plugin-template": "22.2.0", - "@angular-eslint/schematics": "22.2.0", - "@angular-eslint/template-parser": "22.2.0", + "@angular-eslint/builder": "22.6.0", + "@angular-eslint/eslint-plugin": "22.6.0", + "@angular-eslint/eslint-plugin-template": "22.6.0", + "@angular-eslint/schematics": "22.6.0", + "@angular-eslint/template-parser": "22.6.0", "@typescript-eslint/types": "^8.0.0", "@typescript-eslint/utils": "^8.0.0" }, @@ -8740,82 +9095,6 @@ "typescript-eslint": "^8.0.0" } }, - "node_modules/angular-eslint/node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-22.2.0.tgz", - "integrity": "sha512-JYjUXcnZCMg23HXvHnaGcMvVF0WP9b/n9I9Oz3zY+lH2A2HkcCUYnTg3lhDghZfCcermNaz+JvXp88NX+cgA6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/angular-eslint/node_modules/@angular-eslint/eslint-plugin-template": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-22.2.0.tgz", - "integrity": "sha512-v/X8/QJXWXaOkU8chmIPWu/86JAca5Tje6EFIf3G2VOxxuGzDpCPPuAKLBclhK+dtFHuJnqKYKZOfcdXqzj9eg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "22.2.0", - "@angular-eslint/utils": "22.2.0", - "aria-query": "5.3.2", - "axobject-query": "4.1.0" - }, - "peerDependencies": { - "@angular-eslint/template-parser": "22.2.0", - "@typescript-eslint/types": "^8.0.0", - "@typescript-eslint/utils": "^8.0.0", - "eslint": "^9.0.0 || ^10.0.0", - "typescript": "*" - } - }, - "node_modules/angular-eslint/node_modules/@angular-eslint/template-parser": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-22.2.0.tgz", - "integrity": "sha512-RCDEzYRFIV8UPWsAgj8v8ryKwXq+wAmEHqMJRqMdAGXRWrxziWvCxI7nCsj74u/11GXZKSAz3SQmwfkdWiZEQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "22.2.0", - "eslint-scope": "9.1.2" - }, - "peerDependencies": { - "eslint": "^9.0.0 || ^10.0.0", - "typescript": "*" - } - }, - "node_modules/angular-eslint/node_modules/@angular-eslint/utils": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-22.2.0.tgz", - "integrity": "sha512-hAAMlPhaoLI0W4CmICrLp58Jm0pMs4OBL/DYvjFu7cdoey0fRMRBiHV1Fw5lT1oHtLjsFj0n6TzvpbjGYkaYvw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "22.2.0" - }, - "peerDependencies": { - "@typescript-eslint/utils": "^8.0.0", - "eslint": "^9.0.0 || ^10.0.0", - "typescript": "*" - } - }, - "node_modules/angular-eslint/node_modules/eslint-scope": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", - "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@types/esrecurse": "^4.3.1", - "@types/estree": "^1.0.8", - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -9602,6 +9881,30 @@ "node": ">=6.0.0" } }, + "node_modules/cacheable": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.5.0.tgz", + "integrity": "sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cacheable/memory": "^2.2.0", + "@cacheable/utils": "^2.5.0", + "hookified": "^1.15.0", + "keyv": "^5.6.0", + "qified": "^0.10.1" + } + }, + "node_modules/cacheable/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -10112,6 +10415,16 @@ "node": ">=18" } }, + "node_modules/comment-parser": { + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.9.tgz", + "integrity": "sha512-+2AvZKjJaNq9GQljm3tr0utwrig5BL+jgJGvz5rDpGKNIp+ojcRXWUwBbh/sGIi1QCprR6PsKFakub+w1v+4hQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/component-emitter": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", @@ -11493,45 +11806,43 @@ } }, "node_modules/eslint": { - "version": "9.39.5", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.5.tgz", - "integrity": "sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "version": "10.13.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.13.0.tgz", + "integrity": "sha512-UohDjD4zSzEwhf58M3O7vc/ycc8O1I7dNlhtD0WxE8Px8EHNJKtUwzBqrzeGhisRuv2ag4sAYswszCJRgKXYUg==", "dev": true, "license": "MIT", + "workspaces": [ + "packages/*" + ], "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.2", - "@eslint/config-helpers": "^0.4.2", - "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.6", - "@eslint/js": "9.39.5", - "@eslint/plugin-kit": "^0.4.1", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.7.0", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.3", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", - "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", + "file-entry-cache": "11.1.5 || >11.1.6 <12", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.5", + "minimatch": "^10.2.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, @@ -11539,7 +11850,7 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://eslint.org/donate" @@ -11553,18 +11864,98 @@ } } }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-context": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/eslint-import-context/-/eslint-import-context-0.1.9.tgz", + "integrity": "sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-tsconfig": "^4.10.1", + "stable-hash-x": "^0.2.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-context" + }, + "peerDependencies": { + "unrs-resolver": "^1.0.0" + }, + "peerDependenciesMeta": { + "unrs-resolver": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-import-x": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.17.1.tgz", + "integrity": "sha512-4cdstYkKCyjumM2Q9NSI03K8D2a9F4Ssz33K2lv2hQa4KmR9jPLwk3uWGtNvclfqBrPGfGuMBwsGMbe6dMRbfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "^8.56.0", + "comment-parser": "^1.4.1", + "debug": "^4.4.1", + "eslint-import-context": "^0.1.9", + "is-glob": "^4.0.3", + "minimatch": "^9.0.3 || ^10.1.2", + "semver": "^7.7.2", + "stable-hash-x": "^0.2.0", + "unrs-resolver": "^1.9.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-import-x" + }, + "peerDependencies": { + "@typescript-eslint/utils": "^8.56.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "eslint-import-resolver-node": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/utils": { + "optional": true + }, + "eslint-import-resolver-node": { + "optional": true + } + } + }, "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -11601,13 +11992,13 @@ } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -11630,45 +12021,32 @@ "dev": true, "license": "MIT" }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.15.0", + "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" + "eslint-visitor-keys": "^5.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -11689,9 +12067,9 @@ } }, "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -12123,16 +12501,13 @@ } }, "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "version": "11.1.5", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz", + "integrity": "sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" + "flat-cache": "^6.1.23" } }, "node_modules/fill-range": { @@ -12198,23 +12573,21 @@ } }, "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "version": "6.1.23", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.23.tgz", + "integrity": "sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==", "dev": true, "license": "MIT", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" + "cacheable": "^2.5.0", + "flatted": "^3.4.2", + "hookified": "^1.15.0" } }, "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", "dev": true, "license": "ISC" }, @@ -12474,6 +12847,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-tsconfig": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.3.tgz", + "integrity": "sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/get-uri": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", @@ -12609,19 +12995,6 @@ "which": "bin/which" } }, - "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -12799,6 +13172,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hashery": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz", + "integrity": "sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hookified": "^1.15.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/hasown": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", @@ -12821,6 +13207,13 @@ "node": ">=16.9.0" } }, + "node_modules/hookified": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz", + "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==", + "dev": true, + "license": "MIT" + }, "node_modules/hosted-git-info": { "version": "10.1.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-10.1.1.tgz", @@ -13147,9 +13540,9 @@ "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", - "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.12.tgz", + "integrity": "sha512-/8UvqAPU9DGTI9k4mxtf49U37Isfwr8Uts96+SBHIkFxPJnHS0Ew4f00sM4Scd8V8EjM0jUNtVDdv1kPdt35lg==", "dev": true, "license": "MIT", "engines": { @@ -15227,13 +15620,6 @@ "lodash.isarray": "^3.0.0" } }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.restparam": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", @@ -16121,6 +16507,23 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/napi-postinstall": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.7.tgz", + "integrity": "sha512-jyU4cU4kVAmy/3qjP+DcoQTNXfINHc+dFw54gGqWC8nu0mpV0kOnk7kff+J+Q18SbX0k3Np8Rm7yFjd3phatNQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-patch": "lib/patch.js", + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, "node_modules/native-run": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/native-run/-/native-run-2.0.3.tgz", @@ -17464,6 +17867,22 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.10.tgz", + "integrity": "sha512-skGHTH1Yb9QvaTC4hWnRTzEYtCpApF0UMBPz+t/0ZPzP8ihefo/btKd+QA7pUE0fEwA1SbS/NmhyEcstdXOIdA==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/proc-log": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-7.0.0.tgz", @@ -17757,6 +18176,26 @@ "teleport": ">=0.2.0" } }, + "node_modules/qified": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/qified/-/qified-0.10.1.tgz", + "integrity": "sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hookified": "^2.1.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/qified/node_modules/hookified": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz", + "integrity": "sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==", + "dev": true, + "license": "MIT" + }, "node_modules/qjobs": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", @@ -18174,6 +18613,16 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/resolve-url-loader": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", @@ -19409,6 +19858,16 @@ "node": ">=0.10.0" } }, + "node_modules/stable-hash-x": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.2.0.tgz", + "integrity": "sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -20561,16 +21020,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.71.2.tgz", - "integrity": "sha512-Rz4effbMy2g9wnvOJZG6SbVavX313Lap1vNEbk1RUochzickvzP8P4HB+bkNg5e50eVz1hQGjh9K1omI1xB4Bw==", + "version": "8.72.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.72.0.tgz", + "integrity": "sha512-r26Fkc8As+mZvqp7SLsMmNFyYUup/6CjK7/eHBHmhOw6GH6n6YFxHVFrG0jN1c5CMpDzelLPxvgeCOzx7BjN+A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.71.2", - "@typescript-eslint/parser": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2", - "@typescript-eslint/utils": "8.71.2" + "@typescript-eslint/eslint-plugin": "8.72.0", + "@typescript-eslint/parser": "8.72.0", + "@typescript-eslint/typescript-estree": "8.72.0", + "@typescript-eslint/utils": "8.72.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -20686,6 +21145,44 @@ "node": ">= 0.8" } }, + "node_modules/unrs-resolver": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.4" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.12.2", + "@unrs/resolver-binding-android-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-x64": "1.12.2", + "@unrs/resolver-binding-freebsd-x64": "1.12.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", + "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-musl": "1.12.2", + "@unrs/resolver-binding-openharmony-arm64": "1.12.2", + "@unrs/resolver-binding-wasm32-wasi": "1.12.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" + } + }, "node_modules/untildify": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", diff --git a/package.json b/package.json index 7a1257408..0a5879459 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,11 @@ "start": "ng serve", "build": "ng build", "test": "ng test", - "lint": "ng lint && npm run lint:sass", - "lint:sass": "stylelint \"src/**/*.scss\"" + "lint": "npm run eslint && npm run lint:sass && npm run prettier -- --check", + "lint:sass": "stylelint \"src/**/*.scss\"", + "lint:fix": "npm run eslint -- --fix && npm run prettier -- --write", + "eslint": "ng lint", + "prettier": "prettier \"**/*.{ts,html}\"" }, "repository": { "type": "git", @@ -60,15 +63,16 @@ "@angular/compiler-cli": "^22.0.2", "@angular/language-service": "^22.0.2", "@capacitor/cli": "^8.0.0", - "@eslint/js": "^9.20.0", "@ionic/angular-toolkit": "^13.0.0", "@ionic/cli": "7.2.1", + "@ionic/eslint-config": "^0.5.0", + "@ionic/prettier-config": "^4.0.0", "@ionic/storage": "^3.0.6", "@types/jasmine": "~5.1.0", "@types/leaflet": "^1.9.17", "@types/node": "^12.11.1", - "angular-eslint": "^22.0.0", - "eslint": "^9.20.0", + "angular-eslint": "^22.6.0", + "eslint": "^10.13.0", "istanbul-lib-instrument": "^6.0.3", "jasmine-core": "~5.13.0", "jasmine-spec-reporter": "~5.0.0", @@ -77,13 +81,14 @@ "karma-coverage-istanbul-reporter": "~3.0.2", "karma-jasmine": "~5.1.0", "karma-jasmine-html-reporter": "~2.3.0", + "prettier": "^3.9.10", "puppeteer": "^11.0.0", "stylelint": "15.11.0", "stylelint-config-standard-scss": "7.0.1", "stylelint-order": "6.0.4", "ts-node": "8.10.2", "typescript": "~6.0.3", - "typescript-eslint": "^8.62.0" + "typescript-eslint": "^8.72.0" }, "browserslist": [ "Chrome >=111", @@ -91,5 +96,6 @@ "Edge >=111", "Safari >=16.4", "iOS >=16.4" - ] + ], + "prettier": "@ionic/prettier-config" } diff --git a/renovate.json b/renovate.json index 05e994119..cebe3bfd3 100644 --- a/renovate.json +++ b/renovate.json @@ -13,7 +13,7 @@ "gitIgnoredAuthors": ["hi@ionicframework.com"], "packageRules": [ { - "matchPackageNames": ["@ionic/**"], + "matchPackageNames": ["@ionic/**", "!@ionic/eslint-config", "!@ionic/prettier-config"], "minimumReleaseAge": "0 days", "groupName": "ionic" }, @@ -57,7 +57,15 @@ "description": "@types/jasmine has no 7.x release. Raise this when it publishes one." }, { - "matchPackageNames": ["eslint", "@eslint/**", "stylelint*", "typescript-eslint"], + "matchPackageNames": [ + "eslint", + "@eslint/**", + "@ionic/eslint-config", + "@ionic/prettier-config", + "prettier", + "stylelint*", + "typescript-eslint" + ], "groupName": "dev-tools" } ] diff --git a/src/app/app.component.html b/src/app/app.component.html index dc6424700..55f6c5f28 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -4,104 +4,73 @@ Conference - @for(p of appPages; track p.url; let i = $index) { - - - - - {{ p.title }} - - - + @for (p of appPages; track p.url; let i = $index) { + + + + + {{ p.title }} + + + } - @if(loggedIn()) { - - Account + @if (loggedIn()) { + + Account - - - - Account - - + + + + Account + + - - - - Support - - + + + + Support + + - - - - Logout - - - - } @if(!loggedIn()) { - - Account + + + + Logout + + + + } + @if (!loggedIn()) { + + Account - - - - Login - - + + + + Login + + - - - - Support - - + + + + Support + + - - - - Signup - - + + + + Signup + + - - - - Dark Mode - - - + + + Dark Mode + + } diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index 05e0aa2aa..bf1b288e8 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -1,15 +1,12 @@ import { provideHttpClient } from '@angular/common/http'; import { provideHttpClientTesting } from '@angular/common/http/testing'; -import { - CUSTOM_ELEMENTS_SCHEMA, - importProvidersFrom, - provideZonelessChangeDetection, -} from '@angular/core'; +import { CUSTOM_ELEMENTS_SCHEMA, importProvidersFrom, provideZonelessChangeDetection } from '@angular/core'; import { TestBed } from '@angular/core/testing'; import { provideRouter } from '@angular/router'; import { SwUpdate } from '@angular/service-worker'; import { MenuController, provideIonicAngular } from '@ionic/angular'; import { IonicStorageModule } from '@ionic/storage-angular'; + import { AppComponent } from './app.component'; import { routes } from './app.routes'; import { UserService } from './providers/user.service'; @@ -21,12 +18,9 @@ describe('AppComponent', () => { menuSpy = jasmine.createSpyObj('MenuController', ['toggle', 'enable']); userDataSpy = jasmine.createSpyObj('UserService', ['isLoggedIn', 'logout']); userDataSpy.isLoggedIn.and.returnValue(Promise.resolve(false)); - swUpdateSpy = jasmine.createSpyObj('SwUpdate', [ - 'available', - 'activateUpdate', - ]); + swUpdateSpy = jasmine.createSpyObj('SwUpdate', ['available', 'activateUpdate']); swUpdateSpy.versionUpdates = { - subscribe: jasmine.createSpy('subscribe').and.returnValue({ unsubscribe: () => {} }) + subscribe: jasmine.createSpy('subscribe').and.returnValue({ unsubscribe: () => {} }), }; await TestBed.configureTestingModule({ diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 23b3f913a..139522c33 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,14 +1,10 @@ -import { Component, inject, OnInit, signal, ViewEncapsulation } from '@angular/core'; +import type { OnInit } from '@angular/core'; +import { Component, inject, signal, ViewEncapsulation } from '@angular/core'; +import { FormsModule } from '@angular/forms'; import { Router, RouterLink, RouterLinkActive } from '@angular/router'; import { SwUpdate } from '@angular/service-worker'; -import { addIcons } from 'ionicons'; - import { SplashScreen } from '@capacitor/splash-screen'; import { StatusBar } from '@capacitor/status-bar'; - -import { Storage } from '@ionic/storage-angular'; - -import { FormsModule } from '@angular/forms'; import { IonApp, IonContent, @@ -26,6 +22,8 @@ import { Platform, ToastController, } from '@ionic/angular'; +import { Storage } from '@ionic/storage-angular'; +import { addIcons } from 'ionicons'; import { calendarOutline, hammer, @@ -39,31 +37,32 @@ import { person, personAdd, } from 'ionicons/icons'; + import { UserService } from './providers/user.service'; @Component({ - selector: 'app-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.scss'], - imports: [ - RouterLink, - RouterLinkActive, - IonRouterOutlet, - IonLabel, - IonIcon, - IonMenuToggle, - IonToggle, - IonList, - IonListHeader, - IonItem, - IonContent, - IonMenu, - IonSplitPane, - IonApp, - FormsModule, - ], - providers: [MenuController, ToastController], - encapsulation: ViewEncapsulation.None + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'], + imports: [ + RouterLink, + RouterLinkActive, + IonRouterOutlet, + IonLabel, + IonIcon, + IonMenuToggle, + IonToggle, + IonList, + IonListHeader, + IonItem, + IonContent, + IonMenu, + IonSplitPane, + IonApp, + FormsModule, + ], + providers: [MenuController, ToastController], + encapsulation: ViewEncapsulation.None, }) export class AppComponent implements OnInit { private router = inject(Router); @@ -152,7 +151,7 @@ export class AppComponent implements OnInit { } checkLoginStatus() { - return this.userService.isLoggedIn().then(loggedIn => { + return this.userService.isLoggedIn().then((loggedIn) => { return this.updateLoggedInStatus(loggedIn); }); } diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index ac838263d..032f95290 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,4 +1,5 @@ -import { Routes } from '@angular/router'; +import type { Routes } from '@angular/router'; + import { canDeactivateSupportPage } from './providers/can-deactivate-support.guard'; import { checkTutorialGuard } from './providers/check-tutorial.guard'; @@ -10,33 +11,28 @@ export const routes: Routes = [ }, { path: 'account', - loadComponent: () => - import('./pages/account/account').then(m => m.AccountPage), + loadComponent: () => import('./pages/account/account').then((m) => m.AccountPage), }, { path: 'support', - loadComponent: () => - import('./pages/support/support').then(m => m.SupportPage), + loadComponent: () => import('./pages/support/support').then((m) => m.SupportPage), canDeactivate: [canDeactivateSupportPage], }, { path: 'login', - loadComponent: () => import('./pages/login/login').then(m => m.LoginPage), + loadComponent: () => import('./pages/login/login').then((m) => m.LoginPage), }, { path: 'signup', - loadComponent: () => - import('./pages/signup/signup').then(m => m.SignupPage), + loadComponent: () => import('./pages/signup/signup').then((m) => m.SignupPage), }, { path: 'app', - loadChildren: () => - import('./pages/tabs-page/routes').then(m => m.TABS_ROUTES), + loadChildren: () => import('./pages/tabs-page/routes').then((m) => m.TABS_ROUTES), }, { path: 'tutorial', - loadComponent: () => - import('./pages/tutorial/tutorial').then(m => m.TutorialPage), + loadComponent: () => import('./pages/tutorial/tutorial').then((m) => m.TutorialPage), canMatch: [checkTutorialGuard], }, ]; diff --git a/src/app/pages/about-popover/about-popover.ts b/src/app/pages/about-popover/about-popover.ts index 9f62f2abb..b18a9dd3c 100644 --- a/src/app/pages/about-popover/about-popover.ts +++ b/src/app/pages/about-popover/about-popover.ts @@ -1,19 +1,11 @@ import { Component, inject } from '@angular/core'; import { Router } from '@angular/router'; -import { - IonItem, - IonLabel, - IonList, - PopoverController, -} from '@ionic/angular'; +import { IonItem, IonLabel, IonList, PopoverController } from '@ionic/angular'; @Component({ - template: ` + template: ` - + Learn Ionic @@ -30,8 +22,8 @@ import { `, - imports: [IonList, IonItem, IonLabel], - providers: [PopoverController] + imports: [IonList, IonItem, IonLabel], + providers: [PopoverController], }) export class PopoverPage { private router = inject(Router); diff --git a/src/app/pages/about/about.html b/src/app/pages/about/about.html index a8cb95ec9..c5edb67fa 100644 --- a/src/app/pages/about/about.html +++ b/src/app/pages/about/about.html @@ -6,11 +6,7 @@ - + @@ -18,45 +14,28 @@
-
-
-
-
+
+
+
+

About

- The Ionic Conference is a one-day event happening on {{ conferenceDate | date: - 'mediumDate' }}, featuring talks from the Ionic team. The conference focuses on - building applications with Ionic Framework, including topics such as app migration - to the latest version, Angular best practices, Webpack, Sass, and other technologies - commonly used in the Ionic ecosystem. Tickets are completely sold out, and we're expecting - over 1,000 developers — making this the largest Ionic conference to date! + The Ionic Conference is a one-day event happening on {{ conferenceDate | date: 'mediumDate' }}, featuring talks + from the Ionic team. The conference focuses on building applications with Ionic Framework, including topics such + as app migration to the latest version, Angular best practices, Webpack, Sass, and other technologies commonly + used in the Ionic ecosystem. Tickets are completely sold out, and we're expecting over 1,000 developers — making + this the largest Ionic conference to date!

Details

- + Madison, WI Austin, TX Chicago, IL @@ -65,9 +44,7 @@

Details

Date - {{ conferenceDate | date: 'mediumDate' }} + {{ conferenceDate | date: 'mediumDate' }} Details alignment="end" > - + @@ -91,9 +64,7 @@

Internet

Wifi network - - ica{{conferenceDate | date: 'y'}} - + ica{{conferenceDate | date: 'y'}} Password diff --git a/src/app/pages/about/about.ts b/src/app/pages/about/about.ts index 569bad04b..70acbb246 100644 --- a/src/app/pages/about/about.ts +++ b/src/app/pages/about/about.ts @@ -21,33 +21,34 @@ import { } from '@ionic/angular'; import { addIcons } from 'ionicons'; import { ellipsisHorizontal, ellipsisVertical } from 'ionicons/icons'; + import { PopoverPage } from '../about-popover/about-popover'; @Component({ - selector: 'page-about', - templateUrl: 'about.html', - styleUrls: ['./about.scss'], - imports: [ - NgStyle, - FormsModule, - DatePipe, - IonContent, - IonHeader, - IonToolbar, - IonButtons, - IonMenuButton, - IonButton, - IonIcon, - IonList, - IonItem, - IonLabel, - IonSelect, - IonSelectOption, - IonPopover, - IonDatetime, - IonText, - ], - providers: [PopoverController] + selector: 'page-about', + templateUrl: 'about.html', + styleUrls: ['./about.scss'], + imports: [ + NgStyle, + FormsModule, + DatePipe, + IonContent, + IonHeader, + IonToolbar, + IonButtons, + IonMenuButton, + IonButton, + IonIcon, + IonList, + IonItem, + IonLabel, + IonSelect, + IonSelectOption, + IonPopover, + IonDatetime, + IonText, + ], + providers: [PopoverController], }) export class AboutPage { location = 'madison'; diff --git a/src/app/pages/account/account.ts b/src/app/pages/account/account.ts index cd2858a15..f4b70e193 100644 --- a/src/app/pages/account/account.ts +++ b/src/app/pages/account/account.ts @@ -1,7 +1,7 @@ -import { AfterViewInit, Component, inject, signal } from '@angular/core'; -import { Router } from '@angular/router'; - import { NgOptimizedImage } from '@angular/common'; +import type { AfterViewInit } from '@angular/core'; +import { Component, inject, signal } from '@angular/core'; +import { Router } from '@angular/router'; import { AlertController, IonButtons, @@ -13,24 +13,15 @@ import { IonTitle, IonToolbar, } from '@ionic/angular'; + import { UserService } from '../../providers/user.service'; @Component({ - selector: 'page-account', - templateUrl: 'account.html', - styleUrls: ['./account.scss'], - imports: [ - IonHeader, - IonToolbar, - IonButtons, - IonMenuButton, - IonTitle, - IonContent, - IonItem, - IonList, - NgOptimizedImage, - ], - providers: [AlertController] + selector: 'page-account', + templateUrl: 'account.html', + styleUrls: ['./account.scss'], + imports: [IonHeader, IonToolbar, IonButtons, IonMenuButton, IonTitle, IonContent, IonItem, IonList, NgOptimizedImage], + providers: [AlertController], }) export class AccountPage implements AfterViewInit { private alertCtrl = inject(AlertController); @@ -77,7 +68,7 @@ export class AccountPage implements AfterViewInit { } getUsername() { - this.user.getUsername().then(username => { + this.user.getUsername().then((username) => { this.username.set(username ?? ''); }); } diff --git a/src/app/pages/login/login.html b/src/app/pages/login/login.html index 83676d73a..160868cd0 100644 --- a/src/app/pages/login/login.html +++ b/src/app/pages/login/login.html @@ -45,14 +45,10 @@ - Login + Login - Signup + Signup diff --git a/src/app/pages/login/login.ts b/src/app/pages/login/login.ts index ac2dbaf30..0a1b72d6e 100644 --- a/src/app/pages/login/login.ts +++ b/src/app/pages/login/login.ts @@ -1,5 +1,6 @@ import { Component, inject } from '@angular/core'; -import { FormsModule, NgForm } from '@angular/forms'; +import type { NgForm } from '@angular/forms'; +import { FormsModule } from '@angular/forms'; import { Router } from '@angular/router'; import { IonButton, @@ -14,7 +15,7 @@ import { IonToolbar, } from '@ionic/angular'; -import { UserOptions } from '../../interfaces/user-options'; +import type { UserOptions } from '../../interfaces/user-options'; import { UserService } from '../../providers/user.service'; @Component({ diff --git a/src/app/pages/map/map.ts b/src/app/pages/map/map.ts index 012823196..0ab0f228b 100644 --- a/src/app/pages/map/map.ts +++ b/src/app/pages/map/map.ts @@ -1,25 +1,11 @@ - -import { - AfterViewInit, - Component, - DOCUMENT, - DestroyRef, - ElementRef, - ViewChild, - inject, -} from '@angular/core'; +import type { AfterViewInit, ElementRef } from '@angular/core'; +import { Component, DOCUMENT, DestroyRef, ViewChild, inject } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; -import { - IonButtons, - IonContent, - IonHeader, - IonMenuButton, - IonTitle, - IonToolbar, -} from '@ionic/angular'; +import { IonButtons, IonContent, IonHeader, IonMenuButton, IonTitle, IonToolbar } from '@ionic/angular'; import * as L from 'leaflet'; import { firstValueFrom } from 'rxjs'; -import { Location } from '../../interfaces/conference.interfaces'; + +import type { Location } from '../../interfaces/conference.interfaces'; import { LocationService } from '../../providers/location.service'; @Component({ @@ -39,14 +25,7 @@ import { LocationService } from '../../providers/location.service'; `, styleUrls: ['./map.scss'], - imports: [ - IonHeader, - IonToolbar, - IonButtons, - IonMenuButton, - IonTitle, - IonContent, - ], + imports: [IonHeader, IonToolbar, IonButtons, IonMenuButton, IonTitle, IonContent], standalone: true, }) export class MapPage implements AfterViewInit { @@ -59,14 +38,16 @@ export class MapPage implements AfterViewInit { @ViewChild('mapCanvas', { static: true }) mapElement!: ElementRef; ngAfterViewInit() { - this.locationService.loadLocations() + this.locationService + .loadLocations() .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.initializeMap(); }); // Subscribe to location changes - this.locationService.getLocations() + this.locationService + .getLocations() .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { if (this.map) { @@ -88,7 +69,7 @@ export class MapPage implements AfterViewInit { // Remove existing map if it exists if (this.map) { this.map.remove(); - this.markers.forEach(marker => marker.remove()); + this.markers.forEach((marker) => marker.remove()); this.markers = []; } @@ -103,7 +84,7 @@ export class MapPage implements AfterViewInit { this.map = L.map(mapEle, { center: [centerLocation.lat, centerLocation.lng], zoom: 16, - preferCanvas: true + preferCanvas: true, }); // Configure default marker icon with shadow @@ -114,12 +95,12 @@ export class MapPage implements AfterViewInit { popupAnchor: [1, -34], shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png', shadowSize: [41, 41], - shadowAnchor: [12, 41] + shadowAnchor: [12, 41], }); // Add tile layer L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { - attribution: '© OpenStreetMap contributors' + attribution: '© OpenStreetMap contributors', }).addTo(this.map); // Add markers for all locations @@ -129,7 +110,7 @@ export class MapPage implements AfterViewInit { const marker = L.marker([location.lat, location.lng]) .addTo(this.map as L.Map) .bindPopup(`${location.name}`, { - className: 'location-popup' + className: 'location-popup', }); this.markers.push(marker); }); diff --git a/src/app/pages/schedule-filter/schedule-filter.html b/src/app/pages/schedule-filter/schedule-filter.html index c8dfaa56c..bf819e14c 100644 --- a/src/app/pages/schedule-filter/schedule-filter.html +++ b/src/app/pages/schedule-filter/schedule-filter.html @@ -26,11 +26,7 @@ } - - {{track.name}} - + {{track.name}} } diff --git a/src/app/pages/schedule-filter/schedule-filter.spec.ts b/src/app/pages/schedule-filter/schedule-filter.spec.ts index 44faaafff..411f1d942 100644 --- a/src/app/pages/schedule-filter/schedule-filter.spec.ts +++ b/src/app/pages/schedule-filter/schedule-filter.spec.ts @@ -1,13 +1,12 @@ -import { - CUSTOM_ELEMENTS_SCHEMA, - provideZonelessChangeDetection, -} from '@angular/core'; -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { CUSTOM_ELEMENTS_SCHEMA, provideZonelessChangeDetection } from '@angular/core'; +import type { ComponentFixture } from '@angular/core/testing'; +import { TestBed } from '@angular/core/testing'; import { ModalController, provideIonicAngular } from '@ionic/angular'; import { of } from 'rxjs'; -import { Track } from '../../interfaces/conference.interfaces'; +import type { Track } from '../../interfaces/conference.interfaces'; import { ConferenceService } from '../../providers/conference.service'; + import { ScheduleFilterPage } from './schedule-filter'; const tracks: Track[] = [ @@ -48,7 +47,7 @@ describe('ScheduleFilterPage', () => { app.ionViewWillEnter(); - const byName = new Map(app.tracks().map(t => [t.name, t.isChecked])); + const byName = new Map(app.tracks().map((t) => [t.name, t.isChecked])); expect(byName.get('Angular')).toBe(false); expect(byName.get('Tooling')).toBe(true); expect(byName.get('Documentation')).toBe(true); @@ -60,7 +59,7 @@ describe('ScheduleFilterPage', () => { app.ionViewWillEnter(); expect(app.tracks().length).toBe(tracks.length); - expect(app.tracks().every(t => t.isChecked)).toBe(true); + expect(app.tracks().every((t) => t.isChecked)).toBe(true); }); it('should sort tracks alphabetically by name', () => { @@ -68,11 +67,7 @@ describe('ScheduleFilterPage', () => { app.ionViewWillEnter(); - expect(app.tracks().map(t => t.name)).toEqual([ - 'Angular', - 'Documentation', - 'Tooling', - ]); + expect(app.tracks().map((t) => t.name)).toEqual(['Angular', 'Documentation', 'Tooling']); }); // Presents a real modal, so this covers the componentProps wiring the tests above don't. @@ -86,12 +81,10 @@ describe('ScheduleFilterPage', () => { await modal.present(); // Let the presented page finish its first render before reading the checkboxes. - await new Promise(resolve => setTimeout(resolve)); + await new Promise((resolve) => setTimeout(resolve)); const checkedFor = (name: string) => - modal.querySelector( - `ion-item[track="${name}"] ion-checkbox` - )?.checked; + modal.querySelector(`ion-item[track="${name}"] ion-checkbox`)?.checked; expect(checkedFor('angular')).withContext('tracks rendered').toBeDefined(); expect(checkedFor('angular')).toBe(false); diff --git a/src/app/pages/schedule-filter/schedule-filter.ts b/src/app/pages/schedule-filter/schedule-filter.ts index 7dfc99fa2..6f519bc13 100644 --- a/src/app/pages/schedule-filter/schedule-filter.ts +++ b/src/app/pages/schedule-filter/schedule-filter.ts @@ -30,29 +30,30 @@ import { logoIonic, restaurant, } from 'ionicons/icons'; + import { ConferenceService } from '../../providers/conference.service'; @Component({ - selector: 'page-schedule-filter', - templateUrl: 'schedule-filter.html', - styleUrls: ['./schedule-filter.scss'], - imports: [ - IonHeader, - IonToolbar, - IonButtons, - IonButton, - IonTitle, - IonContent, - IonList, - IonListHeader, - IonCheckbox, - IonFooter, - IonItem, - FormsModule, - LowerCasePipe, - IonIcon, - ], - providers: [ModalController] + selector: 'page-schedule-filter', + templateUrl: 'schedule-filter.html', + styleUrls: ['./schedule-filter.scss'], + imports: [ + IonHeader, + IonToolbar, + IonButtons, + IonButton, + IonTitle, + IonContent, + IonList, + IonListHeader, + IonCheckbox, + IonFooter, + IonItem, + FormsModule, + LowerCasePipe, + IonIcon, + ], + providers: [ModalController], }) export class ScheduleFilterPage { private config = inject(Config); @@ -87,8 +88,8 @@ export class ScheduleFilterPage { // passed in array of track names that should be excluded (unchecked) const excludedTrackNames = this.excludedTracks(); - this.confService.getTracks().subscribe(tracks => { - const filterTracks = tracks.map(track => ({ + this.confService.getTracks().subscribe((tracks) => { + const filterTracks = tracks.map((track) => ({ name: track.name, icon: track.icon, isChecked: excludedTrackNames.indexOf(track.name) === -1, @@ -101,16 +102,14 @@ export class ScheduleFilterPage { selectAll(check: boolean) { // set all to checked or unchecked - this.tracks.update(tracks => - tracks.map(track => ({ ...track, isChecked: check })) - ); + this.tracks.update((tracks) => tracks.map((track) => ({ ...track, isChecked: check }))); } applyFilters() { // Pass back a new array of track names to exclude const excludedTrackNames = this.tracks() - .filter(c => !c.isChecked) - .map(c => c.name); + .filter((c) => !c.isChecked) + .map((c) => c.name); this.dismiss(excludedTrackNames); } diff --git a/src/app/pages/schedule/schedule.html b/src/app/pages/schedule/schedule.html index 22ed5c18b..e43281ab5 100644 --- a/src/app/pages/schedule/schedule.html +++ b/src/app/pages/schedule/schedule.html @@ -54,11 +54,7 @@ Schedule - + @@ -70,33 +66,18 @@ @for (session of group.sessions; track session.id) { - +

{{session.name}}

-

- {{session.timeStart}} — {{session.timeEnd}}: - {{session.location}} -

+

{{session.timeStart}} — {{session.timeEnd}}: {{session.location}}

@if (segment === 'all') { - - Favorite - + Favorite } @if (segment === 'favorites') { - + Remove } @@ -107,9 +88,7 @@

{{session.name}}

}
- - No Sessions Found - + No Sessions Found diff --git a/src/app/pages/schedule/schedule.ts b/src/app/pages/schedule/schedule.ts index e625aa2ac..5e30bb1e8 100644 --- a/src/app/pages/schedule/schedule.ts +++ b/src/app/pages/schedule/schedule.ts @@ -1,19 +1,8 @@ -import { Component, OnInit, signal, ViewChild, inject } from '@angular/core'; -import { Router, RouterLink } from '@angular/router'; - -import { addIcons } from 'ionicons'; -import { - logoFacebook, - logoInstagram, - logoTwitter, - logoVimeo, - options, - search, - shareSocial, -} from 'ionicons/icons'; - import { LowerCasePipe } from '@angular/common'; +import type { OnInit } from '@angular/core'; +import { Component, signal, ViewChild, inject } from '@angular/core'; import { FormsModule } from '@angular/forms'; +import { Router, RouterLink } from '@angular/router'; import { AlertController, Config, @@ -44,49 +33,46 @@ import { ModalController, ToastController, } from '@ionic/angular'; -import { Group, Session } from '../../interfaces/conference.interfaces'; +import { addIcons } from 'ionicons'; +import { logoFacebook, logoInstagram, logoTwitter, logoVimeo, options, search, shareSocial } from 'ionicons/icons'; + +import type { Group, Session } from '../../interfaces/conference.interfaces'; import { ConferenceService } from '../../providers/conference.service'; import { UserService } from '../../providers/user.service'; import { ScheduleFilterPage } from '../schedule-filter/schedule-filter'; @Component({ - selector: 'page-schedule', - templateUrl: 'schedule.html', - styleUrls: ['./schedule.scss'], - imports: [ - IonHeader, - IonToolbar, - IonButtons, - IonSegment, - IonSegmentButton, - IonContent, - IonTitle, - IonSearchbar, - IonButton, - IonIcon, - IonList, - IonListHeader, - IonFab, - IonFabButton, - IonFabList, - FormsModule, - IonItemSliding, - LowerCasePipe, - RouterLink, - IonItemGroup, - IonItemDivider, - IonItemOption, - IonItemOptions, - IonLabel, - IonMenuButton, - ], - providers: [ - ModalController, - AlertController, - LoadingController, - ToastController, - Config, - ] + selector: 'page-schedule', + templateUrl: 'schedule.html', + styleUrls: ['./schedule.scss'], + imports: [ + IonHeader, + IonToolbar, + IonButtons, + IonSegment, + IonSegmentButton, + IonContent, + IonTitle, + IonSearchbar, + IonButton, + IonIcon, + IonList, + IonListHeader, + IonFab, + IonFabButton, + IonFabList, + FormsModule, + IonItemSliding, + LowerCasePipe, + RouterLink, + IonItemGroup, + IonItemDivider, + IonItemOption, + IonItemOptions, + IonLabel, + IonMenuButton, + ], + providers: [ModalController, AlertController, LoadingController, ToastController, Config], }) export class SchedulePage implements OnInit { alertCtrl = inject(AlertController); @@ -136,13 +122,8 @@ export class SchedulePage implements OnInit { } this.confService - .getTimeline( - this.dayIndex, - this.queryText, - this.excludeTrackNames, - this.segment - ) - .subscribe(data => { + .getTimeline(this.dayIndex, this.queryText, this.excludeTrackNames, this.segment) + .subscribe((data) => { this.shownSessions.set(data.shownSessions ?? 0); // getTimeline mutates group.hide in place on the cached day object and // returns the same groups array reference each call. Spread into a new @@ -196,11 +177,7 @@ export class SchedulePage implements OnInit { } } - async removeFavorite( - slidingItem: IonItemSliding, - sessionData: Session, - title: string - ) { + async removeFavorite(slidingItem: IonItemSliding, sessionData: Session, title: string) { const alert = await this.alertCtrl.create({ header: title, message: 'Would you like to remove this session from your favorites?', diff --git a/src/app/pages/session-detail/session-detail.html b/src/app/pages/session-detail/session-detail.html index a83b7f552..319878937 100644 --- a/src/app/pages/session-detail/session-detail.html +++ b/src/app/pages/session-detail/session-detail.html @@ -46,12 +46,7 @@

{{session.name}}

Download Video - + Leave Feedback diff --git a/src/app/pages/session-detail/session-detail.ts b/src/app/pages/session-detail/session-detail.ts index 445353c67..040f97142 100644 --- a/src/app/pages/session-detail/session-detail.ts +++ b/src/app/pages/session-detail/session-detail.ts @@ -14,35 +14,29 @@ import { IonToolbar, } from '@ionic/angular'; import { addIcons } from 'ionicons'; -import { - cloudDownload, - share, - shareOutline, - star, - starOutline, -} from 'ionicons/icons'; +import { cloudDownload, share, shareOutline, star, starOutline } from 'ionicons/icons'; -import { Session } from '../../interfaces/conference.interfaces'; +import type { Session } from '../../interfaces/conference.interfaces'; import { ConferenceService } from '../../providers/conference.service'; import { UserService } from '../../providers/user.service'; @Component({ - selector: 'page-session-detail', - styleUrls: ['./session-detail.scss'], - templateUrl: 'session-detail.html', - imports: [ - IonHeader, - IonToolbar, - IonButtons, - IonBackButton, - IonContent, - IonButton, - IonIcon, - IonList, - IonItem, - IonLabel, - IonText, - ] + selector: 'page-session-detail', + styleUrls: ['./session-detail.scss'], + templateUrl: 'session-detail.html', + imports: [ + IonHeader, + IonToolbar, + IonButtons, + IonBackButton, + IonContent, + IonButton, + IonIcon, + IonList, + IonItem, + IonLabel, + IonText, + ], }) export class SessionDetailPage { private confService = inject(ConferenceService); @@ -58,13 +52,8 @@ export class SessionDetailPage { } ionViewWillEnter() { - this.confService.load().subscribe(data => { - if ( - data && - data.schedule && - data.schedule[0] && - data.schedule[0].groups - ) { + this.confService.load().subscribe((data) => { + if (data && data.schedule && data.schedule[0] && data.schedule[0].groups) { const sessionId = this.route.snapshot.paramMap.get('sessionId'); for (const group of data.schedule[0].groups) { if (group && group.sessions) { @@ -72,9 +61,7 @@ export class SessionDetailPage { if (session && session.id === sessionId) { this.session.set(session); - this.isFavorite.set( - this.userService.hasFavorite(session.name) - ); + this.isFavorite.set(this.userService.hasFavorite(session.name)); break; } diff --git a/src/app/pages/signup/signup.html b/src/app/pages/signup/signup.html index 4c19a2a7e..30099476a 100644 --- a/src/app/pages/signup/signup.html +++ b/src/app/pages/signup/signup.html @@ -42,9 +42,7 @@ - Create + Create diff --git a/src/app/pages/signup/signup.ts b/src/app/pages/signup/signup.ts index 3a8fbc180..2321e8f83 100644 --- a/src/app/pages/signup/signup.ts +++ b/src/app/pages/signup/signup.ts @@ -1,5 +1,6 @@ import { Component, inject } from '@angular/core'; -import { FormsModule, NgForm } from '@angular/forms'; +import type { NgForm } from '@angular/forms'; +import { FormsModule } from '@angular/forms'; import { Router } from '@angular/router'; import { IonButton, @@ -11,13 +12,12 @@ import { IonTitle, IonToolbar, IonCol, - IonRow + IonRow, } from '@ionic/angular'; +import type { UserOptions } from '../../interfaces/user-options'; import { UserService } from '../../providers/user.service'; -import { UserOptions } from '../../interfaces/user-options'; - @Component({ selector: 'page-signup', templateUrl: 'signup.html', @@ -34,7 +34,7 @@ import { UserOptions } from '../../interfaces/user-options'; IonContent, IonInput, IonButton, - ] + ], }) export class SignupPage { router = inject(Router); diff --git a/src/app/pages/speaker-detail/speaker-detail.html b/src/app/pages/speaker-detail/speaker-detail.html index ce5d1b9f4..5653613bd 100644 --- a/src/app/pages/speaker-detail/speaker-detail.html +++ b/src/app/pages/speaker-detail/speaker-detail.html @@ -8,18 +8,10 @@ @if (speaker(); as speaker) { - + - + } @@ -38,9 +30,7 @@

{{speaker()?.name ?? 'Loading...'}}

-

- {{speaker()?.about ?? 'Loading biography...'}} Say hello on social media! -

+

{{speaker()?.about ?? 'Loading biography...'}} Say hello on social media!


diff --git a/src/app/pages/speaker-detail/speaker-detail.ts b/src/app/pages/speaker-detail/speaker-detail.ts index 82c75f6c2..e20dbcfe2 100644 --- a/src/app/pages/speaker-detail/speaker-detail.ts +++ b/src/app/pages/speaker-detail/speaker-detail.ts @@ -23,26 +23,27 @@ import { shareOutline, shareSharp, } from 'ionicons/icons'; -import { Speaker } from '../../interfaces/conference.interfaces'; + +import type { Speaker } from '../../interfaces/conference.interfaces'; import { ConferenceService } from '../../providers/conference.service'; @Component({ - selector: 'page-speaker-detail', - templateUrl: 'speaker-detail.html', - styleUrls: ['./speaker-detail.scss'], - imports: [ - IonContent, - IonHeader, - IonToolbar, - IonButtons, - IonBackButton, - IonButton, - IonIcon, - IonChip, - IonLabel, - NgOptimizedImage, - ], - providers: [ActionSheetController] + selector: 'page-speaker-detail', + templateUrl: 'speaker-detail.html', + styleUrls: ['./speaker-detail.scss'], + imports: [ + IonContent, + IonHeader, + IonToolbar, + IonButtons, + IonBackButton, + IonButton, + IonIcon, + IonChip, + IonLabel, + NgOptimizedImage, + ], + providers: [ActionSheetController], }) export class SpeakerDetailPage { speaker = signal(undefined); @@ -64,7 +65,7 @@ export class SpeakerDetailPage { } ionViewWillEnter() { - this.confService.load().subscribe(data => { + this.confService.load().subscribe((data) => { const speakerId = this.route.snapshot.paramMap.get('speakerId'); if (data && data.speakers) { for (const speaker of data.speakers) { @@ -88,16 +89,9 @@ export class SpeakerDetailPage { { text: 'Copy Link', handler: () => { - console.log( - 'Copy link clicked on https://twitter.com/' + speaker.twitter - ); - if ( - (window as any).cordova && - (window as any).cordova.plugins.clipboard - ) { - (window as any).cordova.plugins.clipboard.copy( - 'https://twitter.com/' + speaker.twitter - ); + console.log('Copy link clicked on https://twitter.com/' + speaker.twitter); + if ((window as any).cordova && (window as any).cordova.plugins.clipboard) { + (window as any).cordova.plugins.clipboard.copy('https://twitter.com/' + speaker.twitter); } }, }, diff --git a/src/app/pages/speaker-list/speaker-list.html b/src/app/pages/speaker-list/speaker-list.html index 307774928..e1623d239 100644 --- a/src/app/pages/speaker-list/speaker-list.html +++ b/src/app/pages/speaker-list/speaker-list.html @@ -27,10 +27,7 @@ routerLink="/app/tabs/speakers/speaker-details/{{speaker.id}}" > - +

{{speaker.name}}

@@ -42,20 +39,14 @@

{{speaker.name}}

@for (session of speaker.sessions; track session.id) { - +

{{session.name}}

} - +

About {{speaker.name}}

diff --git a/src/app/pages/speaker-list/speaker-list.spec.ts b/src/app/pages/speaker-list/speaker-list.spec.ts index 0740b7521..9520a8122 100644 --- a/src/app/pages/speaker-list/speaker-list.spec.ts +++ b/src/app/pages/speaker-list/speaker-list.spec.ts @@ -1,12 +1,10 @@ -import { - CUSTOM_ELEMENTS_SCHEMA, - provideZonelessChangeDetection, -} from '@angular/core'; +import { CUSTOM_ELEMENTS_SCHEMA, provideZonelessChangeDetection } from '@angular/core'; import { TestBed } from '@angular/core/testing'; import { RouteReuseStrategy, Router } from '@angular/router'; import { ActionSheetController, IonicRouteStrategy, provideIonicAngular } from '@ionic/angular'; import { ConferenceService } from '../../providers/conference.service'; + import { SpeakerListPage } from './speaker-list'; const confDataSub = {}; @@ -14,9 +12,7 @@ const confDataSub = {}; describe('SpeakerListPage', () => { let fixture, app: SpeakerListPage; beforeEach(async () => { - const actionSheetSpy = jasmine.createSpyObj('ActionSheetController', [ - 'create', - ]); + const actionSheetSpy = jasmine.createSpyObj('ActionSheetController', ['create']); const routerSpy = jasmine.createSpyObj('Router', ['navigateByUrl']); await TestBed.configureTestingModule({ diff --git a/src/app/pages/speaker-list/speaker-list.ts b/src/app/pages/speaker-list/speaker-list.ts index 3c0ab435c..ca1c560dc 100644 --- a/src/app/pages/speaker-list/speaker-list.ts +++ b/src/app/pages/speaker-list/speaker-list.ts @@ -18,32 +18,33 @@ import { IonTitle, IonToolbar, } from '@ionic/angular'; -import { Speaker } from '../../interfaces/conference.interfaces'; + +import type { Speaker } from '../../interfaces/conference.interfaces'; import { ConferenceService } from '../../providers/conference.service'; @Component({ - selector: 'page-speaker-list', - templateUrl: 'speaker-list.html', - styleUrls: ['./speaker-list.scss'], - imports: [ - IonHeader, - IonToolbar, - IonButtons, - IonMenuButton, - IonTitle, - IonContent, - IonGrid, - IonRow, - IonCol, - IonCard, - IonCardHeader, - IonItem, - IonAvatar, - IonLabel, - IonCardContent, - IonList, - RouterLink, - ] + selector: 'page-speaker-list', + templateUrl: 'speaker-list.html', + styleUrls: ['./speaker-list.scss'], + imports: [ + IonHeader, + IonToolbar, + IonButtons, + IonMenuButton, + IonTitle, + IonContent, + IonGrid, + IonRow, + IonCol, + IonCard, + IonCardHeader, + IonItem, + IonAvatar, + IonLabel, + IonCardContent, + IonList, + RouterLink, + ], }) export class SpeakerListPage { private confData = inject(ConferenceService); @@ -51,7 +52,7 @@ export class SpeakerListPage { speakers = signal([]); ionViewDidEnter() { - this.confData.getSpeakers().subscribe(speakers => { + this.confData.getSpeakers().subscribe((speakers) => { this.speakers.set(speakers); }); } diff --git a/src/app/pages/support/support.ts b/src/app/pages/support/support.ts index 4ade8e18a..0186ddb54 100644 --- a/src/app/pages/support/support.ts +++ b/src/app/pages/support/support.ts @@ -1,5 +1,6 @@ import { Component, inject } from '@angular/core'; -import { FormsModule, NgForm } from '@angular/forms'; +import type { NgForm } from '@angular/forms'; +import { FormsModule } from '@angular/forms'; import { AlertController, IonButton, @@ -16,24 +17,24 @@ import { } from '@ionic/angular'; @Component({ - selector: 'page-support', - templateUrl: 'support.html', - styleUrls: ['./support.scss'], - imports: [ - FormsModule, - IonHeader, - IonButton, - IonButtons, - IonContent, - IonCol, - IonHeader, - IonMenuButton, - IonRow, - IonTextarea, - IonTitle, - IonToolbar, - ], - providers: [AlertController, ToastController] + selector: 'page-support', + templateUrl: 'support.html', + styleUrls: ['./support.scss'], + imports: [ + FormsModule, + IonHeader, + IonButton, + IonButtons, + IonContent, + IonCol, + IonHeader, + IonMenuButton, + IonRow, + IonTextarea, + IonTitle, + IonToolbar, + ], + providers: [AlertController, ToastController], }) export class SupportPage { private toastCtrl = inject(ToastController); diff --git a/src/app/pages/tabs-page/routes.ts b/src/app/pages/tabs-page/routes.ts index ef0593a26..aeb53432f 100644 --- a/src/app/pages/tabs-page/routes.ts +++ b/src/app/pages/tabs-page/routes.ts @@ -1,4 +1,5 @@ -import { Routes } from '@angular/router'; +import type { Routes } from '@angular/router'; + import { TabsPage } from './tabs-page'; export const TABS_ROUTES: Routes = [ @@ -11,15 +12,11 @@ export const TABS_ROUTES: Routes = [ children: [ { path: '', - loadComponent: () => - import('../schedule/schedule').then(m => m.SchedulePage), + loadComponent: () => import('../schedule/schedule').then((m) => m.SchedulePage), }, { path: 'session/:sessionId', - loadComponent: () => - import('../session-detail/session-detail').then( - m => m.SessionDetailPage - ), + loadComponent: () => import('../session-detail/session-detail').then((m) => m.SessionDetailPage), }, ], }, @@ -28,38 +25,28 @@ export const TABS_ROUTES: Routes = [ children: [ { path: '', - loadComponent: () => - import('../speaker-list/speaker-list').then( - m => m.SpeakerListPage - ), + loadComponent: () => import('../speaker-list/speaker-list').then((m) => m.SpeakerListPage), }, { path: 'session/:sessionId', - loadComponent: () => - import('../session-detail/session-detail').then( - m => m.SessionDetailPage - ), + loadComponent: () => import('../session-detail/session-detail').then((m) => m.SessionDetailPage), }, { path: 'speaker-details/:speakerId', - loadComponent: () => - import('../speaker-detail/speaker-detail').then( - m => m.SpeakerDetailPage - ), + loadComponent: () => import('../speaker-detail/speaker-detail').then((m) => m.SpeakerDetailPage), }, ], }, { path: 'map', - loadComponent: () => import('../map/map').then(m => m.MapPage), + loadComponent: () => import('../map/map').then((m) => m.MapPage), }, { path: 'about', children: [ { path: '', - loadComponent: () => - import('../about/about').then(m => m.AboutPage), + loadComponent: () => import('../about/about').then((m) => m.AboutPage), }, ], }, diff --git a/src/app/pages/tabs-page/tabs-page.spec.ts b/src/app/pages/tabs-page/tabs-page.spec.ts index 3dfafc1d5..3215584cd 100644 --- a/src/app/pages/tabs-page/tabs-page.spec.ts +++ b/src/app/pages/tabs-page/tabs-page.spec.ts @@ -1,11 +1,9 @@ -import { - CUSTOM_ELEMENTS_SCHEMA, - provideZonelessChangeDetection, -} from '@angular/core'; +import { CUSTOM_ELEMENTS_SCHEMA, provideZonelessChangeDetection } from '@angular/core'; import { TestBed } from '@angular/core/testing'; - import { provideRouter } from '@angular/router'; + import { routes } from '../../app.routes'; + import { TabsPage } from './tabs-page'; describe('TabsPage', () => { diff --git a/src/app/pages/tabs-page/tabs-page.ts b/src/app/pages/tabs-page/tabs-page.ts index 104351865..599d59de8 100644 --- a/src/app/pages/tabs-page/tabs-page.ts +++ b/src/app/pages/tabs-page/tabs-page.ts @@ -1,25 +1,12 @@ import { Component } from '@angular/core'; import { RouterModule } from '@angular/router'; -import { - IonIcon, - IonLabel, - IonTabBar, - IonTabButton, - IonTabs, -} from '@ionic/angular'; +import { IonIcon, IonLabel, IonTabBar, IonTabButton, IonTabs } from '@ionic/angular'; import { addIcons } from 'ionicons'; import { calendar, informationCircle, location, people } from 'ionicons/icons'; @Component({ - templateUrl: 'tabs-page.html', - imports: [ - IonTabs, - IonTabBar, - IonTabButton, - IonIcon, - IonLabel, - RouterModule, - ] + templateUrl: 'tabs-page.html', + imports: [IonTabs, IonTabBar, IonTabButton, IonIcon, IonLabel, RouterModule], }) export class TabsPage { constructor() { diff --git a/src/app/pages/tutorial/tutorial.html b/src/app/pages/tutorial/tutorial.html index 1dc3bd9fd..7f73297e2 100644 --- a/src/app/pages/tutorial/tutorial.html +++ b/src/app/pages/tutorial/tutorial.html @@ -1,9 +1,7 @@ - Skip + Skip @@ -17,8 +15,8 @@

ICA

- The ionic conference app is a practical preview of the ionic - framework in action, and a demonstration of proper code use. + The ionic conference app is a practical preview of the ionic framework in action, and a demonstration of + proper code use.

@@ -26,9 +24,8 @@

What is Ionic?

- Ionic Framework is an open source SDK that enables developers to - build high quality mobile apps with web technologies like HTML, CSS, and - JavaScript. + Ionic Framework is an open source SDK that enables developers to build high quality mobile apps with web + technologies like HTML, CSS, and JavaScript.

@@ -36,9 +33,8 @@

What is Ionic?

What is Ionic Appflow?

- Ionic Appflow is a powerful set of services and features built on - top of Ionic Framework that brings a totally new level of app - development agility to mobile dev teams. + Ionic Appflow is a powerful set of services and features built on top of Ionic Framework that brings a + totally new level of app development agility to mobile dev teams.

diff --git a/src/app/pages/tutorial/tutorial.spec.ts b/src/app/pages/tutorial/tutorial.spec.ts index 534528e42..8a815f8d8 100644 --- a/src/app/pages/tutorial/tutorial.spec.ts +++ b/src/app/pages/tutorial/tutorial.spec.ts @@ -1,22 +1,17 @@ -import { - CUSTOM_ELEMENTS_SCHEMA, - importProvidersFrom, - provideZonelessChangeDetection, -} from '@angular/core'; +import { CUSTOM_ELEMENTS_SCHEMA, importProvidersFrom, provideZonelessChangeDetection } from '@angular/core'; import { TestBed } from '@angular/core/testing'; import { Router, provideRouter } from '@angular/router'; import { MenuController, provideIonicAngular } from '@ionic/angular'; import { IonicStorageModule } from '@ionic/storage-angular'; + import { routes } from '../../app.routes'; + import { TutorialPage } from './tutorial'; describe('TutorialPage', () => { let fixture, app: TutorialPage; beforeEach(async () => { - const menuSpy = jasmine.createSpyObj('MenuController', [ - 'toggle', - 'enable', - ]); + const menuSpy = jasmine.createSpyObj('MenuController', ['toggle', 'enable']); const routerSpy = jasmine.createSpyObj('Router', ['navigateByUrl']); await TestBed.configureTestingModule({ diff --git a/src/app/pages/tutorial/tutorial.ts b/src/app/pages/tutorial/tutorial.ts index 7a59e5679..42d7471b5 100644 --- a/src/app/pages/tutorial/tutorial.ts +++ b/src/app/pages/tutorial/tutorial.ts @@ -1,24 +1,15 @@ import { Component, inject } from '@angular/core'; import { Router } from '@angular/router'; - -import { - IonButton, - IonButtons, - IonContent, - IonHeader, - IonIcon, - IonToolbar, - MenuController, -} from '@ionic/angular'; +import { IonButton, IonButtons, IonContent, IonHeader, IonIcon, IonToolbar, MenuController } from '@ionic/angular'; import { Storage } from '@ionic/storage-angular'; import { addIcons } from 'ionicons'; import { arrowForward, close } from 'ionicons/icons'; @Component({ - selector: 'page-tutorial', - templateUrl: 'tutorial.html', - styleUrls: ['./tutorial.scss'], - imports: [IonHeader, IonToolbar, IonButtons, IonButton, IonContent, IonIcon] + selector: 'page-tutorial', + templateUrl: 'tutorial.html', + styleUrls: ['./tutorial.scss'], + imports: [IonHeader, IonToolbar, IonButtons, IonButton, IonContent, IonIcon], }) export class TutorialPage { menu = inject(MenuController); @@ -41,7 +32,7 @@ export class TutorialPage { } ionViewWillEnter() { - this.storage.get('ion_did_tutorial').then(res => { + this.storage.get('ion_did_tutorial').then((res) => { if (res === true) { this.router.navigateByUrl('/app/tabs/schedule', { replaceUrl: true }); } diff --git a/src/app/providers/can-deactivate-support.guard.ts b/src/app/providers/can-deactivate-support.guard.ts index 2ce17cca8..0e00ce313 100644 --- a/src/app/providers/can-deactivate-support.guard.ts +++ b/src/app/providers/can-deactivate-support.guard.ts @@ -1,24 +1,19 @@ import { inject } from '@angular/core'; -import { CanDeactivateFn } from '@angular/router'; +import type { CanDeactivateFn } from '@angular/router'; import { AlertController } from '@ionic/angular'; -import { SupportPage } from '../pages/support/support'; -export const canDeactivateSupportPage: CanDeactivateFn = async ( - component: SupportPage -) => { +import type { SupportPage } from '../pages/support/support'; + +export const canDeactivateSupportPage: CanDeactivateFn = async (component: SupportPage) => { // If the support message is empty we should just navigate - if ( - !component.supportMessage || - component.supportMessage.trim().length === 0 - ) { + if (!component.supportMessage || component.supportMessage.trim().length === 0) { return true; } const alertCtrl = inject(AlertController); const alert = await alertCtrl.create({ header: 'Leave this page?', - message: - 'Are you sure you want to leave this page? Your support message will not be submitted.', + message: 'Are you sure you want to leave this page? Your support message will not be submitted.', buttons: [ { text: 'Stay', diff --git a/src/app/providers/check-tutorial.guard.ts b/src/app/providers/check-tutorial.guard.ts index 325a93100..a68b13cd0 100644 --- a/src/app/providers/check-tutorial.guard.ts +++ b/src/app/providers/check-tutorial.guard.ts @@ -8,11 +8,11 @@ export const checkTutorialGuard = () => { const router = inject(Router); return from(storage.get('ion_did_tutorial')).pipe( - tap(didTutorial => { + tap((didTutorial) => { if (didTutorial === true) { router.navigate(['/app', 'tabs', 'schedule']); } }), - map(didTutorial => !didTutorial) + map((didTutorial) => !didTutorial), ); }; diff --git a/src/app/providers/conference.service.ts b/src/app/providers/conference.service.ts index 37b4f2ba7..201cb7fe4 100644 --- a/src/app/providers/conference.service.ts +++ b/src/app/providers/conference.service.ts @@ -3,13 +3,8 @@ import { Injectable, inject } from '@angular/core'; import { of } from 'rxjs'; import { map } from 'rxjs/operators'; -import { - ConferenceData, - Group, - ScheduleDay, - Session, - Speaker, -} from '../interfaces/conference.interfaces'; +import type { ConferenceData, Group, ScheduleDay, Session, Speaker } from '../interfaces/conference.interfaces'; + import { UserService } from './user.service'; @Injectable({ @@ -24,9 +19,7 @@ export class ConferenceService { if (this.data) { return of(this.data); } else { - return this.http - .get('assets/data/data.json') - .pipe(map(this.processData, this)); + return this.http.get('assets/data/data.json').pipe(map(this.processData, this)); } } @@ -45,9 +38,7 @@ export class ConferenceService { session.speakers = sessionSpeakers; if (session.speakerNames) { session.speakerNames.forEach((speakerName: string) => { - const speaker = data.speakers.find( - (s: Speaker) => s.name === speakerName - ); + const speaker = data.speakers.find((s: Speaker) => s.name === speakerName); if (speaker) { sessionSpeakers.push(speaker); const speakerSessions = speaker.sessions ?? []; @@ -63,21 +54,14 @@ export class ConferenceService { return data; } - getTimeline( - dayIndex: number, - queryText = '', - excludeTracks: string[] = [], - segment = 'all' - ) { + getTimeline(dayIndex: number, queryText = '', excludeTracks: string[] = [], segment = 'all') { return this.load().pipe( map((data: ConferenceData) => { const day = data.schedule[dayIndex]; let shownSessions = 0; queryText = queryText.toLowerCase().replace(/,|\.|-/g, ' '); - const queryWords = queryText - .split(' ') - .filter(w => !!w.trim().length); + const queryWords = queryText.split(' ').filter((w) => !!w.trim().length); day.groups.forEach((group: Group) => { group.hide = true; @@ -103,16 +87,11 @@ export class ConferenceService { day.shownSessions = shownSessions; return day; - }) + }), ); } - filterSession( - session: Session, - queryWords: string[], - excludeTracks: string[], - segment: string - ) { + filterSession(session: Session, queryWords: string[], excludeTracks: string[], segment: string) { let matchesQueryText = false; if (queryWords.length) { // of any query word is in the session name than it passes the query test diff --git a/src/app/providers/location.service.ts b/src/app/providers/location.service.ts index 4d9735e66..5f2fe2cab 100644 --- a/src/app/providers/location.service.ts +++ b/src/app/providers/location.service.ts @@ -1,10 +1,12 @@ -import { Injectable, inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; -import { BehaviorSubject, Observable, catchError, map, of } from 'rxjs'; -import { Location } from '../interfaces/conference.interfaces'; +import { Injectable, inject } from '@angular/core'; +import type { Observable } from 'rxjs'; +import { BehaviorSubject, catchError, map, of } from 'rxjs'; + +import type { Location } from '../interfaces/conference.interfaces'; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class LocationService { private http = inject(HttpClient); @@ -14,12 +16,12 @@ export class LocationService { loadLocations(): Observable { return this.http.get('assets/data/data.json').pipe( - map(data => { + map((data) => { if (data.map && Array.isArray(data.map)) { // Add IDs to locations const locations = data.map.map((location: any, index: number) => ({ ...location, - id: index + 1 + id: index + 1, })); this.locationsSubject.next(locations); return locations; @@ -27,19 +29,21 @@ export class LocationService { throw new Error('Invalid data format: map array not found'); } }), - catchError(error => { + catchError((error) => { console.error('Error loading locations:', error); // Set default locations if data cannot be loaded - const defaultLocations = [{ - id: 1, - name: 'Monona Terrace Convention Center', - lat: 43.071584, - lng: -89.38012, - center: true - }]; + const defaultLocations = [ + { + id: 1, + name: 'Monona Terrace Convention Center', + lat: 43.071584, + lng: -89.38012, + center: true, + }, + ]; this.locationsSubject.next(defaultLocations); return of(defaultLocations); - }) + }), ); } @@ -48,8 +52,6 @@ export class LocationService { } getCenterLocation(): Observable { - return this.locations$.pipe( - map(locations => locations.find(location => location.center)) - ); + return this.locations$.pipe(map((locations) => locations.find((location) => location.center))); } } diff --git a/src/app/providers/user.service.ts b/src/app/providers/user.service.ts index d8096c41c..bad51cf7e 100644 --- a/src/app/providers/user.service.ts +++ b/src/app/providers/user.service.ts @@ -56,13 +56,13 @@ export class UserService { } getUsername(): Promise { - return this.storage.get('username').then(value => { + return this.storage.get('username').then((value) => { return value; }); } isLoggedIn(): Promise { - return this.storage.get(this.HAS_LOGGED_IN).then(value => { + return this.storage.get(this.HAS_LOGGED_IN).then((value) => { return value === true; }); } diff --git a/src/index.html b/src/index.html index 75e52fec7..5379d69cd 100644 --- a/src/index.html +++ b/src/index.html @@ -1,15 +1,18 @@ - + - + Ionic Conference App - - - - + + + + - + diff --git a/src/main.ts b/src/main.ts index c7966c141..32313f289 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,12 +1,7 @@ import '@angular/compiler'; -import { enableProdMode, importProvidersFrom, isDevMode } from '@angular/core'; -import { - IonicRouteStrategy, - provideIonicAngular, -} from '@ionic/angular'; - import { provideHttpClient } from '@angular/common/http'; +import { enableProdMode, importProvidersFrom, isDevMode } from '@angular/core'; import { bootstrapApplication } from '@angular/platform-browser'; import { PreloadAllModules, @@ -15,11 +10,10 @@ import { withComponentInputBinding, withPreloading, } from '@angular/router'; -import { - provideServiceWorker, - ServiceWorkerModule, -} from '@angular/service-worker'; +import { provideServiceWorker, ServiceWorkerModule } from '@angular/service-worker'; +import { IonicRouteStrategy, provideIonicAngular } from '@ionic/angular'; import { IonicStorageModule } from '@ionic/storage-angular'; + import { AppComponent } from './app/app.component'; import { routes } from './app/app.routes'; import { environment } from './environments/environment'; @@ -34,21 +28,17 @@ bootstrapApplication(AppComponent, { // Lets Ionic pass overlay componentProps through ComponentRef.setInput, so pages can // read them as signal inputs instead of the deprecated NavParams. provideIonicAngular({ useSetInputAPI: true }), - provideRouter( - routes, - withPreloading(PreloadAllModules), - withComponentInputBinding() - ), + provideRouter(routes, withPreloading(PreloadAllModules), withComponentInputBinding()), provideHttpClient(), importProvidersFrom( IonicStorageModule.forRoot(), ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production, - }) + }), ), provideServiceWorker('ngsw-worker.js', { enabled: !isDevMode(), registrationStrategy: 'registerWhenStable:30000', }), ], -}).catch(err => console.error(err)); +}).catch((err) => console.error(err)); diff --git a/src/test.ts b/src/test.ts index 44672fbc9..71186e681 100644 --- a/src/test.ts +++ b/src/test.ts @@ -1,16 +1,9 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files import { getTestBed } from '@angular/core/testing'; -import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting, -} from '@angular/platform-browser-dynamic/testing'; +import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; // First, initialize the Angular testing environment. -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, +}); From 34a6e33a8cca93ef12d3b0825992f12517b2d98c Mon Sep 17 00:00:00 2001 From: Brandy Smith <6577830+brandyscarney@users.noreply.github.com> Date: Fri, 23 Oct 2026 15:17:00 -0400 Subject: [PATCH 2/2] chore(lint): ignore native projects in prettier --- .prettierignore | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .prettierignore diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..08d41d635 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +# Prettier only reads the root .gitignore, not the ones inside the native +# projects, so ignore them here to skip Capacitor's copied web build and +# Gradle's build output. +android/ +ios/