.github
.prettierrc.json
.prettierignore
-.jshintrc
-.eslintrc.json
-.eslintrc.js
-.eslintrc.cjs
-.eslintrc.mjs
-.eslintignore
+eslint.config.js
.eslintcache
.lintstagedrc.json
.lintstagedrc.js
.nycrc.json
.nyc_output
.reuse
-.release-it.json
.xmake.cfg
# Logs
logs/
--- /dev/null
+node_modules
+logs
+dist
+coverage
+++ /dev/null
-dist/
-ui/web/
+++ /dev/null
-// eslint-disable-next-line n/no-unpublished-require
-const { defineConfig } = require('eslint-define-config')
-
-module.exports = defineConfig({
- root: true,
- env: {
- es2022: true,
- node: true
- },
- parserOptions: {
- sourceType: 'module',
- ecmaVersion: 2022
- },
- plugins: ['simple-import-sort'],
- extends: ['eslint:recommended', 'plugin:import/recommended'],
- settings: {
- 'import/resolver': {
- typescript: {
- project: './tsconfig.json'
- }
- }
- },
- rules: {
- 'simple-import-sort/imports': 'error',
- 'simple-import-sort/exports': 'error'
- },
- overrides: [
- {
- files: ['**/*.ts'],
- parser: '@typescript-eslint/parser',
- parserOptions: {
- project: './tsconfig.json'
- },
- plugins: ['@typescript-eslint', 'eslint-plugin-tsdoc'],
- extends: [
- 'plugin:@typescript-eslint/strict-type-checked',
- 'plugin:@typescript-eslint/stylistic-type-checked',
- 'plugin:import/typescript',
- 'love'
- ],
- rules: {
- 'operator-linebreak': 'off',
- 'tsdoc/syntax': 'warn'
- }
- },
- {
- files: ['**/*.js', '**/*.cjs', '**/*.mjs'],
- plugins: ['jsdoc'],
- extends: ['plugin:n/recommended', 'plugin:jsdoc/recommended', 'standard'],
- rules: {
- 'n/shebang': 'off'
- }
- }
- ]
-})
This issue tracker is for bugs and issues found in e-mobility-charging-stations-simulator.
Any misuse of this issue tracker will be closed immediately, such as simulator configuration support, simulator usage support, ...
+ Support requests are expected to be filed in the [Discussions](https://github.com/poolifier/poolifier/discussions) Q&A category.
Please fill in as much of the template below as you're able.
- type: checkboxes
options:
- Simulator
- Web UI
+ - OCPP 2 Mock Server
validations:
required: true
- type: textarea
This issue tracker is for feature requests in e-mobility-charging-stations-simulator.
Any misuse of this issue tracker will be closed immediately, such as simulator configuration support, simulator usage support, ...
+ Support requests are expected to be filed in the [Discussions](https://github.com/poolifier/poolifier/discussions) Q&A category.
Please fill in as much of the template below as you're able.
- type: checkboxes
options:
- Simulator
- Web UI
+ - OCPP 2 Mock Server
validations:
required: true
- type: textarea
# Docs: https://docs.github.com/en/code-security/supply-chain-security/configuration-options-for-dependency-updates
version: 2
updates:
- - package-ecosystem: 'github-actions'
+ - package-ecosystem: github-actions
directory: '/'
schedule:
- interval: 'daily'
+ interval: daily
labels:
- 'github-actions'
- reviewers:
- - 'jerome-benoit'
- - 'olivierbagot'
- - package-ecosystem: 'npm'
+ - package-ecosystem: npm
directory: '/'
schedule:
- interval: 'daily'
+ interval: daily
+ groups:
+ regular:
+ update-types:
+ - 'patch'
+ - 'minor'
+ exclude-patterns:
+ - 'typescript'
+ typescript:
+ update-types:
+ - 'patch'
+ - 'minor'
+ - 'major'
+ patterns:
+ - 'typescript'
+ eslint:
+ update-types:
+ - 'major'
+ patterns:
+ - 'eslint'
+ - '@eslint/*'
+ mikro-orm:
+ patterns:
+ - '@mikro-orm/*'
+ commitlint:
+ patterns:
+ - '@commitlint/*'
+ vitest:
+ patterns:
+ - 'vitest'
+ - '@vitest/*'
+ vite:
+ patterns:
+ - 'vite'
+ - '@vitejs/*'
labels:
- 'dependencies'
- reviewers:
- - 'jerome-benoit'
- - 'olivierbagot'
versioning-strategy: increase
+ - package-ecosystem: pip
+ directory: 'tests/ocpp-server'
+ schedule:
+ interval: daily
+ groups:
+ regular:
+ update-types:
+ - 'patch'
+ - 'minor'
+ labels:
+ - 'dependencies'
+ - package-ecosystem: docker
+ directories:
+ - '/docker'
+ - '/ui/web/docker'
+ schedule:
+ interval: daily
+ labels:
+ - 'docker'
--- /dev/null
+<!--
+ Thanks for contributing to EVSE simulator project.
+ Please be sure to read our [contributing guidelines](https://github.com/sap/e-mobility-charging-stations-simulator/blob/master/CONTRIBUTING.md).
+-->
+
+## PR Checklist
+
+- [ ] Please add a description of your changes.
+- [ ] Please ensure title follows [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/).
+- [ ] We need your changes to come with unit tests in order to keep this project in quality and easy to maintain.
+- [ ] If your changes contain any new feature please be sure to document it.
+- [ ] Please add a link to the open issue or task that this pull request will resolve.
+
+## Does this PR introduce a breaking change?
+
+- [ ] Yes
+- [ ] No
+
+If yes please indicate it in the title and add migration info into the documentation.
+
+---
+
+<!-- Your PR text -->
--- /dev/null
+{
+ "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
+ "release-type": "node",
+ "bump-minor-pre-major": true,
+ "bump-patch-for-minor-pre-major": true,
+ "tag-separator": "@",
+ "include-v-in-tag": true,
+ "packages": {
+ ".": {
+ "exclude-paths": ["ui/web", "tests/ocpp-server"],
+ "component": "simulator",
+ "extra-files": ["sonar-project.properties"]
+ },
+ "ui/web": {
+ "component": "webui",
+ "extra-files": ["sonar-project.properties"]
+ },
+ "tests/ocpp-server": {
+ "release-type": "python",
+ "component": "ocpp-server"
+ }
+ },
+ "plugins": [
+ {
+ "type": "linked-versions",
+ "groupName": "simulator-ui-ocpp-server",
+ "components": ["simulator", "webui", "ocpp-server"]
+ }
+ ],
+ "changelog-sections": [
+ { "type": "feat", "section": "🚀 Features", "hidden": false },
+ { "type": "fix", "section": "🐞 Bug Fixes", "hidden": false },
+ { "type": "perf", "section": "⚡ Performance", "hidden": false },
+ { "type": "refactor", "section": "✨ Polish", "hidden": false },
+ { "type": "test", "section": "🧪 Tests", "hidden": false },
+ { "type": "docs", "section": "📚 Documentation", "hidden": false },
+
+ { "type": "build", "section": "🤖 Automation", "hidden": false },
+ { "type": "ci", "section": "🤖 Automation", "hidden": true },
+
+ { "type": "chore", "section": "🧹 Chores", "hidden": true }
+ ]
+}
--- /dev/null
+{
+ ".": "2.0.10",
+ "ui/web": "2.0.10",
+ "tests/ocpp-server": "2.0.10"
+}
--- /dev/null
+name: autofix.ci
+on:
+ push:
+ pull_request:
+ branches: [main]
+permissions:
+ contents: read
+
+jobs:
+ autofix:
+ runs-on: ubuntu-latest
+ continue-on-error: true
+ steps:
+ - uses: actions/checkout@v4
+ - run: pipx install poetry
+ - uses: actions/setup-python@v5
+ with:
+ python-version: 3.13
+ cache: poetry
+
+ - working-directory: tests/ocpp-server
+ run: |
+ poetry install --no-root
+ poetry run task format
+
+ - uses: pnpm/action-setup@v4
+ - uses: actions/setup-node@v4
+ with:
+ cache: 'pnpm'
+
+ - run: pnpm install --ignore-scripts
+
+ - run: pnpm format
+
+ - working-directory: ui/web
+ run: |
+ pnpm format
+ pnpm lint:fix
+
+ - uses: autofix-ci/action@635ffb0c9798bd160680f18fd73371e355b85f27
else
echo "defined=false" >> $GITHUB_OUTPUT;
fi
+ build-ocpp-server:
+ strategy:
+ matrix:
+ os: [ubuntu-latest, windows-latest, macos-latest]
+ python: [3.12, 3.13]
+ name: Build OCPP mock server with Python ${{ matrix.python }} on ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ defaults:
+ run:
+ working-directory: tests/ocpp-server
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install Poetry
+ run: pipx install poetry
+ - name: Setup Python ${{ matrix.python }}
+ uses: actions/setup-python@v5
+ with:
+ python-version: ${{ matrix.python }}
+ cache: poetry
+ - name: Install Dependencies
+ run: poetry install --no-root
+ - name: Lint
+ if: ${{ matrix.os == 'ubuntu-latest' && matrix.python == '3.13' }}
+ run: poetry run task lint
build-simulator:
needs: [check-secrets]
strategy:
matrix:
os: [windows-latest, macos-latest, ubuntu-latest]
- node: ['20.x', 'latest']
+ node: ['20.x', '22.x', '24.x', 'latest']
name: Build simulator with Node ${{ matrix.node }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
steps:
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Dependency Review
- if: ${{ github.event_name == 'push' && matrix.os == 'ubuntu-latest' && matrix.node == '20.x' }}
+ if: ${{ github.event_name == 'push' && matrix.os == 'ubuntu-latest' && matrix.node == '22.x' }}
uses: actions/dependency-review-action@v4
with:
base-ref: ${{ github.ref_name }}
head-ref: ${{ github.sha }}
- name: Pull Request Dependency Review
- if: ${{ github.event_name == 'pull_request' && matrix.os == 'ubuntu-latest' && matrix.node == '20.x' }}
+ if: ${{ github.event_name == 'pull_request' && matrix.os == 'ubuntu-latest' && matrix.node == '22.x' }}
uses: actions/dependency-review-action@v4
- uses: pnpm/action-setup@v4
- name: Setup node ${{ matrix.node }}
cache: 'pnpm'
- name: pnpm install
run: pnpm install --ignore-scripts --frozen-lockfile
- - name: pnpm audit
- if: ${{ matrix.os == 'ubuntu-latest' && matrix.node == '20.x' }}
- run: pnpm audit --prod
+ # - name: pnpm audit
+ # if: ${{ matrix.os == 'ubuntu-latest' && matrix.node == '22.x' }}
+ # run: pnpm audit --prod
- name: pnpm lint
- if: ${{ matrix.os == 'ubuntu-latest' && matrix.node == '20.x' }}
+ if: ${{ matrix.os == 'ubuntu-latest' && matrix.node == '22.x' }}
run: pnpm lint
- name: pnpm build
run: pnpm build
- name: pnpm test
run: pnpm test
- name: pnpm coverage
- if: ${{ github.repository == 'sap/e-mobility-charging-stations-simulator' && matrix.os == 'ubuntu-latest' && matrix.node == '20.x' }}
+ if: ${{ github.repository == 'sap/e-mobility-charging-stations-simulator' && matrix.os == 'ubuntu-latest' && matrix.node == '22.x' }}
run: pnpm coverage
- name: SonarCloud Scan
- if: ${{ needs.check-secrets.outputs.sonar-token-exists == 'true' && github.repository == 'sap/e-mobility-charging-stations-simulator' && matrix.os == 'ubuntu-latest' && matrix.node == '20.x' }}
- uses: sonarsource/sonarcloud-github-action@v2.1.1
+ if: ${{ needs.check-secrets.outputs.sonar-token-exists == 'true' && github.repository == 'sap/e-mobility-charging-stations-simulator' && matrix.os == 'ubuntu-latest' && matrix.node == '22.x' }}
+ uses: sonarsource/sonarqube-scan-action@v5.2.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
strategy:
matrix:
os: [windows-latest, macos-latest, ubuntu-latest]
- node: ['18.x', '20.x', 'latest']
+ node: ['20.x', '22.x', '24.x', 'latest']
name: Build dashboard with Node ${{ matrix.node }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
defaults:
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Dependency Review
- if: ${{ github.event_name == 'push' && matrix.os == 'ubuntu-latest' && matrix.node == '20.x' }}
+ if: ${{ github.event_name == 'push' && matrix.os == 'ubuntu-latest' && matrix.node == '22.x' }}
uses: actions/dependency-review-action@v4
with:
base-ref: ${{ github.ref_name }}
head-ref: ${{ github.sha }}
- name: Pull Request Dependency Review
- if: ${{ github.event_name == 'pull_request' && matrix.os == 'ubuntu-latest' && matrix.node == '20.x' }}
+ if: ${{ github.event_name == 'pull_request' && matrix.os == 'ubuntu-latest' && matrix.node == '22.x' }}
uses: actions/dependency-review-action@v4
- uses: pnpm/action-setup@v4
- name: Setup node ${{ matrix.node }}
cache: 'pnpm'
- name: pnpm install
run: pnpm install --ignore-scripts --frozen-lockfile
- - name: pnpm audit
- if: ${{ matrix.os == 'ubuntu-latest' && matrix.node == '20.x' }}
- run: pnpm audit --prod
+ # - name: pnpm audit
+ # if: ${{ matrix.os == 'ubuntu-latest' && matrix.node == '22.x' }}
+ # run: pnpm audit --prod
- name: pnpm lint
- if: ${{ matrix.os == 'ubuntu-latest' && matrix.node == '20.x' }}
+ if: ${{ matrix.os == 'ubuntu-latest' && matrix.node == '22.x' }}
run: pnpm lint
- name: pnpm build
run: pnpm build
- name: pnpm test
run: pnpm test
- name: pnpm coverage
- if: ${{ github.repository == 'sap/e-mobility-charging-stations-simulator' && matrix.os == 'ubuntu-latest' && matrix.node == '20.x' }}
+ if: ${{ github.repository == 'sap/e-mobility-charging-stations-simulator' && matrix.os == 'ubuntu-latest' && matrix.node == '22.x' }}
run: pnpm coverage
- name: SonarCloud Scan
- if: ${{ needs.check-secrets.outputs.sonar-token-exists == 'true' && github.repository == 'sap/e-mobility-charging-stations-simulator' && matrix.os == 'ubuntu-latest' && matrix.node == '20.x' }}
- uses: sonarsource/sonarcloud-github-action@v2.1.1
+ if: ${{ needs.check-secrets.outputs.sonar-token-exists == 'true' && github.repository == 'sap/e-mobility-charging-stations-simulator' && matrix.os == 'ubuntu-latest' && matrix.node == '22.x' }}
+ uses: sonarsource/sonarqube-scan-action@v5.2.0
with:
projectBaseDir: ui/web
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- build-docker-image:
+ build-simulator-docker-image:
runs-on: ubuntu-latest
- name: Build docker image
+ name: Build simulator docker image
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup Docker Buildx
+ id: buildx
+ uses: docker/setup-buildx-action@v3
+ - name: Build docker image
+ run: |
+ cd docker
+ make SUBMODULES_INIT=false
+ build-dashboard-docker-image:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: ui/web
+ name: Build dashboard docker image
steps:
- uses: actions/checkout@v4
- name: Setup Docker Buildx
jobs:
clone-count:
runs-on: ubuntu-latest
+ if: github.repository == 'sap/e-mobility-charging-stations-simulator'
steps:
- uses: actions/checkout@v4
pull_request:
# The branches below must be a subset of the branches above
branches: [main]
- # merge_group:
- # branches: [main]
schedule:
- cron: '17 15 * * 1'
steps:
- name: combine-prs
id: combine-prs
- uses: github/combine-prs@v5.0.0
+ uses: github/combine-prs@v5.2.0
with:
- github_token: ${{ secrets.SECRET_TOKEN }}
+ github_token: ${{ secrets.WORKFLOW_TOKEN }}
--- /dev/null
+name: Release Please
+
+on:
+ push:
+ branches:
+ - main
+
+permissions:
+ contents: write
+ pull-requests: write
+
+jobs:
+ release-please:
+ runs-on: ubuntu-latest
+ if: github.repository == 'sap/e-mobility-charging-stations-simulator'
+ steps:
+ - uses: googleapis/release-please-action@v4
+ id: release
+ with:
+ token: ${{ secrets.WORKFLOW_TOKEN }}
+ config-file: .github/release-please/config.json
+ manifest-file: .github/release-please/manifest.json
+ - uses: actions/checkout@v4
+ if: ${{ steps.release.outputs.release_created }}
+ - name: Create tags for major and minor versions
+ if: ${{ steps.release.outputs.release_created }}
+ run: |
+ git config user.name github-actions[bot]
+ git config user.email 41898282+github-actions[bot]@users.noreply.github.com
+ git remote add gh-token "https://${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git"
+ git tag -d v${{ steps.release.outputs.major }} || true
+ git tag -d v${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }} || true
+ git push origin :v${{ steps.release.outputs.major }} || true
+ git push origin :v${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }} || true
+ git tag -a v${{ steps.release.outputs.major }} -m "Release v${{ steps.release.outputs.major }}"
+ git tag -a v${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }} -m "Release v${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }}"
+ git push origin v${{ steps.release.outputs.major }}
+ git push origin v${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }}
-npx --no -- commitlint --edit $1
+commitlint --edit $1
-npx --no-install lint-staged
+lint-staged
export default {
- '{src,tests}/**/*.{ts,tsx,cts,mts}': ['prettier --cache --write', 'eslint --cache --fix'],
+ '**/*.{js,jsx,cjs,mjs}': ['prettier --cache --write', 'eslint --cache --fix'],
'**/*.{json,md,yml,yaml}': ['prettier --cache --write'],
- '**/*.{js,jsx,cjs,mjs}': ['prettier --cache --write', 'eslint --cache --fix']
+ '{src,tests}/**/*.{ts,tsx,cts,mts}': ['prettier --cache --write', 'eslint --cache --fix'],
}
-ignore-workspace-root-check=true
+@jsr:registry=https://npm.jsr.io
auto-install-peers=true
legacy-peer-deps=true
"arrowParens": "avoid",
"singleQuote": true,
"semi": false,
- "trailingComma": "none"
+ "trailingComma": "es5"
}
+++ /dev/null
-{
- "git": {
- "requireBranch": "main",
- "changelog": "pnpm exec auto-changelog --stdout --commit-limit false --unreleased --template https://raw.githubusercontent.com/release-it/release-it/master/templates/changelog-compact.hbs",
- "commitMessage": "chore: version ${version}",
- "tagAnnotation": "Version ${version}",
- "tagExclude": "*[-]*",
- "pushRepo": "origin"
- },
- "npm": {
- "publish": false
- },
- "github": {
- "release": true,
- "releaseName": "Version ${version}"
- },
- "plugins": {
- "@release-it/bumper": {
- "out": ["sonar-project.properties"]
- }
- },
- "hooks": {
- "after:bump": "pnpm exec auto-changelog --commit-limit false --package --template https://raw.githubusercontent.com/release-it/release-it/master/templates/keepachangelog.hbs"
- }
-}
+++ /dev/null
-Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Upstream-Name: e-mobility-charging-stations-simulator
-Upstream-Contact: Jerome Benoit <jerome.benoit@sap.com>
-Source: <https://github.com/sap/e-mobility-charging-stations-simulator>
-Disclaimer: The code in this project may include calls to APIs ("API Calls") of
- SAP or third-party products or services developed outside of this project
- ("External Products").
- "APIs" means application programming interfaces, as well as their respective
- specifications and implementing code that allows software to communicate with
- other software.
- API Calls to External Products are not licensed under the open source license
- that governs this project. The use of such API Calls and related External
- Products are subject to applicable additional agreements with the relevant
- provider of the External Products. In no event shall the open source license
- that governs this project grant any rights in or to any External Products,or
- alter, expand or supersede any terms of the applicable additional agreements.
- If you have a valid license agreement with SAP for the use of a particular SAP
- External Product, then you may make use of any API Calls included in this
- project's code for that SAP External Product, subject to the terms of such
- license agreement. If you do not have a valid license agreement for the use of
- a particular SAP External Product, then you may only make use of any API Calls
- in this project for that SAP External Product for your internal, non-productive
- and non-commercial test and evaluation of such API Calls. Nothing herein grants
- you any rights to use or access any SAP External Product, or provide any third
- parties the right to use of access any SAP External Product, through API Calls.
-
-Files: *
-Copyright: 2021-2024 SAP SE or an SAP affiliate company and e-mobility-charging-stations-simulator contributors
-License: Apache-2.0
"connor4312.nodejs-testing",
"dbaeumer.vscode-eslint",
"EditorConfig.EditorConfig",
- "ms-azuretools.vscode-docker",
+ "ms-vscode-remote.remote-containers",
"sonarsource.sonarlint-vscode",
"streetsidesoftware.code-spell-checker"
]
"bufferutil",
"cacheable",
"CENTI",
+ "chargingstations",
"choco",
"commitlint",
"corepack",
"csms",
+ "ctrlr",
"DECI",
"doctorprof",
- "emerg",
"emobility",
"evlink",
"evse",
"idtags",
"imsi",
"keba",
+ "kvar",
+ "kvarh",
"lcov",
- "linebreak",
"logform",
"measurand",
"measurands",
"mikro",
"MILLI",
"mnemonist",
+ "neostandard",
"ocpp",
"olivierbagot",
"onconnection",
"parens",
"piment",
"poolifier",
+ "postject",
"preinstall",
- "rambda",
- "Recurrency",
+ "recurrency",
"RFID",
"shutdowning",
"sonarlint",
"SRPC",
- "tsdoc",
+ "varh",
"VCAP",
"webui",
+ "workerd",
"workerset"
]
}
# Changelog
-## [v1.3.3](https://github.com/sap/e-mobility-charging-stations-simulator/compare/v1.3.2...v1.3.3)
+## [2.0.10](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator@v2.0.9...simulator@v2.0.10) (2025-07-03)
+
+### ⚡ Performance
+
+- speed up mean and median computation ([0c58e0c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/0c58e0c202eafd13fc96ea40b045e8ce9f119e52))
+
+### ✨ Polish
+
+- cleanup empty data structure checks ([3cc104c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/3cc104c22939ea5c126faf04543745f7773b5548))
+- cleanup statistics related namespace ([034962b](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/034962b82c0eb94cc3f1df604e95343ad4facc87))
+- handle empty string configuration file name ([c820074](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/c820074de27fab5f31b371c80614f0de6361b3f1))
+
+### 🤖 Automation
+
+- **deps:** bump the regular group across 1 directory with 6 updates ([#1452](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1452)) ([b039a4f](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b039a4fc9382aec82b63e48b126a47cb615f7dd4))
+
+## [2.0.9](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator@v2.0.8...simulator@v2.0.9) (2025-06-27)
+
+### 🐞 Bug Fixes
+
+- check vendorId against CS template at DataTransfer cmd handling ([#1450](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1450)) ([d39adbd](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/d39adbd45dfc5fe4a42d64b93d229cfdfad878a9))
+
+### ✨ Polish
+
+- refine type definitions ([13b0cc5](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/13b0cc5ceee4c372d64ed21c1fd783407fd119ca))
+
+### 🧪 Tests
+
+- add UTs for newly added helpers ([06ca76a](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/06ca76ae5f156e86591bb1f21c80240ff8dd956f))
+
+### 🤖 Automation
+
+- **deps-dev:** bump @types/node from 22.15.31 to 24.0.0 ([#1437](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1437)) ([b871758](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b871758ddaa7e28b479d45bf7585f172b4db36c4))
+- **deps-dev:** bump the regular group with 2 updates ([#1444](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1444)) ([dcd454c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/dcd454c166a2afcc25f992d3cb7c0fb6f7a07284))
+- **deps-dev:** bump the regular group with 3 updates ([3b34fab](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/3b34fabb6b659eadbf2ec96936851d69e43e043d))
+- **deps-dev:** bump the regular group with 3 updates ([#1427](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1427)) ([9f10bb4](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/9f10bb49f617f45d0d14c58bac901b7e0d96bc2b))
+- **deps-dev:** bump the vite group with 3 updates ([1cd81ff](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1cd81ff001b7505ddbdd9260bc5485367ac8973a))
+- **deps:** bump autofix-ci/action ([#1434](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1434)) ([25b538c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/25b538c6eb451adcad220aba48f66e9ef6d16619))
+
+## [2.0.8](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator@v2.0.7...simulator@v2.0.8) (2025-05-27)
+
+### 🐞 Bug Fixes
+
+- **docker:** dependencies installation with latest pnpm ([b1dab0c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b1dab0ce2c231c96a3ba1aecb559054879745170))
+
+### 🤖 Automation
+
+- **deps-dev:** bump @cspell/eslint-plugin from 8.19.4 to 9.0.0 ([#1408](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1408)) ([78c7a82](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/78c7a82d33b0f3a9dc9713e4631b0dbdc652b193))
+- **deps-dev:** bump lint-staged from 15.5.2 to 16.0.0 ([#1413](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1413)) ([f6d19a9](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f6d19a9dd3a420f7e2d9beeaffcddfe90ba73de5))
+- **deps:** bump sonarsource/sonarqube-scan-action from 5.1.0 to 5.2.0 ([7a64458](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/7a64458c37ea67ff15cf0723501c56fff73a56cb))
+- **deps:** bump the regular group across 1 directory with 15 updates ([c74bb2c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/c74bb2c6d158b4344ef8acfc6a8d6ae84cbc0801))
+- **deps:** bump the regular group across 1 directory with 9 updates ([#1411](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1411)) ([384bf4b](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/384bf4b7a95fbc8d93b17950b4c7988982ea648a))
+
+## [2.0.7](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator@v2.0.6...simulator@v2.0.7) (2025-04-30)
+
+### 🐞 Bug Fixes
+
+- ensure buffered messages flushing is stopped when WS is closed ([4e0e653](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/4e0e6536ce7de6a83e9343e6873d3054b58f2532))
+- throttle failed buffered messages sending with exponential backoff ([#1399](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1399)) ([f43dbe1](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f43dbe14bc4075c3fa6ec7611d8cab7885db69d6))
+
+### ✨ Polish
+
+- refine log level in buffered OCPP messages handling ([84fa762](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/84fa762257648a5d6f2095251b722563d201193d))
+
+### 📚 Documentation
+
+- recommend container tools vscode extension ([7282b15](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/7282b156ff929492e067eebe326b748e3bcc80a3))
+
+### 🤖 Automation
+
+- **deps-dev:** bump the regular group across 1 directory with 5 updates ([#1396](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1396)) ([637b90c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/637b90ccf2a4c187e5681ab37d394e4cf57dd5bf))
+- **deps-dev:** bump vite from 6.2.5 to 6.2.6 in the regular group ([#1382](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1382)) ([c369454](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/c369454c86a86543f38ce9549d16ac57a7b4e360))
+- **deps-dev:** bump vite from 6.3.3 to 6.3.4 in the regular group ([#1400](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1400)) ([3ea8331](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/3ea83318991587b84a8d7df00655f437ef170752))
+- **deps:** bump the regular group across 1 directory with 7 updates ([#1393](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1393)) ([e55d6c4](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e55d6c40ca642e2dfb9f764a2b824a4eaba38494))
+
+## [2.0.6](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator@v2.0.5...simulator@v2.0.6) (2025-04-08)
+
+### 🐞 Bug Fixes
+
+- ensure the BootNotification interval is reused a registration ([fcc3ada](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fcc3ada9f33a04267d32fac032eee1bd0ad98152))
+- gracefully handle malformed boot notification response ([db7e450](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/db7e450e595dae12f32520fe3d1a7f1061c3616f))
+
+## [2.0.5](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator@v2.0.4...simulator@v2.0.5) (2025-04-08)
+
+### 🐞 Bug Fixes
+
+- ensure CS in pending state can send boot notification ([#1376](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1376)) ([b72d174](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b72d174972edbd0572e0489036924934e6d8ea1c))
+
+### 🤖 Automation
+
+- **deps-dev:** bump the regular group with 2 updates ([1b0518d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1b0518d781c3c2f5fb08243c5e8b39cbe8da871e))
+- **deps-dev:** bump the regular group with 2 updates ([a86ad89](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a86ad89b37158d888826946197e82e28afa51606))
+- **deps:** bump the regular group with 7 updates ([33f5c72](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/33f5c724c277263dcb35d82dfb97e6d31f627175))
+
+## [2.0.4](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator@v2.0.3...simulator@v2.0.4) (2025-04-01)
+
+### 🐞 Bug Fixes
+
+- properly handle empty key array in GetConfiguration ([#1368](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1368)) ([d13819a](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/d13819a6bfadb0a08c6c2379f5a4bdb4000be4eb)), closes [#1364](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1364)
+
+### 🤖 Automation
+
+- **deps-dev:** bump the regular group with 6 updates ([da28b39](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/da28b394d059de0fd2cfa28bafe037e382411f7e))
+- **deps:** bump mongodb from 6.14.2 to 6.15.0 in the regular group ([#1354](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1354)) ([dbbcc02](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/dbbcc0206c58011165e816787efc8351193f3bcb))
+- **deps:** bump sonarsource/sonarqube-scan-action from 5.0.0 to 5.1.0 ([961c27d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/961c27d882f267bced5516081b3ddcbd157c1ca1))
+- **deps:** bump the regular group with 6 updates ([#1357](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1357)) ([93c3165](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/93c3165637b688b851ac9de682e9fcc8cc4a6d00))
+
+## [2.0.3](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator@v2.0.2...simulator@v2.0.3) (2025-03-17)
+
+### 🐞 Bug Fixes
+
+- **docker:** workaround corepack bug ([88a04b7](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/88a04b71ccf51cf4f94a279c95e072f0306d902b))
+
+### 🤖 Automation
+
+- **deps-dev:** bump @types/node in the regular group ([#1264](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1264)) ([7d3076d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/7d3076df490d0c4fe2f19bba39066384bf2a6060))
+- **deps-dev:** bump @types/node in the regular group ([#1269](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1269)) ([f76119c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f76119cefac3d3ef7f8186e5e37e92c11f58be5f))
+- **deps-dev:** bump @types/node in the regular group ([#1317](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1317)) ([cb49916](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/cb49916d261d2785d0fe96cdaf674e3fc6a29469))
+- **deps-dev:** bump eslint-plugin-perfectionist in the regular group ([#1267](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1267)) ([a5946ce](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a5946ce92ecb10e34b4f3d9141411c465bf5d7ab))
+- **deps-dev:** bump eslint-plugin-perfectionist in the regular group ([#1271](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1271)) ([ba78676](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/ba7867687bbf53d9b966d8995706348c048c6973))
+- **deps-dev:** bump eslint-plugin-vue from 9.32.0 to 9.33.0 ([56dc680](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/56dc680ad901f68459ba04bbb27ad37cc5c35264))
+- **deps-dev:** bump glob from 11.0.0 to 11.0.1 in the regular group ([#1274](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1274)) ([df397f6](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/df397f603cec1aa565474ac0d01edb7c064fdb1f))
+- **deps-dev:** bump jsdom from 25.0.1 to 26.0.0 ([#1276](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1276)) ([a082525](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a082525de20451c572433ac5cb9b4b6c0a908b1d))
+- **deps-dev:** bump the regular group across 1 directory with 2 updates ([#1349](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1349)) ([b038814](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b038814501c9bf3b83ad59afe1b92d76c520c887))
+- **deps-dev:** bump the regular group across 1 directory with 6 updates ([#1300](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1300)) ([4ec2ae9](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/4ec2ae9d1a25c3e7605fa329a59a55b9b30708ca))
+- **deps-dev:** bump the regular group with 2 updates ([#1278](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1278)) ([fa27c74](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fa27c744c34e0c70a92741acef570bdefc65c3be))
+- **deps-dev:** bump the regular group with 2 updates ([#1279](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1279)) ([84f9a57](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/84f9a5783bc76c46acf6a31c29f16f698096f318))
+- **deps-dev:** bump the regular group with 2 updates ([#1288](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1288)) ([1598cd2](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1598cd2b66f5ee794b3de24c3cddb7df27e058f9))
+- **deps-dev:** bump the regular group with 3 updates ([#1292](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1292)) ([460b4f7](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/460b4f787eaa9d6ec9ff928b5e674679ac069982))
+- **deps-dev:** bump the regular group with 3 updates ([#1316](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1316)) ([33f023c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/33f023c84ef127cd19d1034b0ca27dc54d18c30b))
+- **deps-dev:** bump the regular group with 5 updates ([#1347](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1347)) ([7de098e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/7de098e773583a32d92bd41babf6fb7590f637ee))
+- **deps-dev:** bump typescript in the typescript group ([db6e518](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/db6e518be63b8eba2510937c9291ac34acbd9563))
+- **deps-dev:** bump typescript in the typescript group ([#1275](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1275)) ([8a16c2c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/8a16c2cd8dea56de21d7a4bfabc2178b4091f6d8))
+- **deps-dev:** bump typescript in the typescript group ([#1336](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1336)) ([f59c2bc](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f59c2bc913c580258e8e574c6faa41cfbd0e2041))
+- **deps-dev:** bump vite from 5.4.11 to 5.4.12 ([#1293](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1293)) ([3935e7d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/3935e7dcb8b4d46c43f3b73db8cbd4cab0b6aa00))
+- **deps-dev:** bump vite from 5.4.14 to 6.2.0 in the vite group ([03487e6](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/03487e6ed10b9dccf45836dfc6f14e8e1ad53244))
+- **deps-dev:** bump vite from 6.2.1 to 6.2.2 in the regular group ([e406114](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e406114618fc4b9055eab801a4cca08b032683d7))
+- **deps:** bump autofix-ci/action ([#1284](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1284)) ([5c1e170](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/5c1e17073424144c5b08dbc87f997036b1fb0618))
+- **deps:** bump finalhandler from 1.3.1 to 2.1.0 ([4c20ab7](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/4c20ab72a54def59e360353ebd2d82e8c4243129))
+- **deps:** bump mnemonist from 0.40.0-rc1 to 0.40.0 ([#1298](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1298)) ([b61b19b](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b61b19b4fbd08c8efef9109529ce686c7ba74579))
+- **deps:** bump mongodb from 6.13.1 to 6.14.0 in the regular group ([e9ef4d3](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e9ef4d390b75be3c28db31d8cdf003c2427cf443))
+- **deps:** bump sonarsource/sonarqube-scan-action from 4.2.1 to 5.0.0 ([02f1f13](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/02f1f13aadb84f94b1c33f573019eeef838b0c63))
+- **deps:** bump the regular group across 1 directory with 3 updates ([3c61d82](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/3c61d827b67cda74fa4f0ff76d169a238f0ccf06))
+- **deps:** bump the regular group across 1 directory with 3 updates ([#1285](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1285)) ([1831ac9](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1831ac9e3426d88f58523de957428a121fd423b8))
+- **deps:** bump the regular group across 1 directory with 3 updates ([#1337](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1337)) ([efb264d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/efb264d54f0e3d3d0c6a024215915e95779127f8))
+- **deps:** bump the regular group across 1 directory with 5 updates ([074d58e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/074d58e7718045e8cbd1535c19f435ec27ef9d51))
+- **deps:** bump the regular group across 1 directory with 6 updates ([#1305](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1305)) ([fea949e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fea949ef7ab1ad7d8b30e34470f62703a711c067))
+- **deps:** bump the regular group across 1 directory with 9 updates ([5dd44c7](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/5dd44c73f3c8a77069d71631fa93e2d7ff9cbe6e))
+- **deps:** bump the regular group with 10 updates ([#1353](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1353)) ([0a7a66b](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/0a7a66bc2a448d881f63c361a39e193b13a8c2a3))
+- **deps:** bump the regular group with 14 updates ([97693a9](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/97693a9d2f0689847de045d4828cf3c6e1189d2e))
+- **deps:** bump the regular group with 2 updates ([a917716](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a917716e9de67dbc6211d394ebfc82eabdb008e3))
+- **deps:** bump the regular group with 2 updates ([#1262](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1262)) ([a8de006](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a8de0063cd6e9e817d8edf715679173c9beed470))
+- **deps:** bump the regular group with 5 updates ([dfca506](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/dfca506c9ff6d5908eeb6a8941967137e3bb4574))
+- **deps:** bump the regular group with 5 updates ([#1273](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1273)) ([3594fbd](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/3594fbd4ef832fb9da039f103ee6b2bc4e062863))
+- **deps:** bump the regular group with 6 updates ([#1302](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1302)) ([a12cb9b](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a12cb9bc7d6130c48ec689e34d84c2efb32343fd))
+- **deps:** bump the regular group with 8 updates ([fd124fb](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fd124fbe6004358e03569ae44027bb9886063d9c))
+
+## [2.0.2](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator@v2.0.1...simulator@v2.0.2) (2024-12-23)
+
+### ✨ Polish
+
+- cleanup some OCPP type definitions ([11ca3c7](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/11ca3c7f34134ea0db5cb3733c09b455acd80fd7))
+- deprecate incorrect error type entry ([8ae3581](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/8ae35815daa6783872a6077f97acbcd4ad7e2899))
+
+### 📚 Documentation
+
+- add link for support request GH discussions category ([7eed01f](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/7eed01f7d48ed1f3212f10ca29df09c460de6f31)), closes [#1136](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1136)
+
+### 🤖 Automation
+
+- **deps-dev:** bump @cspell/eslint-plugin in the regular group ([#1233](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1233)) ([318f5d1](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/318f5d1468ed701e2b5313fd715d6f991ef0b263))
+- **deps-dev:** bump eslint-plugin-perfectionist in the regular group ([#1242](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1242)) ([71060bb](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/71060bb2c71000868010fd2da403f2de67a7b029))
+- **deps-dev:** bump eslint-plugin-perfectionist in the regular group ([#1253](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1253)) ([8b8c282](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/8b8c282316ff8803d9ed1cd8c086b798d9e3fd77))
+- **deps-dev:** bump prettier from 3.4.1 to 3.4.2 in the regular group ([#1243](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1243)) ([a1bbf37](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a1bbf3717246b87c33e935cdb28179eb78eae109))
+- **deps-dev:** bump the regular group with 2 updates ([#1235](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1235)) ([0414e23](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/0414e23c28c3a44aea711d596516a21070a3b867))
+- **deps-dev:** bump the regular group with 2 updates ([#1250](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1250)) ([ac8c9b4](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/ac8c9b463f91ccedf33f39ab0dcb115df0fc6069))
+- **deps-dev:** bump the regular group with 2 updates ([#1258](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1258)) ([ad1ab8e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/ad1ab8e54dee1b88b5c4700cc6d8c16a4d47dafb))
+- **deps-dev:** bump the regular group with 5 updates ([#1239](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1239)) ([5b34f7a](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/5b34f7ae2193fedb89219b108bbcc696303bd910))
+- **deps-dev:** bump the regular group with 6 updates ([#1230](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1230)) ([6ffb90e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/6ffb90e3d27c1935dc65cf9517ecfec0bfe31053))
+- **deps:** bump autofix-ci/action ([#1241](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1241)) ([1c54315](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1c5431517bfa93aa1891efb8103f3edceb85e408))
+- **deps:** bump sonarsource/sonarcloud-github-action ([#1245](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1245)) ([4718131](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/4718131cdc218fa807c1687b1547c385a20697f5))
+- **deps:** bump sonarsource/sonarqube-scan-action from 4.1.0 to 4.2.1 ([#1255](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1255)) ([6d60411](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/6d604115cedb1496189db879029605b8b70f686a))
+- **deps:** bump the regular group with 2 updates ([#1228](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1228)) ([01ae0b2](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/01ae0b21e24f7490f67c7f51434c03854123be58))
+- **deps:** bump the regular group with 4 updates ([#1251](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1251)) ([2cfd250](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/2cfd2508ff99ea6600088b503e592ca0ef9a114c))
+- **deps:** bump the regular group with 5 updates ([#1249](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1249)) ([208b128](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/208b128397cb7cbc93c3d1d711be501659c643a3))
+- **deps:** bump the regular group with 5 updates ([#1254](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1254)) ([a01fdca](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a01fdca77f0394354ccd4310ff3dffb49adc1e1e))
+- **deps:** bump the regular group with 6 updates ([#1260](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1260)) ([b0ce06a](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b0ce06ab9c9454d4600c45e83fb6fd7739647756))
+
+## [2.0.1](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator@v2.0.0...simulator@v2.0.1) (2024-11-22)
+
+### 🐞 Bug Fixes
+
+- ensure undefined is handled at computing power limitation ([55a17ee](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/55a17ee03b588b4cd5b14276b1f103bcdd3ec0a4)), closes [#1223](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1223)
+
+### ✨ Polish
+
+- cleanup linter warnings ([1ea7f1d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1ea7f1dfaa14dfb2be0855e73e3b541da86af536))
+- cleanup logger export ([a715340](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a71534044917af1e6d37f5ad9209f61b3b317f7b))
+- silence linter warnings ([fa8baf1](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fa8baf177c5691312128077deb9299a44a7e2f42))
+- use micro tasks queue instead next tick one ([95e17f6](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/95e17f676b7c1067ce40de914335e35afb862df8))
+
+### 🧪 Tests
+
+- fix CI failure ([87a4259](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/87a4259551eb51e3565b14343dbdf74cc97db343))
+
+### 🤖 Automation
+
+- **deps-dev:** bump @types/node in the regular group ([05eeba4](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/05eeba4c543c89a098f89d2859922ecca92d81d3))
+- **deps-dev:** bump @types/node in the regular group ([#1206](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1206)) ([009b39e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/009b39e67fc3ed602b676daa8d7984fee62a45dc))
+- **deps-dev:** bump @types/node in the regular group ([#1207](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1207)) ([a8ecc38](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a8ecc3853c85790d59a67befa2d31e588624d29d))
+- **deps-dev:** bump eslint-plugin-jsdoc in the regular group ([#1216](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1216)) ([9369001](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/93690010cfed503d846e9df514059bfb29b2dc1b))
+- **deps-dev:** bump the regular group with 4 updates ([#1217](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1217)) ([639c849](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/639c849b2cf9fbc586f7b101896f7ed0cf61066e))
+- **deps:** bump mongodb from 6.10.0 to 6.11.0 in the regular group ([#1225](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1225)) ([087efff](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/087efff031eff90ad3fd7e161566754d4beb701b))
+- **deps:** bump the regular group across 1 directory with 2 updates ([#1203](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1203)) ([90eb3b3](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/90eb3b34a3679829df20d3b008115d23444d1c1e))
+- **deps:** bump the regular group with 11 updates ([#1215](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1215)) ([1c3e200](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1c3e200fa957bae57aa33da1117828abd6d7b61e))
+- **deps:** bump the regular group with 2 updates ([#1212](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1212)) ([7c4f2ba](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/7c4f2baeb2988e79e98a77a969f800c267c1fb44))
+- **deps:** bump the regular group with 2 updates ([#1219](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1219)) ([9b823a0](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/9b823a0faa557dadeb5ea951e76fb40ce875b553))
+- **deps:** bump the regular group with 5 updates ([#1205](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1205)) ([6e0ee99](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/6e0ee990fee626e27d99103aad81ccbc9658fd63))
+- **deps:** bump the regular group with 6 updates ([#1211](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1211)) ([636421d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/636421d3912f65978bc31ab486d4d9f0f6e3cc3d))
+- fix linter errors ([408b4e6](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/408b4e6d9b9a617ef4a1fc465e407e4711886b24))
+
+## [2.0.0](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator@v1.5.2...simulator@v2.0.0) (2024-10-23)
+
+### ⚠ BREAKING CHANGES
+
+- bump the minimum node version supported to 20.x.x
+
+### ⚡ Performance
+
+- use crypto `hash` instead of `createHash` ([1f9416c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1f9416ccaf3bacf0c4f3f61ae8501d8b3f036ad2))
+
+### 🤖 Automation
+
+- **ci:** readd pnpm audit step ([11d2ed9](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/11d2ed98b089dff19a7c2521b0f36ffc81a49b0c))
+- **ci:** switch to workflow token ([ecb01bf](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/ecb01bf1c1d631d2f0920c870097c7f17df6118a))
+- **deps-dev:** bump neostandard in the regular group ([#1198](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1198)) ([d65f40c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/d65f40c07014ba5c72e180ec8ca43b67bac0aacf))
+- **deps:** bump the regular group with 2 updates ([#1197](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1197)) ([6f31a7a](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/6f31a7a48fbe760691ebc36695ca8ab07b538f8b))
+
+### 🧹 Chores
+
+- bump the minimum node version supported to 20.x.x ([7b8957c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/7b8957c7a45de0415157f08ce7aa18e0b2fc83c4))
+
+## [1.5.2](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator@v1.5.1...simulator@v1.5.2) (2024-10-21)
+
+### 🐞 Bug Fixes
+
+- fix has() rambda usage ([dfffcac](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/dfffcac323d3168250d029205981eb8d054cb463))
+- make sea script works on Windows™ ([844081b](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/844081b0ccab6d76dcd269aeca9a4e3ae599c468))
+
+### ⚡ Performance
+
+- speed up isAsyncFunction() helper ([f8d74e9](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f8d74e92b50b36d7e5cb9c4a8ecbfcfc8fee0cee))
+
+### ✨ Polish
+
+- cleanup blank lines ([b1421bc](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b1421bc351387bb5efd738f0be8cfd5ab94a4426))
+- cleanup comments formatting ([f46aabb](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f46aabbfb98e55c0b6d4bec15a2f2e9ba92a8e14))
+- **deps-dev:** remove unused deps ([fd855c1](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fd855c1b97eb0eb50caba0f766c94b2cea4ff5e0))
+- **docker:** rename start.sh to run.sh ([baf8b16](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/baf8b16408ca3209ec4b9b8b07e1a9b026761444))
+- order ErrorType enum properly ([420b812](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/420b812b683f370ed611b3ef264909445c3e1917))
+- refine isNotEmptyString() and isNotEmptyArray() helpers type ([665864c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/665864cacd27d66cd323b6f66b2724f6e9e244e8))
+- remove unneeded blank lines ([b78c3f2](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b78c3f238166ea6c763bf046704a476a8ada90f1))
+- revert overzealous enums ordering ([42f3318](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/42f331849ea30557749162cc37b0c4658933cf93))
+- separate out dashboard docker image ([20fb109](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/20fb10949dc2553d7695be1aab02bf84a8ddab98)), closes [#1040](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1040)
+- silence linter ([a4a246b](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a4a246bbfaf265d6f91fb366c70e64a5ee84c43c))
+- switch to eslint-plugin-perfectionist ([0749233](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/0749233f25516e4c73ee8dbcea8c4ad6b8a506bb))
+- turn on `noImplicitOverride` in TS configuration ([6375d3c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/6375d3cdd7f42a6e125976df194f4fe689d24113))
+- use ENTRYPOINT syntax in docker files ([989108f](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/989108f63bd531f04b28e65c8b499c9dbf5bbed0))
+- use rambda has() helper ([e0e6de7](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e0e6de7ff7e4fad7f4b7ed364caba0a25f075a70))
+
+### 🧪 Tests
+
+- add AsyncLock test ([b842c65](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b842c65bd62d35d7b19f5d45371dfe0c6539e6d3))
+- add checkStationInfoConnectorStatus() test ([dd81d27](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/dd81d27d043073971f29ec761261489f16c66541))
+- add getPhaseRotationValue() test ([2997179](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/29971799109b0dff8f12f0977b5f520ec55cc100))
+- add missing tests/utils/AsyncLock.test.ts file ([35f57b2](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/35f57b2c14853801f09f675a08decf17f5f6da4c))
+- cleanup AsyncLock test ([213958d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/213958d630327ba513982a7f18642b09ec5a03c8))
+- fix simulator configuration test ([32f3b30](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/32f3b3045faf65cdfdf4ef7dba57e782b30b4430))
+- improve AsyncLock test coverage ([aff8ddb](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/aff8ddb379f1d6659ae6aac4d23acfecde6ceef9))
+- refine AsyncLock runExclusive() expectation ([bff96f3](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/bff96f3a942ee6ff5f85926683440945017ffeab))
+
+### 📚 Documentation
+
+- **CONTRIBUTING.md:** reference SAP GenAI contribution guidelines ([#1164](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1164)) ([0f41d83](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/0f41d83d644491bbe4247caf886136e763986119))
+
+### 🤖 Automation
+
+- **ci:** comment out pnpm audit step ([f03694f](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f03694f0645b67a40f97067eb11d6722f4897851))
+- **ci:** node 23.x support ([2244858](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/22448581a254e4ea149ad67a333d0694254dfeb0))
+- **ci:** run OCPP server build GHA on several OS ([1752bac](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1752bacff32da5e2e80ecf12f5239d6ccf256e49))
+- **ci:** silence linter errors ([3b7b2e3](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/3b7b2e36648e6af19111f3b065ff43b1dbe917aa))
+- **deps-dev:** bump @types/node from 22.0.3 to 22.1.0 ([#1120](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1120)) ([c11dc2a](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/c11dc2a0aca044ee03dc565dfaff7342b4ce039a))
+- **deps-dev:** bump @vitest/coverage-v8 from 2.0.4 to 2.0.5 ([#1117](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1117)) ([4ee8259](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/4ee82592a066961b6877858ed29a825bfd480acf))
+- **deps-dev:** bump eslint-plugin-jsdoc in the major group ([#1131](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1131)) ([90c55af](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/90c55af4d09233be277d0e73a621441a564c0199))
+- **deps-dev:** bump eslint-plugin-jsdoc in the regular group ([#1172](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1172)) ([89fb871](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/89fb871535d9c6a4d0ca08894606369a60eed86f))
+- **deps-dev:** bump eslint-plugin-jsdoc in the regular group ([#1190](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1190)) ([1d26740](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1d267405713f36adaf4e3199328a735643d13630))
+- **deps-dev:** bump eslint-plugin-jsdoc in the regular group ([#1192](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1192)) ([2cba942](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/2cba942ca12f2ea943a179cc40110445b4709e6e))
+- **deps-dev:** bump eslint-plugin-vue in the regular group ([#1195](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1195)) ([be79449](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/be7944967cff38f5afd10ee2aa20553e4284a538))
+- **deps-dev:** bump jsdom from 24.1.1 to 25.0.0 in the major group ([#1152](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1152)) ([bb7aeb1](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/bb7aeb1e64f53b1b3af1b1b33c405bb13310578c))
+- **deps-dev:** bump the regular group with 2 updates ([cc3e26b](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/cc3e26b41348dffd62937a9b44e4b22d963beebc))
+- **deps-dev:** bump the regular group with 2 updates ([#1138](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1138)) ([81fe15c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/81fe15c66400b48457ab34908cac32ca00d61e38))
+- **deps-dev:** bump the regular group with 2 updates ([#1156](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1156)) ([d366869](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/d36686932f284482ecfd095387a717b92ce64b5a))
+- **deps-dev:** bump the regular group with 2 updates ([#1183](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1183)) ([9de6af7](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/9de6af7490dc616d685c474b0d54c19c53fb15cd))
+- **deps-dev:** bump the regular group with 3 updates ([#1167](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1167)) ([fcca987](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fcca98745121549db537d9ce588e38900c8f0e0d))
+- **deps-dev:** bump vitest from 2.0.4 to 2.0.5 ([#1116](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1116)) ([e454b55](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e454b5538856316f8492463262186a24e02e2925))
+- **deps:** bump github/combine-prs from 5.1.0 to 5.2.0 ([#1188](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1188)) ([99cca19](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/99cca19cec0e67601f2973a1a4c985fe3dac6417))
+- **deps:** bump rambda from 9.2.1 to 9.3.0 in the regular group ([#1150](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1150)) ([c862413](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/c8624132fb742098c26e7a3a446ae7364ed5784a))
+- **deps:** bump sonarsource/sonarcloud-github-action ([d1b99e7](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/d1b99e7b824a6f0a20fc936b58ad8fa3eb7b2d7d))
+- **deps:** bump sonarsource/sonarcloud-github-action ([#1185](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1185)) ([9f7011d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/9f7011df003d985b0dc4032fb83d53c6dc669f7a))
+- **deps:** bump the regular group across 1 directory with 12 updates ([#1140](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1140)) ([89e8682](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/89e8682d8e1b3936bd17af7eca0142f9ad695b7f))
+- **deps:** bump the regular group across 1 directory with 4 updates ([58e990c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/58e990c7169a44eaa5ee14029119713ce92f5033))
+- **deps:** bump the regular group with 10 updates ([#1153](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1153)) ([48bd33f](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/48bd33f9432231b9551d65ceb5cd14b937e5cff1))
+- **deps:** bump the regular group with 2 updates ([#1129](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1129)) ([d9f951c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/d9f951c258d12765106548688672b8413716fb16))
+- **deps:** bump the regular group with 2 updates ([#1143](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1143)) ([f883a83](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f883a83f647b54a7b625e19972e94224f768c50b))
+- **deps:** bump the regular group with 2 updates ([#1155](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1155)) ([c02ea07](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/c02ea0790b61c5b29c353ff1297fa5e3fe5538da))
+- **deps:** bump the regular group with 2 updates ([#1165](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1165)) ([e1fb067](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e1fb067c6a2d00106c5bf7ec0707d5374fdca464))
+- **deps:** bump the regular group with 2 updates ([#1189](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1189)) ([d626254](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/d626254db881732a6478258428fd37da26c4cabb))
+- **deps:** bump the regular group with 3 updates ([#1151](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1151)) ([271426f](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/271426fb72220de7969c8200067f51793a5502a7))
+- **deps:** bump the regular group with 3 updates ([#1170](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1170)) ([fb89e15](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fb89e155dbfd8be508fa42a08fc44dad925bd7ad))
+- **deps:** bump the regular group with 4 updates ([#1157](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1157)) ([35fbcd3](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/35fbcd383c244ae746b45c031abac4b6cbadf001))
+- **deps:** bump the regular group with 4 updates ([#1166](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1166)) ([2f2d625](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/2f2d625b102d7211e5311c8367690bd03ce8087a))
+- **deps:** bump the regular group with 4 updates ([#1173](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1173)) ([b07a57e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b07a57e8de27faf8008b26e94f78978cc1b58ff4))
+- **deps:** bump the regular group with 5 updates ([#1128](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1128)) ([2786b45](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/2786b45addc24eaefc167970ef42f831573cc7b8))
+- **deps:** bump the regular group with 5 updates ([#1187](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1187)) ([7c2dbe5](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/7c2dbe52f8fb160bfd25090793e0b7f4d7df1317))
+- **deps:** bump the regular group with 5 updates ([#1191](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1191)) ([c9a4d44](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/c9a4d44f8a45e92a7b5dd755c0b811c85f5c2f6e))
+- **deps:** bump the regular group with 6 updates ([#1163](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1163)) ([e6ea62c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e6ea62c8b4c1ba8c99c8502a9df24709f46e19cf))
+- **deps:** bump the regular group with 7 updates ([f5d5fe0](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f5d5fe0e8449c8c1ecd560cdaea66757d4cb6168))
+- **deps:** bump the regular group with 7 updates ([#1130](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1130)) ([4f1d887](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/4f1d8877c57dd59ec6b862c5caee613532e0873a))
+- **deps:** bump the regular group with 7 updates ([#1158](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1158)) ([4809da4](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/4809da42ba62306e05652e685aba604bc66ec179))
+- **deps:** bump the regular group with 7 updates ([#1168](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1168)) ([2336b18](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/2336b18a25e03b086d23fd7c99753ac9201eee6e))
+- **deps:** bump the regular group with 7 updates ([#1182](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1182)) ([462fe86](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/462fe8611ff8b5938b6e9164f897210d475d3fb5))
+- **deps:** bump the regular group with 9 updates ([#1137](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1137)) ([eede99d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/eede99da5f4df39204a48daf6caf8463c1048be6))
+- **deps:** bump vue from 3.4.36 to 3.4.37 in the regular group ([#1132](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1132)) ([1e755e0](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1e755e07ca8925d906b4b83a9a430d4d4dc4b31d))
+- **deps:** bump vue from 3.5.1 to 3.5.2 in the regular group ([54e7c79](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/54e7c7947381865de499ddff816d007399942040))
+- **deps:** bump vue from 3.5.10 to 3.5.11 in the regular group ([#1184](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1184)) ([b216885](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b216885bc638297def6a91f530813a4ab078dc5c))
+- **deps:** bump winston from 3.14.0 to 3.14.1 in the regular group ([#1135](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1135)) ([99edec9](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/99edec9e2c356c875dc6c9a1f0aaca1840ab1af1))
+- **sea:** cleanup build artefacts ([2e65f18](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/2e65f185a91dcce233c38fcd1e2383c68c017f02))
+- **sonar:** refine sonar-project.properties files ([216a56a](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/216a56a2a3c4548eb9fdb3a67793e653b4f8bbf3))
+
+## [1.5.1](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator@v1.5.0...simulator@v1.5.1) (2024-07-30)
+
+### ✨ Polish
+
+- cleanup eslint configuration ([31dab31](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/31dab314ef8b2f785e8074218e1889792752049a))
+- move buidling, bundling, ... scripts into a directory ([bf30bb2](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/bf30bb229a6296e16bd4aab4cf7285f7dd187288))
+- silence two linter errors ([664ba1d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/664ba1dde7b64ea9f9a262a31dec9aa91c6a92f3))
+- **test:** code cleanups ([7edfbc1](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/7edfbc133ab8b7d617cbb1e4fbda4acd4c63800d))
+
+### 🧪 Tests
+
+- add checkConfiguration() helper test ([243a494](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/243a494b9598b7aa85f9b5cdca067cd5fd4f5b06))
+- add more charging station helpers tests ([e01619b](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e01619ba83f630b55890f18e1adbc561ef95fd50))
+- add some tests for charging station helpers ([df59920](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/df5992062c1e0975e1e159f7fa7b81bcc263bd27))
+
+### 📚 Documentation
+
+- add OCPP 2 mock server component to issue templates ([a95db78](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a95db7832890d86af2eb75ffe39f3baad686eb09))
+
+### 🤖 Automation
+
+- **ci:** reenabled auto code formating and linting on simulator ([1e4b13c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1e4b13ce2da1be9ee2437dd057d477309168b716))
+- **ci:** reenabled linting on web ui code ([5a1832c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/5a1832ce790d0398fa031e738db47eb94fa975ec))
+- **deps-dev:** bump @types/ws from 8.5.11 to 8.5.12 ([#1113](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1113)) ([1e10f26](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1e10f2640989a05281874950de452b76fc57d59a))
+- **deps-dev:** bump eslint-plugin-jsdoc from 48.8.3 to 48.9.2 ([#1112](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1112)) ([79e727f](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/79e727f19f927ee2532ff95337a363b8ee594bbb))
+- **deps-dev:** bump eslint-plugin-jsdoc from 48.9.2 to 48.10.1 ([#1115](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1115)) ([9cd5283](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/9cd5283ad66aeefacdcf3b7df7c8685e6df83d6b))
+- **deps-dev:** bump husky from 9.1.3 to 9.1.4 ([#1114](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1114)) ([c398be4](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/c398be430ad2d387e8982af00e54fc89e2b0db8e))
+
+## [1.5.0](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator@v1.4.2...simulator@v1.5.0) (2024-07-25)
+
+### 🚀 Features
+
+- add initial node sea support ([f6e18e3](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f6e18e33b68a67239eba3f4d873172a491283d00))
+
+### 🐞 Bug Fixes
+
+- ensure OCPP payload validation report error details ([45087a8](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/45087a81ca7dda0b6e72897acd1391d859026961))
+
+### ✨ Polish
+
+- npx -> pnpm dlx where appropriates ([bf25e53](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/bf25e531346a2e0579cb14d1d7c1da45dbb0aa08))
+- permit build code to run with other JS runtime ([456b7f2](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/456b7f2d7fc934d306e948e906c847417432009b))
+- refine OCPP PDU validation error messages ([5827ccc](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/5827ccc27d6c46f82df4e42a5707cfa19b550442))
+- refine station information validation error message ([915c88d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/915c88d593292e7a47c92868e4b2d3752cce4dcd))
+- validate station information at CS init ([b55f94b](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b55f94b6ac5dee58f38d13781b4345c4cc43f349))
+
+### 🧪 Tests
+
+- fix clone() test ([53ec800](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/53ec800a644f89a299cede7a89dd8a7b05959797))
+
+### 📚 Documentation
+
+- **README.md:** refine volta installation on windows ([fad9e72](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fad9e7271b22c74fe6eb67e939090cf529a2b249))
+
+### 🤖 Automation
+
+- **ci:** fix autofix GH action ([c033310](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/c03331039ff7a080a3456d5a88fb7b18d505df7f))
+- **deps-dev:** bump @types/node from 20.14.11 to 20.14.12 ([#1106](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1106)) ([fb46a87](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fb46a877f5c2b880759b9e70a08092510a7cb473))
+- **deps-dev:** bump @vitejs/plugin-vue from 5.0.5 to 5.1.0 ([#1105](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1105)) ([d36c4c8](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/d36c4c840ab5ac7a9c7fe6abbd2ae01844cb981e))
+- **deps-dev:** bump @vitest/coverage-v8 from 2.0.1 to 2.0.2 ([bbdb386](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/bbdb3861ed14ea52669231e5d372add76c50d65e))
+- **deps-dev:** bump eslint-plugin-jsdoc from 48.5.2 to 48.6.0 ([fd091c8](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fd091c8cd219780ff650859e7b4506180f436861))
+- **deps-dev:** bump glob from 10.4.3 to 11.0.0 ([cff23bd](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/cff23bd9ab0f9ca92bc2d4721bf454b00a54daf0))
+- **deps-dev:** bump husky from 9.0.11 to 9.1.0 ([#1091](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1091)) ([e74759d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e74759d1c5cc66ef325b75bae39cc930ae33eb92))
+- **deps-dev:** bump rimraf from 5.0.8 to 6.0.0 ([207408c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/207408cf661a7b8a1d35f8a9aa5ff02104fcd8ba))
+- **deps-dev:** bump typescript-eslint from 7.16.0 to 7.16.1 ([a60a99d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a60a99dce05328466e9a631ba83a9d527f3b4548))
+- **deps-dev:** bump vitest from 2.0.1 to 2.0.2 ([#1082](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1082)) ([f3d0d30](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f3d0d30346974ec0e979d53d8a761ce254ba8bb0))
+- **deps:** bump github/combine-prs from 5.0.0 to 5.1.0 ([#1093](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1093)) ([55f4d38](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/55f4d386ab0e3903101c8a4b296b962cf71c9427))
+- **deps:** bump tar from 7.4.0 to 7.4.1 ([#1102](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1102)) ([0da233c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/0da233c3b206d71bda0504908a1fd429547de923))
+- **deps:** bump vue from 3.4.33 to 3.4.34 ([#1107](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1107)) ([0bfef14](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/0bfef1423a926bd6054a25934957148d1d2fb4b0))
+
+## [1.4.2](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator@v1.4.1...simulator@v1.4.2) (2024-07-06)
+
+### 📚 Documentation
+
+- format 'Branching model' section in README.md ([3196db2](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/3196db2fbe206231fc0ee7d7947b19937a23ce42))
+
+### 🤖 Automation
+
+- **ci:** do not cancel workflow in case of autofix failure ([7e302de](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/7e302dea6f55838438fbe7bf0b9b8e70f3c3af21))
+- **ci:** fix release-please changelog after module renaming ([26058fd](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/26058fdb1d89d53caceceb1a981e3d48d73dcfae))
+- **ci:** rename module in changelog ([b7c140d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b7c140d7aad6d935d8941b07062011d4171596e9))
+- **deps:** bump poolifier from 4.0.15 to 4.0.16 ([8965c9e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/8965c9e361bd771e59963c7ebd22b4d3fc0da04b))
+
+## [1.4.1](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator@v1.4.0...simulator@v1.4.1) (2024-07-05)
+
+### 🐞 Fixes
+
+- **ci:** fix release branches creation ([f727f02](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f727f029cb974cffb38a2c569173730b6b808e3f))
+
+### ✨ Polish
+
+- **ci:** cleanup release-please configuration ([9880e6f](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/9880e6fed0333e17aad03f33e5ec4ee6307510ec))
+
+## [1.4.0](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/simulator-v1.3.7...simulator@v1.4.0) (2024-07-04)
+
+### 🚀 Features
+
+- switch to release-please release manager ([2c02376](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/2c02376b6b17a6094c451b976275ed9eb2e1407b))
+
+### 🐞 Fixes
+
+- **ci:** fix release-please GH action run ([2a91b70](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/2a91b70f1cf33c64ee6f2f3be63bb9b5614cd319))
+- **ci:** silence release-please GH action warnings ([4dc1046](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/4dc10464e640d30a12ece043edcd72390cd1fb43))
+- ensure checks are run on release PR ([ce4b669](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/ce4b6698ed11fbee77caf6f448fef2db36240bcc))
+
+### 📚 Documentation
+
+- add branching model to README.md ([d295031](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/d295031fa6c94271ec551f32bba55f9cd99c998e))
+- add PR template ([8d9bfb0](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/8d9bfb088bc280dac892ca71f40bb085842eb7e7))
+
+### ✨ Polish
+
+- **test:** code cleanups ([b53037c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b53037c097bf8412831281229234e814aaae82a9))
+- **test:** typing cleanups ([65a1581](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/65a1581afd90a44096f1c0157abf4d5531d76fa5))
+
+### 🤖 Automation
+
+- bump volta node version ([abc5de8](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/abc5de857ea9e4a27f83d1c2fe60b4618775a540))
+- **ci:** fix component handling in release-please ([60414a7](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/60414a7e313e6ce7b3a9effd8a8cccb41555a04c))
+- **ci:** limit initial release PR to previous version commit ([e49bac4](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e49bac45f5d513b19991fde86e7c234eb46ab85d))
+- **ci:** remove release-please workspace plugin ([94097a8](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/94097a8d456f51654a9b201e41309d9628638a81))
+- **deps-dev:** apply updates ([e92bd99](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e92bd991d1f0c43442dd20d7b5e34fd30f9bb136))
+- **deps-dev:** apply updates ([a33e3b4](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a33e3b4129757990b84af075cf9b678506937afb))
+- **deps:** bump ws from 8.17.1 to 8.18.0 ([4119c6e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/4119c6edbafb3fe813587770a2fb5a91c85a8340))
+
+## [v1.3.7](https://github.com/sap/e-mobility-charging-stations-simulator/compare/v1.3.6...v1.3.7)
+
+- fix: fix OCPP2 mock server command sending [`#1061`](https://github.com/sap/e-mobility-charging-stations-simulator/pull/1061)
+- Combined PRs [`#1064`](https://github.com/sap/e-mobility-charging-stations-simulator/pull/1064)
+- Fix GetBaseReport Implementation and Add Request Handlers and CLI Parsing Server-Side [`#1053`](https://github.com/sap/e-mobility-charging-stations-simulator/pull/1053)
+- build(deps-dev): bump eslint-plugin-jsdoc from 48.2.12 to 48.4.0 [`#1059`](https://github.com/sap/e-mobility-charging-stations-simulator/pull/1059)
+- build(deps): bump sonarsource/sonarcloud-github-action from 2.2.0 to 2.3.0 [`#1048`](https://github.com/sap/e-mobility-charging-stations-simulator/pull/1048)
+- build(deps): bump actions/setup-python from 4 to 5 [`#1043`](https://github.com/sap/e-mobility-charging-stations-simulator/pull/1043)
+- Add GetBaseReport Command Handling to OCPP 2.0.1 Server [`#1041`](https://github.com/sap/e-mobility-charging-stations-simulator/pull/1041)
+- build(deps-dev): apply updates [`11846be`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/11846be1d14c97fd648b9492f861e1ee6f84f2c5)
+- build(deps-dev): apply updates [`2177f6d`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/2177f6d759c2cacf2469d4c7b6de4f2caa7a08bc)
+- test: migrate ocpp server to poetry to ease usage [`c11be92`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/c11be92a38d40495df5ec37b9ff946993c4dc84f)
+- build(deps-dev): apply updates [`9d31316`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/9d31316ec2ba72f89f2709088ba8482137efa697)
+- build(deps-dev): apply updates [`e6f14eb`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/e6f14ebf2ecbe64a4f5d026632948c4a2f8b4d65)
+- build(deps): apply updates [`ede334c`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/ede334c888a1ffccb0ea420c1523e06120276df0)
+- refactor(ocpp-server): format code with black [`d4aa970`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/d4aa970003b5e5a012dceaa33d1905a170cb461b)
+- build(deps-dev): apply updates [`7f6b56b`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/7f6b56b555843a45f040f5b709b98725f38bed16)
+- build(deps): apply updates [`06b6085`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/06b60859cbfedab83c209fb2ecdbe0537daf7dfb)
+- test(ocpp-server): switch to ruff to assess coding style [`dfa4a58`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/dfa4a5842974c6de70aa04e84a303f1d10b4bb8b)
+- build(deps): apply updates [`5ebea52`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/5ebea52afe3ede727cb216e6708156738ced7e42)
+- build(deps-dev): apply updates [`6537ae8`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/6537ae8f2148496c326bbcd4fdf95dface14c8b8)
+- build(ci): silence linter [`4d8b5b9`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/4d8b5b9019b4853c97df80817dfb72e7f854b61a)
+- build(deps-dev): apply updates [`5ddbebe`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/5ddbebe972f979292d0e258d766702aa0fc1eb85)
+- fix(ocpp-server): add asyncio compatible timer implementation and use it [`cbfbfbc`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/cbfbfbc11f32acd3da4ae64aaa558b506d0de131)
+- build(deps-dev): apply updates [`69497ad`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/69497ade5b8f692ea0fa785a2fae2059798c9d9f)
+- build(deps-dev): apply updates [`d4c5e39`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/d4c5e39617edd8b9612d564ca693737381d356d9)
+- test: reformat ocpp server python using pep8 rules [`1a0d2c4`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/1a0d2c470d1b156381a9002155ffd6ff9a9f629d)
+- build(deps-dev): apply updates [`6c7388a`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/6c7388a4c4c47e9d19511b8e9b70b0f57d6dbd5f)
+- Add missing types for GetBaseReport payload handling [`fa16d38`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/fa16d389b8eb171e581c3fe5789602c54ac85ab1)
+- build(deps-dev): apply updates [`9388120`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/9388120364d5a2f3b9103f05802e1756d2dad04f)
+- build(deps-dev): apply updates [`12c0935`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/12c0935b3d52b06957d0c80ef4d5e361ea3aafa3)
+- test(ocpp-server): add tasks to format/lint code [`ac96356`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/ac96356cae880d404129e8cb56eeacdd712ea1d4)
+- fix: issue 39 [`299eb3f`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/299eb3fafb21481e38e963ff6080d0822ae6a3ae)
+- refactor: setup repo configuration to handle python code [`d6488e8`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/d6488e8da9634892f480dd4323a64d87716cbf13)
+- refactor: cleanup default params in error handlers [`64c14c9`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/64c14c99f9902d4e96f2a2cd404e536e0584a629)
+- build(deps-dev): apply updates [`a6a928b`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/a6a928b1e16fbc3537298c225829e29bf8eea12f)
+- feat: modified OCPP2.0 test [`7c945b4`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/7c945b4ac211aafb6e90645a0364c12d7373522e)
+- Related issue39 [`f937c17`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/f937c172eebbdfb2d90693806bc045e915bf828d)
+- build(deps-dev): apply updates [`7e7760d`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/7e7760d1bae2a948c88d008130714b2067fcc543)
+- build(deps-dev): apply updates [`a79c81a`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/a79c81afb8d0bc53368fcab7bb341f77ab9f84c0)
+- feat(ci): add autofix.ci action on PR [`a4beba2`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/a4beba2d2d81f4b122eceff72c2a495c27180011)
+- fix: modified mistakes [`b225460`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/b22546014db62ca65e14ecaec6ea62d2c986a4b6)
+- refactor(ocpp-server): add a few types [`c7f80bf`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/c7f80bf972e52fd1afa315ffdf02ff603f6b9e8b)
+- refactor: move more OCPP command sending code to charge point class [`4de4645`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/4de4645dcdfbd3512247c7272888def66f71d30d)
+- fix(ocpp-server): properly handle charge point disconnection [`7628b7e`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/7628b7e63d130ddc602ed3647abf36e8ae35f6dd)
+- build(deps-dev): bump ruff from 0.4.10 to 0.5.0 in /tests/ocpp-server [`2b8b04b`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/2b8b04bdc9838756c37fbe86a517a2b502c125ed)
+- build(ci): run autofix in a unique job [`8b17228`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/8b17228e91d57af035488d1939a07666e5d8649a)
+- [autofix.ci] apply automated fixes [`b794f42`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/b794f42e9d8f01fc21654ed4452df45a79f5f871)
+- build(deps-dev): apply updates [`0f1dc77`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/0f1dc770503395f8035b75fb0ae4ff394d1b5dfe)
+- refactor: move CLI options validation to main() [`93d9519`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/93d95199cbcad411feef0da6e9afff06c46c7e5b)
+- build(ocpp-server): apply updates [`8768034`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/87680344f2f32b45fa89d8ae3c46d3e28634e4bf)
+- chore: move configuration specific to ocpp-server to its folder [`b00abe8`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/b00abe8ebfc55f1029de151e21d2b66a08293a4e)
+- build(deps-dev): apply updates [`9daf701`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/9daf701f5321be7f7ab466026b43e4714d5c3f9d)
+- build(deps-dev): apply updates [`6d037fb`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/6d037fb64a050e2f7c368fabf7da9d0c56b7265e)
+- test: add ConfigurationData enums tests [`47a41cf`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/47a41cfff7de841a931f5694dbcddaf235e91bdd)
+- build(deps-dev): bump vite from 5.3.1 to 5.3.2 [`87170a8`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/87170a8e77a26d5f3156f4411cff1d0e2620992d)
+- docs: document volta usage for development [`17c9163`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/17c916369498726b5dff6145a6d50261f0cb90a0)
+- build(deps-dev): apply updates [`8df621e`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/8df621e643de566c4eae6608ed9cfcc8271bd3aa)
+- build(ci): add ocpp-server code linter check [`ffccbf2`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/ffccbf2287d74bfde06179427a1eabad986d1235)
+- [autofix.ci] apply automated fixes [`1f71f83`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/1f71f83fc5e112fd25fd9ce83af436fcba71ed68)
+- test: remove GetBaseReport ocpp server handler [`3bacab7`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/3bacab7a1e81110d4c416570e13658d2c07ce888)
+- chore(ocpp-server): refine ruff linter configuration [`a6fac14`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/a6fac14d419b2f278ce16d4505018d2ac8a179a1)
+- test(ocpp-server): add more request handlers [`5dd22b9`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/5dd22b9f9bed3b2cbef2ee24a5c7f4f1726a85d0)
+- build(deps): apply updates [`527e52c`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/527e52c5d10f3b8bf84fae1d05d254a053dc62cc)
+- build(deps-dev): apply updates [`936ba67`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/936ba6779d56dbb7ff50810f8ee5adf0a9845a89)
+- test(ocpp-server): keep track of connected CS [`a5c2d21`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/a5c2d21fa2d2bee31c329622e76cd8ac391ca37d)
+- build(deps-dev): apply updates [`b3e2979`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/b3e297931b16fbd02794e62bdea7077419e07097)
+- build: fix pnpm lock file [`757468b`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/757468bf17a0c5eb03ee9eb924ae5c34f8f4e5ca)
+- test(ocpp-server): add TransactionEvent handler [`22c4f1f`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/22c4f1fc7fe1dc966a280de7f66e2f9fe592fbd2)
+- chore(ocpp-server): refine ruff linter configuration [`ad8df5d`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/ad8df5d38dd7ef010f652a4e60f4af2c67e6d908)
+- [autofix.ci] apply automated fixes [`acf133c`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/acf133cd0efc14b1e45719a88dc57fac71bb1c90)
+- test: add clear cache implementation example in ocpp2 server [`a89844d`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/a89844d433370fc777a3a9d5ce29f7e8026b71a8)
+- test(ocpp-server): add RepeatTimer class to allow to emit OCPP messages on a regular [`aea4950`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/aea49501ed3c51f30a6d9c9a2f41ee4588cae313)
+- fix(ocpp-server): ensure the CLI options help is not truncated [`ba56e7c`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/ba56e7c9946964b7c28adb72cd54eeb805194f25)
+- refactor: silence linter [`52f298c`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/52f298cfa6812195ad89d58d15e3e469be52db57)
+- [autofix.ci] apply automated fixes [`b738a0f`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/b738a0fc1c620f3836d868235af16dfb61a91a50)
+- fix(ocpp-server): silence linter [`6c0215d`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/6c0215d2bf5a098aceed9e9d94d75d50ff2630db)
+- build(ci): cache python poetry deps [`52238c6`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/52238c635ec00feeb9b9300a0c99443a72e15925)
+- build(deps-dev): apply updates [`6a656e3`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/6a656e31e8c1c4204bb66fbc439b77232d230022)
+- build(deps-dev): apply updates [`842d677`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/842d677e39a455cee14efabb19110a3c4818a867)
+- build(ci): install pnpm deps only once [`56b900f`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/56b900ff755523df397b7da2a050471a48c91d57)
+- docs: refine README.md [`783b954`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/783b954595e60cfc5e90ddd749bc8578ec2512fe)
+- build(deps-dev): apply updates [`a387f9d`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/a387f9d902a1dc007108f2f632427cf008ea1bf2)
+- build: recommend vscode ruff extension for ocpp-server python code [`a951fc1`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/a951fc1b6194c0f65fd19ea62f119cd26283f2fd)
+- [autofix.ci] apply automated fixes [`f93800e`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/f93800e55130085e7ee3509a7952c5dd2315c146)
+- refactor(ci): cleanup GH actions [`657ddf9`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/657ddf9cc2c9fc8c81fd3da90803cd378987fd3a)
+- fix: fix ApplicationProtocolVersion type definition [`f2a9013`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/f2a90135692aac9beaeeb73efcb7e7aa093ec39a)
+- fix: issue 39 [`4e5c91a`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/4e5c91aef023b214716aeb6699edebd282cceeb9)
+- build(ocpp-server): sync poetry lock file [`cfb413a`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/cfb413a541334cbe3ea80fc111ccc44736442d58)
+- refactor(ci): cleanup GH actions [`fafff4e`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/fafff4ebf141074899e2a8590f5166542d626db5)
+- Update tests/ocpp-server/server.py [`b518537`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/b5185375d64bf123c5f12e165be4175f77dd8466)
+- Update tests/ocpp-server/server.py [`ba0a759`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/ba0a75922d7cba5f44b97eddc7b567f50ba920e2)
+- Update tests/ocpp-server/server.py [`0457819`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/04578196600a49d2f03710ded6ba0548cbbd87ad)
+- Update tests/ocpp-server/server.py [`39d32b7`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/39d32b7191ff76ffb277e6d116caa95e443d326c)
+- docs(ocpp-server): cleanup comment [`12925eb`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/12925ebc4afad719210d96b64571aa8bccad0fe5)
+- Merge dependabot/pip/tests/ocpp-server/ruff-0.5.0 into combined-prs-branch [`e17b6e8`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/e17b6e807babcf5ed7b53b03d4f3006960dfe671)
+- Merge dependabot/npm_and_yarn/vite-5.3.2 into combined-prs-branch [`85f0a4b`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/85f0a4b3b5c7f47c06be1be8cbf51f3fcb88acf3)
+- [autofix.ci] apply automated fixes [`e1702c3`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/e1702c3295a8b068eed8c7cf616a7996037e3651)
+- fix: corrected a error [`d4eddfa`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/d4eddfaee92738e8d33f7cca0acc724b152501d4)
+- refactor(ocpp-server): refine log message [`118332f`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/118332f42f7f6fb80b895794fc5f1179f78c294c)
+- Update tests/ocpp-server/server.py [`891ae31`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/891ae31da6a7a04ad29e46f3d2d2377f55c51932)
+- Update tests/ocpp-server/server.py [`7068f7f`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/7068f7f35112cf086e9b75ff1ee5f9fc2c1b0bb2)
+- Update tests/ocpp-server/server.py [`12798af`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/12798afb447fdc4a24998982e546a7b5334eea03)
+- fix: updated .gitignore to exclude temporary files [`57256ac`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/57256ac7ea82a86b8bf3a08a8f767e0abf4e07d4)
+- build(ci): fix task name for autofix [`e784545`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/e78454533d7ea81da471ea83e615215f8c578014)
+- fix(ci): fix autofix jobs [`3e79e7e`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/3e79e7ebfae0acef316913324cc9ba5e9b018949)
+- build(ci): checkout repo only once [`ecf7494`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/ecf7494a32490227fe31ca25df95fbe24b626f11)
+- modified conflict [`75afd2d`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/75afd2d96080afd378adc6baff4d33dc33fb4ef1)
+- build(deps): add dependabot configuration for ocpp-server [`20e5e16`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/20e5e16ec38052ef88fdcf0879b0877aa3f4b1d8)
+- test: add .gitignore for ocpp-server [`0395ac6`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/0395ac6663d6257d0c9f5f9c0468691721cf6748)
+- refactor(ocpp-server): code formatting [`8430af0`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/8430af0a8ef88806725ab72613f0d2385798e182)
+- test: fix OCPP 2 server startup [`339f65a`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/339f65ad177a26f0c75dab3da066638ffcd7c44d)
+- test(ocpp-server): add heartbeart command handler [`115f3b1`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/115f3b177307e3a152a556db843653a499a5fe4c)
+- refactor: refine OCPP 2 mock server defaults [`dd4588b`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/dd4588bbff2b31d206367724d0aa843ecc7ef7c6)
+- test(ocpp-server): add StatusNotification handler [`65c0600`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/65c0600c2ca47b47559d3d9e7bc5e56b272dc615)
+- chore: bump volta node version [`b89f8c8`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/b89f8c8293de89983b80f4296037b2ae2652fe91)
+- build(deps): bump sonarsource/sonarcloud-github-action [`45609cf`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/45609cfb6cc764eeb8aa0a74dc41ab2a8d1875ca)
+- docs(ocpp-server): refine README.md [`4c69efe`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/4c69efeacafda3a585d526b1476572746537f8c1)
+- refactor: cleanup dependabot configuration [`8f8f989`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/8f8f989efabf09ced480ebf661b54975dd7225b9)
+- chore: cleanup editorconfig config [`c2e5313`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/c2e53133a6d00f5b64e66a1359f7f244730b9d02)
+- test(ocpp-server): add task to run server [`3a89ffc`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/3a89ffcba5b6eb9e37619f67b56aadfea2ee2a09)
+- build(ci): silence warning at building OCPP mock server [`40f37d8`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/40f37d8ec1d1b46e61c2513d17a4fc30c4a45910)
+- refactor(ocpp-server): refine log message [`950b6c5`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/950b6c5a67672f45330979ff63860886dea62b67)
+- test: align OCPP2 server messages [`e1c2dac`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/e1c2dac9ba7b83ab392f9c1130810a9fb07a8eaf)
+
+## [v1.3.6](https://github.com/sap/e-mobility-charging-stations-simulator/compare/v1.3.5...v1.3.6) (2024-06-10)
+
+- build(deps-dev): apply updates [`01ffb6d`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/01ffb6d3583ab4da138dad815803121f3cc6d336)
+- feat: handle CHARGE_POINT_MAX_PROFILE charging profiles at power [`3579910`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/357991053f9d8910cdfaebde426eca58f813c05f)
+- build(deps-dev): apply updates [`7b0a334`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/7b0a334d2c0e42768b246cbc962718d605ca7464)
+- refactor: cleanup power limitation code [`21f68e2`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/21f68e222da0b9ac5d43a70b96beaf3f13ff3926)
+- refactor: cleanup charging profiles handling code [`c76d9c8`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/c76d9c83dba681eeccd78dcfae661b085d7ccf2b)
+- fix: ensure no charging profile purpose TxProfile is loaded at startup [`3edfdf5`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/3edfdf53dc3c75bf26b4737bb014e6e98239ef38)
+- chore: version 1.3.6 [`5d42650`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/5d42650b5661ded13bc4a7f5b938f2b914410b18)
+- build(deps-dev): apply updates [`1056f1b`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/1056f1b4cf5e305c45351093cb062d05468c83e8)
+- build: apply volta pnpm update [`c9a92ed`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/c9a92ed7a2ef6d5258f075620b7f4878ba12c454)
+- fix: fix TxProfile removal with transaction id defined at Tx stop [`d020e24`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/d020e249e5206699107d6e63d3d585a7e72e7830)
+
+## [v1.3.5](https://github.com/sap/e-mobility-charging-stations-simulator/compare/v1.3.4...v1.3.5) (2024-06-09)
+
+- test: add ErrorUtils test [`d05b53c`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/d05b53c7a03b8fad2e106caee68d5871cc6aac6e)
+- test: improve ErrorUtils coverage [`2d4928a`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/2d4928a7237a906158f2e9652e08f0392eeabdcd)
+- build(deps-dev): apply updates [`c4387ed`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/c4387ed4b3d2021034f452deeb35276fabe022e2)
+- feat: handle charging profile purpose TxProfile [`7abb61b`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/7abb61bb4a4e1de238c6bdb31b1a017bcf56d7b6)
+- build(deps-dev): apply updates [`65b608f`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/65b608f0259f6f59138406ea327d22ecd6a19361)
+- test: add tests [`b49550e`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/b49550e256d11c7a30fb19cd672e5e3611d01553)
+- test: improve coverage on existing tests [`ff40d2c`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/ff40d2cc466140d6f18bc15b742100dd4f060d0f)
+- chore: version 1.3.5 [`cc04ce3`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/cc04ce3549100de93505abdd6ff43fd3d968998d)
+- fix: restart metervalues interval if MeterValueSampleInterval is changed [`b8e3363`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/b8e3363a179fcf79d8bb66f47724b377d4d38a75)
+- refactor: rename Storage.handleDBError -> Storage.handleDBStorageError [`a03b18c`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/a03b18c4731bfd1173ff67b74a75684d3f6bb470)
+- fix: allow to set charging profile with TxProfile purpose [`65099c1`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/65099c1e7297b252523172096a8d6ded22daa702)
+- fix: avoid to modify stored charging profiles [`a629e6f`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/a629e6fcfeb952d77da280e69d645b17d94b2e4c)
+- test: add ConfigurationUtils test [`2a9305b`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/2a9305b5ace7b5a49b5862c4282c1a88e3087da5)
+- perf: compute power limitation only once [`5b1bd2d`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/5b1bd2d2c3c606aeef58cb1098def9a20c50dc4e)
+- fix: refine default configuration [`a9babd5`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/a9babd5006e9b70f281d4bd654923fc3d63cd733)
+- test: improve ConfigurationUtils coverage [`8598b56`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/8598b5618e5acf6b9e2538faa5225ba51aa68d10)
+- test: add Utils insertAt() test [`055d4c4`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/055d4c4c39c9c1fcce050019c61caf305ec1a83e)
+- test: trivial refinements [`0acbf5e`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/0acbf5e6ab020dda7ddc6785347c05c144de3bd9)
+- fix: ensure ATG status is refreshed in the UI at stop [`c004d5e`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/c004d5e2e7d277ab99b3ee1b8ce363736529db9e)
+- test: improve ConfigurationUtils coverage [`329f14c`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/329f14c004f74241c7cae1400e81740f3333eeee)
+- fix: add sanity check in ATG on connector id [`a4d9680`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/a4d9680730c77debfb3b9455e4bd5b63e61ce664)
+- perf: add fastpath in array sorting helper [`8bfa4d2`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/8bfa4d2be3f3817654791f166f4aab1b02485005)
+- fix: fix start transaction response handling with authorize [`ae8fb16`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/ae8fb16df7c98a9238e61b1b358f8fbe2aee7a74)
+- fix: fix condition at ATG configuration handling [`274f9b3`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/274f9b3662d8cf5e5fb0a361a1ae9fac86309e40)
+
+## [v1.3.4](https://github.com/sap/e-mobility-charging-stations-simulator/compare/v1.3.3...v1.3.4) (2024-06-06)
+
+- build(deps): bump sonarsource/sonarcloud-github-action from 2.1.1 to 2.2.0 [`#1038`](https://github.com/sap/e-mobility-charging-stations-simulator/pull/1038)
+- build(deps): bump pnpm/action-setup from 3 to 4 [`#1037`](https://github.com/sap/e-mobility-charging-stations-simulator/pull/1037)
+- fix: ensure message sequence is fired at boot notification response [`#1039`](https://github.com/sap/e-mobility-charging-stations-simulator/issues/1039)
+- refactor: code formatting [`48847bc`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/48847bc0d5e594c3e4c0b81c580ac6df48052668)
+- build(deps-dev): apply updates [`7445d18`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/7445d18b9b9ac750b9dc3dc3638d4fd0e8aff818)
+- build(deps-dev): apply updates [`268173c`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/268173c99a4ff81e1416909244ec58a6eb56dae6)
+- build(deps-dev): apply updates [`4f146c7`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/4f146c7c528d96cbe53ffeb9e578dc0c7e633af2)
+- build(deps): apply updates [`1dfc15d`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/1dfc15d22b7ac2363a32540d43540b7a93277a67)
+- build(deps-dev): apply updates [`c8d7098`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/c8d709814d13d9e4ea88a6c3a6701b37bfa858a4)
+- build(deps-dev): apply updates [`5218eec`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/5218eec27c72bade7112c6b029d7d1eb1f42f871)
+- build(deps-dev): apply updates [`18f25d9`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/18f25d958f1a57c34ed9d6e1de32ba9160c49dc2)
+- perf: use mnemonist CirculerBuffer [`840ca85`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/840ca85d7c40a6ee6f3a85a50e68dbea2f90acb8)
+- build(deps-dev): apply updates [`4bbeb8a`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/4bbeb8ad766752ba5da88513d9e77cba136ae85f)
+- build(deps-dev): apply updates [`4ed43d2`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/4ed43d280ab39b9beaadfa90875c71bf3b2a9507)
+- build(deps-dev): apply updates [`2f2e044`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/2f2e04446bb16844a71e8752ae29bff584267029)
+- build(deps): apply updates [`b1b7103`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/b1b7103d2089ea75bff0a15125422adf69683fc1)
+- build(deps): apply updates [`78ffd68`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/78ffd6863ea25544c4933303281c4bc7a81496f0)
+- build(deps-dev): apply updates [`a112428`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/a11242837ef77110c4d4b7a6ab0fa6f9a644a253)
+- build(deps): apply updates [`f26697b`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/f26697b4c9dcdf791e48e8f15160e90f6855c995)
+- build(deps-dev): apply updates [`cd01b1d`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/cd01b1d8f00898e27f78f4795650a78a179f0d14)
+- build(deps): apply updates [`576c4a4`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/576c4a496a355c5d995325406ec2cc37416f8a8e)
+- build(deps-dev): apply updates [`8788b81`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/8788b81a3dd4add12ca01b1fe989b5c7c8927d54)
+- build(deps): apply updates [`21d5c4c`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/21d5c4cdd0ccc30526f290a0be994990d5feac3f)
+- fix: fix performance statistics storage [`1c818bd`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/1c818bd3b021c8e660d64f9054e02d06424a3c59)
+- build(deps): apply updates [`24a0327`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/24a032720668044fc8439da3165715bab8474b26)
+- build(deps): apply updates [`47f846b`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/47f846b2a74439a610321356604f2f4184cb5c0b)
+- build(deps): apply updates [`cc99095`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/cc99095fab6d038ffff7ef3a2a8d33e762368670)
+- build(deps): apply updates [`73a88b8`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/73a88b832be6eedd83e7b277032c8d7ba7d06a97)
+- build(deps): apply updates [`0972694`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/0972694d006542648c971026f43e5f4c8498f459)
+- build(deps-dev): apply updates [`36158bb`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/36158bb7c539757a8b4a898dd6093d6805376921)
+- build(deps): apply updates [`1f851da`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/1f851da6440e4e4a31e959fcb8802b6c7f30beef)
+- chore: version 1.3.4 [`13a6494`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/13a6494f3542b9ed8773311302fa85258a1edec7)
+- refactor: cleanup OCPP utils [`01b82de`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/01b82de5b532cd149eccab7b82fe86a741289581)
+- build(deps-dev): apply updates [`55e006e`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/55e006e1af126c62f26f39cd4a1f91ebd44b865d)
+- fix: ensure only circular buffer is converted to array [`312d325`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/312d3254e6581f6bc939497d610048b6c6226d6d)
+- fix: fix date handling connectorsStatus configuration file section [`1fa9df8`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/1fa9df8ce0e186387ecaa80efb9f40180fc36a7d)
+- fix: start heartbeat once [`d627f8e`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/d627f8ef31d97da80f4de5ed0cb9386472f51bbe)
+- fix: ensure boot notification response is assigned before querying [`0320e2b`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/0320e2bb72ca522c3932850cce0601ab0a895ad3)
+- build(deps-dev): apply updates [`aa345d0`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/aa345d0154ff9700d8c9467c04c215ef5d07bbbf)
+- build: cleanup pnpm lock file [`fccc8f6`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/fccc8f66dfabe8e91f67311f3182e26aece20293)
+- refactor: cleanup boot notification response assignation [`ab29e68`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/ab29e6820d6a6d48d8ccc091ec8adae575398c3d)
+- build(deps): apply updates [`29fe6fd`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/29fe6fd834029f21b22a23a3342f86b43c277c56)
+- build(deps-dev): apply updates [`fc10596`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/fc105961dd56e041fc6de1df3fd51c74723ba419)
+- refactor: refine OCPP message sending error handling [`436569b`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/436569b1470c8e6187c63d974304bd1b99f35ba3)
+- fix: fix clear charging profiles with no connector in payload [`ec6dd88`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/ec6dd88b156eac9a14afd0d349ed58bb02fa920e)
+- fix: start web socket ping interval at successful connection [`99100f9`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/99100f9c8709a7ead56c1e2745db80a75e8f6f79)
+- build(deps-dev): apply updates [`3ebab70`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/3ebab7003594d1c243bcca4ef90007dc63680a52)
+- build(deps-dev): apply updates [`e4006e4`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/e4006e4283d9150be5bd2f1050ff78c979a203c1)
+- fix: ensure charging profiles not related to the current transaction are [`626d3ce`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/626d3ce5e6dfdc848cb2bb5833044fe6fbe68324)
+- fix: ensure inflight requests id cannot be duplicated [`3024d5b`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/3024d5b2497e97bdd355243a5d236fa3f7a4d874)
+- build(deps-dev): apply updates [`69d995b`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/69d995b2c8683703e7d9ce42fdd73ec02209482f)
+- fix: avoid endless loop at remote start transaction [`d0b7173`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/d0b71736d6fced71a50c67e1f1e7ca842068e43e)
+- build(deps-dev): apply updates [`a6f03d2`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/a6f03d2ddc8e28752b94cb0a43687d70c16683a6)
+- build(deps-dev): apply updates [`fa394dc`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/fa394dc9dd5f30d5121c2ce6ed11ba5d7c30bcd3)
+- fix: reset authorize fields connector status after reservation [`239194e`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/239194e9867eaea7d34fc3c8d3bff3360113d8dc)
+- build(deps-dev): apply updates [`df3e0f8`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/df3e0f8da05b9680213ccd3e3beee6686f296cd1)
+- refactor: cleanup Infinity usage [`cffc32b`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/cffc32b7bc5a6569525e92b562af8a93760bc339)
+- build(deps-dev): apply updates [`fa30db1`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/fa30db101a2d11774bd9b29ca806597865ea06bf)
+- build: fix pnpm lockfile [`5e1bf42`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/5e1bf4295e75408830ff46bb704a5139572a4120)
+- fix: properly handle undefined connector id at remote start transaction [`c0bbb3e`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/c0bbb3eaf0c5dc704ea92820a2666a68ffdc27ff)
+- fix: fix error handling default options definition [`30695dc`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/30695dcf67470f149e349d196b3d016482d11a17)
+- build(deps-dev): apply updates [`9e66896`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/9e668960f040bf5da86a6d6e7c477d4ad39dfd04)
+- build: bump volta node version [`494983d`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/494983d465621a426f5dc92fd7cccc62821616f9)
+- build(deps-dev): apply updates [`bb57ea0`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/bb57ea07805938bec42dbee3da6bfda569a1b9bb)
+- refactor: convert npx to pnpm exec [`e1486a4`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/e1486a4c8ce0142f2efc57c87fc8e8e05745a13f)
+- refactor: cleanup boot notification response handling [`52f1dd5`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/52f1dd569da1eac66de821796cdfbcef09b48c87)
+- refactor: cleanup connection retries logic [`aa5f2ea`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/aa5f2ea2958ef34e8d34e20edbe8486b8911d82b)
+- fix: pickup not reserved connector at remote start transaction [`8946ba9`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/8946ba9db13e225292a62b8f4bdcd1419792697a)
+- refactor: cleanup eslint usage [`c69ae13`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/c69ae13bb71df8f2017e21d919979b73dc6184f9)
+- fix: fix firmware update in progress detection [`382b62c`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/382b62c45d665e66d4a2f3ad5ac7ecc6396859c7)
+- fix: fix log files path resolution at GetDiagnostics [`e56bbec`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/e56bbec564af27559aade33d375dc890e882858e)
+- docs: refine code comments [`1d85f41`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/1d85f415a46d0d3355ee013e449ad99d3aee9418)
+- build(deps): bump sonarsource/sonarcloud-github-action [`e48376c`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/e48376cebb2f0e5d6c670b432e1b524e21702d3a)
+- build(ci): rely on packageManager field to setup pnpm [`7bba320`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/7bba3209fa975827c841aeab8fa20b4837ca64b1)
+- refactor: cleanup boot notification handling internal handling [`d9c13bc`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/d9c13bcac891b8686dbba36ae5c10f87948e3614)
+- fix: fix remote transaction start debug log [`7b08e7f`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/7b08e7f332d1146fa5990cf29e08e328343819f1)
+- fix: ensure registration status is deleted if invalid boot notification [`18c6df2`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/18c6df2b1102c307cbe8eb0c04d85c82045abf15)
+- refactor: cleanup string literal variables handling [`4c6f356`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/4c6f35659fb67d395adc035ef80c566eb6eef79e)
+- perf: resize circular array to sensible default [`9b5cf75`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/9b5cf75581e0338885b8e2ea408ea5a3f391d0ec)
+- fix(ci): silence linter [`4293e51`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/4293e5179eabbc8f42a1c06064d15c0ec7d1ca3f)
+- refactor: helper cleanup [`f69ca7c`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/f69ca7ca5f551a427e3181d38bc893cb68b2b542)
+
+## [v1.3.3](https://github.com/sap/e-mobility-charging-stations-simulator/compare/v1.3.2...v1.3.3) (2024-04-30)
- fix: avoid duplicated slash in connection url [`#1034`](https://github.com/sap/e-mobility-charging-stations-simulator/issues/1034)
- chore: switch to pnpm 9.x.x [`6eddb71`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/6eddb71902ac0d0552f705190aaf62525f07c476)
- build(deps-dev): apply updates [`a637f99`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/a637f99f1d9a63bed1338809a5dbfab26925babe)
- build(deps): apply updates [`de073a7`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/de073a748bcd60308615b81c3f6da817639461a1)
- build(deps-dev): apply updates [`5b7bbdb`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/5b7bbdba3612e2f5748a4c21b46ba7bee89ddaba)
+- chore: version 1.3.3 [`6deeebd`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/6deeebd11133a5c4b47452d9d9ab8cf5759e7c8a)
- build(deps-dev): apply updates [`98d6958`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/98d6958a6225cecc92e2f8b676c91be9fffd857b)
- refactor: silence typing errors [`314793a`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/314793aaf25bf1a99deb3f8209c09421235942ba)
- build: bump volta pnpm version [`8fb8f42`](https://github.com/sap/e-mobility-charging-stations-simulator/commit/8fb8f42ace8b9295865adebaeb7845e064c05e71)
--- /dev/null
+* @jerome-benoit @olivierbagot
- Contributions must be licensed under the [Apache 2.0 License](./LICENSE)
- Due to legal reasons, contributors will be asked to accept a Developer Certificate of Origin (DCO) when they create the first pull request to this project. This happens in an automated fashion during the submission process. SAP uses [the standard DCO text of the Linux Foundation](https://developercertificate.org/).
+## Contributing with AI-generated code
+
+As artificial intelligence evolves, AI-generated code is becoming valuable for many software projects, including open-source initiatives. While we recognize the potential benefits of incorporating AI-generated content into our open-source projects there a certain requirements that need to be reflected and adhered to when making contributions.
+
+Please see our [guideline for AI-generated code contributions to SAP Open Source Software Projects](https://github.com/SAP/.github/blob/main/CONTRIBUTING_USING_GENAI.md) for these requirements.
+
## Issues and Planning
- We use GitHub issues to track bugs and enhancement requests.
[](https://github.com/SAP/e-mobility-charging-stations-simulator/graphs/commit-activity)
[](https://github.com/SAP/e-mobility-charging-stations-simulator/actions/workflows/ci.yml)
[](https://api.reuse.software/info/github.com/SAP/e-mobility-charging-stations-simulator)
-[](https://standardjs.com)
+[](https://github.com/neostandard/neostandard)
</div>
- [Windows](#windows)
- [MacOSX](#macosx)
- [GNU/Linux](#gnulinux)
+ - [Development prerequisites (optional)](#development-prerequisites-optional)
+ - [Unix](#unix)
+ - [Windows](#windows-1)
+ - [Branching model](#branching-model)
- [Dependencies](#dependencies)
- [Initial configuration](#initial-configuration)
- [Start simulator](#start-simulator)
- [Start Web UI](#start-web-ui)
- [Configuration files syntax](#configuration-files-syntax)
- [Charging stations simulator configuration](#charging-stations-simulator-configuration)
- - [Charging station configuration template](#charging-station-configuration-template)
+ - [Charging station template configuration](#charging-station-template-configuration)
- [Charging station configuration](#charging-station-configuration)
- [Docker](#docker)
- [OCPP-J commands supported](#ocpp-j-commands-supported)
#### GNU/Linux
-- [NodeSource](https://github.com/nodesource/distributions) Node.js Binary Distributions for all supported versions.
+- [NodeSource](https://github.com/nodesource/distributions) node.js binary distributions for all supported versions.
-#### Dependencies
+### Development prerequisites (optional)
-Enable corepack if not already done and install latest pnpm version:
+Install [volta](https://volta.sh/) for managing automatically the node.js runtime and package manager version:
+
+#### Unix
+
+```shell
+curl https://get.volta.sh | bash
+```
+
+#### Windows
+
+```powershell
+choco install -y volta
+```
+
+Setup [volta](https://volta.sh/) with [pnpm](https://github.com/pnpm/pnpm) package manager support: https://docs.volta.sh/advanced/pnpm
+
+### Branching model
+
+The `main` branch is the default development branch.
+The `vX` branches are the maintenance branches for the corresponding major version `X`.
+The `vX.Y` branches are the maintenance branches for the corresponding major and minor version `X.Y`.
+
+### Dependencies
+
+Enable corepack, if [volta](https://volta.sh/) is not installed and configured, and install latest pnpm version:
```shell
corepack enable
- **dynamicPool** (experimental):
Dynamically sized worker pool executing a fixed total number of simulated charging stations
-### Charging station configuration template
+### Charging station template configuration
**src/assets/station-templates/\<name\>.json**:
Examples:
- **Start Transaction**
-
- Request:
`ProcedureName`: 'startTransaction'
`PDU`: {
}
- **Stop Transaction**
-
- Request:
`ProcedureName`: 'stopTransaction'
`PDU`: {
}
- **Status Notification**
-
- Request:
`ProcedureName`: 'statusNotification'
`PDU`: {
}
- **Heartbeat**
-
- Request:
`ProcedureName`: 'heartbeat'
`PDU`: {
--- /dev/null
+version = 1
+SPDX-PackageName = "e-mobility-charging-stations-simulator"
+SPDX-PackageSupplier = "Jerome Benoit <jerome.benoit@sap.com>"
+SPDX-PackageDownloadLocation = "<https://github.com/sap/e-mobility-charging-stations-simulator>"
+SPDX-PackageComment = "The code in this project may include calls to APIs (\"API Calls\") of\n SAP or third-party products or services developed outside of this project\n (\"External Products\").\n \"APIs\" means application programming interfaces, as well as their respective\n specifications and implementing code that allows software to communicate with\n other software.\n API Calls to External Products are not licensed under the open source license\n that governs this project. The use of such API Calls and related External\n Products are subject to applicable additional agreements with the relevant\n provider of the External Products. In no event shall the open source license\n that governs this project grant any rights in or to any External Products,or\n alter, expand or supersede any terms of the applicable additional agreements.\n If you have a valid license agreement with SAP for the use of a particular SAP\n External Product, then you may make use of any API Calls included in this\n project's code for that SAP External Product, subject to the terms of such\n license agreement. If you do not have a valid license agreement for the use of\n a particular SAP External Product, then you may only make use of any API Calls\n in this project for that SAP External Product for your internal, non-productive\n and non-commercial test and evaluation of such API Calls. Nothing herein grants\n you any rights to use or access any SAP External Product, or provide any third\n parties the right to use of access any SAP External Product, through API Calls."
+
+[[annotations]]
+path = "**"
+precedence = "aggregate"
+SPDX-FileCopyrightText = "2021-2024 SAP SE or an SAP affiliate company and e-mobility-charging-stations-simulator contributors"
+SPDX-License-Identifier = "Apache-2.0"
FROM node:lts-alpine AS builder
-# Build simulator and dashboard
+# Build simulator
WORKDIR /usr/builder
COPY . ./
RUN set -ex \
&& apk add --no-cache --virtual .gyp build-base python3 \
+ && npm install -g --ignore-scripts corepack \
&& corepack enable \
&& corepack prepare pnpm@latest --activate \
&& pnpm set progress=false \
&& cp docker/config.json src/assets/config.json \
&& cp docker/idtags.json src/assets/idtags.json \
&& pnpm build \
- && apk del .gyp \
- && cd ui/web \
- && cp src/assets/config-template.json public/config.json \
- && pnpm build
+ && apk del .gyp
FROM node:lts-alpine
ENV NODE_OPTIONS="--stack-trace-limit=${STACK_TRACE_LIMIT} --max-old-space-size=${MAX_OLD_SPACE_SIZE}"
WORKDIR /usr/app
-COPY --from=builder /usr/builder/ui/web ./ui/web
COPY --from=builder /usr/builder/node_modules ./node_modules
COPY --from=builder /usr/builder/dist ./dist
COPY package.json README.md LICENSE ./
-COPY docker/start.sh /start.sh
+COPY docker/run.sh /run.sh
COPY docker/autoconfig.sh /autoconfig.sh
RUN set -ex \
- && chmod +x /start.sh \
+ && chmod +x /run.sh \
&& chmod +x /autoconfig.sh
-CMD /autoconfig.sh && /start.sh
+ENTRYPOINT ["/bin/sh", "-c", "/autoconfig.sh && /run.sh"]
cp $emobility_install_dir/dist/assets/configs-docker/$emobility_server_type-$emobility_service_type-$emobility_landscape.json $emobility_install_dir/dist/assets/config.json
cp $emobility_install_dir/dist/assets/configs-docker/$emobility_server_type-$emobility_service_type-$emobility_landscape-idtags.json $emobility_install_dir/dist/assets/idtags.json
- cp $emobility_install_dir/dist/assets/configs-docker/$emobility_server_type-$emobility_service_type-$emobility_landscape-webui.json $emobility_install_dir/ui/web/public/config.json
else
echo "no emobility env defined, start with default configuration"
fi
},
"uiServer": {
"enabled": true,
+ "options": {
+ "host": "::"
+ },
"type": "ws",
"authentication": {
"enabled": true,
-version: '3.7'
networks:
ev_network:
driver: bridge
MAX_OLD_SPACE_SIZE: 768
networks:
- ev_network
- expose:
- - 8080
ports:
- - '3030:3030'
+ - 8080:8080
--- /dev/null
+#!/usr/bin/env sh
+
+node dist/start.js
+++ /dev/null
-#!/usr/bin/env sh
-
-node dist/start.js &
-node ui/web/start.js
{
"folders": [
{
- "path": "."
+ "path": ".",
},
{
- "path": "ui/web"
- }
+ "path": "ui/web",
+ },
+ {
+ "path": "tests/ocpp-server",
+ },
],
"settings": {
"nodejs-testing.extensions": [
{
"extensions": ["mjs", "cjs", "js"],
- "parameters": []
+ "parameters": [],
},
{
"extensions": ["mts", "cts", "ts"],
- "parameters": ["--import", "tsx"]
- }
- ]
- }
+ "parameters": ["--import", "tsx"],
+ },
+ ],
+ },
}
--- /dev/null
+/* eslint-disable n/no-unpublished-import */
+import cspellConfigs from '@cspell/eslint-plugin/configs'
+import js from '@eslint/js'
+import jsdoc from 'eslint-plugin-jsdoc'
+import perfectionist from 'eslint-plugin-perfectionist'
+import pluginVue from 'eslint-plugin-vue'
+import { defineConfig } from 'eslint/config'
+import neostandard, { plugins } from 'neostandard'
+
+export default defineConfig([
+ {
+ ignores: ['**/dist/**'],
+ },
+ cspellConfigs.recommended,
+ {
+ rules: {
+ '@cspell/spellchecker': [
+ 'warn',
+ {
+ autoFix: true,
+ cspell: {
+ words: [
+ 'DECI',
+ 'CENTI',
+ 'MILLI',
+ 'Benoit',
+ 'chargingstations',
+ 'ctrlr',
+ 'csms',
+ 'idtag',
+ 'idtags',
+ 'iccid',
+ 'imsi',
+ 'ocpp',
+ 'onconnection',
+ 'evse',
+ 'evses',
+ 'kvar',
+ 'kvarh',
+ 'varh',
+ 'rfid',
+ 'workerset',
+ 'logform',
+ 'mnemonist',
+ 'poolifier',
+ 'measurand',
+ 'measurands',
+ 'mikro',
+ 'neostandard',
+ 'recurrency',
+ 'shutdowning',
+ 'VCAP',
+ 'workerd',
+ ],
+ },
+ },
+ ],
+ },
+ },
+ js.configs.recommended,
+ plugins.promise.configs['flat/recommended'],
+ ...plugins.n.configs['flat/mixed-esm-and-cjs'],
+ jsdoc.configs['flat/recommended-typescript'],
+ {
+ rules: {
+ 'jsdoc/check-tag-names': [
+ 'warn',
+ {
+ definedTags: ['defaultValue', 'experimental', 'typeParam'],
+ typed: true,
+ },
+ ],
+ },
+ },
+ ...pluginVue.configs['flat/recommended'],
+ {
+ files: ['**/*.vue'],
+ languageOptions: {
+ globals: {
+ localStorage: 'readonly',
+ },
+ parserOptions: {
+ parser: '@typescript-eslint/parser',
+ },
+ },
+ },
+ ...plugins['typescript-eslint'].config(
+ {
+ extends: [
+ ...plugins['typescript-eslint'].configs.strictTypeChecked,
+ ...plugins['typescript-eslint'].configs.stylisticTypeChecked,
+ ],
+ files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts', '*/**.vue'],
+ languageOptions: {
+ parserOptions: {
+ projectService: true,
+ // eslint-disable-next-line n/no-unsupported-features/node-builtins
+ tsconfigRootDir: import.meta.dirname,
+ },
+ },
+ },
+ {
+ files: ['**/*.js', '**/*.mjs', '**/*.cjs'],
+ ...plugins['typescript-eslint'].configs.disableTypeChecked,
+ }
+ ),
+ perfectionist.configs['recommended-natural'],
+ {
+ files: ['**/*.vue'],
+ rules: {
+ 'perfectionist/sort-vue-attributes': 'off',
+ },
+ },
+ ...neostandard({
+ ts: true,
+ }),
+ {
+ files: [
+ 'src/charging-station/Bootstrap.ts',
+ 'src/charging-station/ChargingStation.ts',
+ 'src/charging-station/Helpers.ts',
+ 'src/charging-station/ocpp/OCPPServiceUtils.ts',
+ 'src/charging-station/ocpp/1.6/OCPP16ResponseService.ts',
+ 'src/performance/PerformanceStatistics.ts',
+ ],
+ rules: {
+ '@stylistic/operator-linebreak': 'off',
+ },
+ },
+ {
+ files: ['src/scripts/*.cjs'],
+ rules: {
+ '@typescript-eslint/no-require-imports': 'off',
+ },
+ },
+ {
+ files: ['tests/utils/Utils.test.ts'],
+ rules: {
+ '@typescript-eslint/no-unsafe-member-access': 'off',
+ },
+ },
+ {
+ files: ['ui/web/src/components/Container.vue', 'ui/web/src/components/buttons/Button.vue'],
+ rules: {
+ 'vue/multi-word-component-names': 'off',
+ },
+ },
+])
export default defineConfig({
dbName: `${Constants.DEFAULT_PERFORMANCE_DIRECTORY}/${Constants.DEFAULT_PERFORMANCE_RECORDS_DB_NAME}.db`,
+ debug: true,
entities: ['./dist/types/orm/entities/*.js'],
entitiesTs: ['./src/types/orm/entities/*.ts'],
- debug: true
})
{
"$schema": "https://json.schemastore.org/package",
"name": "e-mobility-charging-stations-simulator",
- "version": "1.3.3",
+ "version": "2.0.10",
"engines": {
- "node": ">=18.18.0",
+ "node": ">=20.11.0",
"pnpm": ">=9.0.0"
},
"volta": {
- "node": "22.2.0",
- "pnpm": "9.1.2"
+ "node": "22.17.0",
+ "pnpm": "10.12.4"
},
- "packageManager": "pnpm@9.1.2",
+ "packageManager": "pnpm@10.12.4",
"repository": {
"type": "git",
"url": "https://github.com/sap/e-mobility-charging-stations-simulator.git"
],
"type": "module",
"exports": "./dist/start.js",
- "auto-changelog": {
- "commitUrl": "https://github.com/sap/e-mobility-charging-stations-simulator/commit/{id}",
- "issueUrl": "https://github.com/sap/e-mobility-charging-stations-simulator/issues/{id}",
- "mergeUrl": "https://github.com/sap/e-mobility-charging-stations-simulator/pull/{id}",
- "compareUrl": "https://github.com/sap/e-mobility-charging-stations-simulator/compare/{from}...{to}"
- },
"mikro-orm": {
"tsConfigPath": "./tsconfig-mikro-orm.json",
"useTsNode": true
},
"scripts": {
- "prepare": "node prepare.js",
- "build-requirements": "node --no-warnings build-requirements.js",
+ "prepare": "node scripts/prepare.js",
+ "build-requirements": "node scripts/build-requirements.js",
"start": "pnpm build && cross-env NODE_ENV=production node dist/start.js",
"start:dev": "pnpm build:dev && cross-env NODE_ENV=development node --enable-source-maps dist/start.js",
"start:dev:debug": "pnpm build:dev && cross-env NODE_ENV=development node --enable-source-maps --inspect dist/start.js",
"start:flameprof": "cross-env NODE_ENV=production clinic flame -- node --enable-source-maps dist/start.js",
"start:bubbleprof": "cross-env NODE_ENV=production clinic bubbleprof -- node --enable-source-maps dist/start.js",
"start:heapprofiler": "cross-env NODE_ENV=production clinic heapprofiler -- node --enable-source-maps dist/start.js",
- "esbuild": "pnpm build-requirements && node bundle.js",
+ "esbuild": "pnpm build-requirements && node scripts/bundle.js",
"build": "pnpm esbuild",
"build:dev": "cross-env BUILD=development pnpm esbuild",
"build:cf": "pnpm clean:node_modules && pnpm exec cross-env SKIP_PREINSTALL=1 npm install && pnpm build",
"build:entities": "tsc -p tsconfig-mikro-orm.json",
"clean:dist": "pnpm exec rimraf dist",
"clean:node_modules": "pnpm exec rimraf node_modules",
- "lint": "cross-env TIMING=1 eslint --cache src tests .eslintrc.cjs bundle.js mikro-orm.config-template.ts",
- "lint:fix": "cross-env TIMING=1 eslint --cache --fix src tests .eslintrc.cjs bundle.js mikro-orm.config-template.ts",
- "format": "prettier --cache --write .; eslint --cache --fix src .eslintrc.cjs tests bundle.js mikro-orm.config-template.ts",
+ "lint": "cross-env TIMING=1 eslint --cache src tests scripts ./*.js ./*.ts",
+ "lint:fix": "cross-env TIMING=1 eslint --cache --fix src tests scripts ./*.js ./*.ts",
+ "format": "prettier --cache --write .; eslint --cache --fix src tests scripts ./*.js ./*.ts",
"test": "glob -c \"c8 node --import tsx --test\" \"tests/**/*.test.ts\"",
"test:debug": "glob -c \"node --import tsx --test --inspect\" \"tests/**/*.test.ts\"",
"coverage": "c8 report --reporter=lcov",
"coverage:html": "c8 report --reporter=html",
"clinic:clean": "clinic clean",
- "release": "release-it"
+ "sea": "pnpm exec rimraf ./dist/evse-simulator ./dist/evse-simulator.blob && node --experimental-sea-config sea-config.json && pnpm dlx ncp $(volta which node || n which lts || nvm which node || command -v node) ./dist/evse-simulator && pnpm dlx postject ./dist/evse-simulator NODE_SEA_BLOB ./dist/evse-simulator.blob --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 && pnpm exec rimraf ./dist/evse-simulator.blob"
},
"pnpm": {
"overrides": {
"d3-color": "^3.1.0",
"ejs": "^3.1.9",
"got": "^12.6.1",
+ "nanoid": "^3.3.8",
"semver": "^7.5.3",
- "uuid": "^9.0.0",
- "tough-cookie": "^4.1.3"
+ "tough-cookie": "^4.1.3",
+ "uuid": "^9.0.0"
}
},
"dependencies": {
- "@mikro-orm/core": "^6.2.7",
- "@mikro-orm/mariadb": "^6.2.7",
- "@mikro-orm/reflection": "^6.2.7",
- "@mikro-orm/sqlite": "^6.2.7",
- "ajv": "^8.13.0",
+ "@mikro-orm/core": "^6.4.16",
+ "@mikro-orm/mariadb": "^6.4.16",
+ "@mikro-orm/reflection": "^6.4.16",
+ "@mikro-orm/sqlite": "^6.4.16",
+ "ajv": "^8.17.1",
"ajv-formats": "^3.0.1",
"basic-ftp": "^5.0.5",
- "chalk": "^5.3.0",
- "date-fns": "^3.6.0",
+ "chalk": "^5.4.1",
+ "date-fns": "^4.1.0",
"http-status-codes": "^2.3.0",
- "logform": "^2.6.0",
- "mnemonist": "0.40.0-rc1",
- "mongodb": "^6.6.2",
- "poolifier": "^4.0.10",
- "rambda": "^9.2.0",
- "tar": "^7.1.0",
- "winston": "^3.13.0",
+ "logform": "^2.7.0",
+ "mnemonist": "0.40.3",
+ "mongodb": "^6.17.0",
+ "poolifier": "^5.0.2",
+ "tar": "^7.4.3",
+ "winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0",
- "ws": "^8.17.0"
+ "ws": "^8.18.3"
},
"optionalDependencies": {
- "bufferutil": "^4.0.8",
- "utf-8-validate": "^6.0.4"
+ "bufferutil": "^4.0.9",
+ "utf-8-validate": "^6.0.5"
},
"devDependencies": {
- "@commitlint/cli": "^19.3.0",
- "@commitlint/config-conventional": "^19.2.2",
- "@mikro-orm/cli": "^6.2.7",
- "@release-it/bumper": "^6.0.1",
- "@types/node": "^20.12.12",
- "@types/semver": "^7.5.8",
- "@types/ws": "^8.5.10",
- "@typescript-eslint/eslint-plugin": "^7.10.0",
- "@typescript-eslint/parser": "^7.10.0",
- "auto-changelog": "^2.4.0",
- "c8": "^9.1.0",
+ "@commitlint/cli": "^19.8.1",
+ "@commitlint/config-conventional": "^19.8.1",
+ "@cspell/eslint-plugin": "^9.1.2",
+ "@eslint/js": "^9.30.1",
+ "@mikro-orm/cli": "^6.4.16",
+ "@std/expect": "npm:@jsr/std__expect@^1.0.16",
+ "@types/node": "^24.0.10",
+ "@types/semver": "^7.7.0",
+ "@types/ws": "^8.18.1",
+ "c8": "^10.1.3",
"clinic": "^13.0.0",
"cross-env": "^7.0.3",
- "esbuild": "^0.21.3",
+ "esbuild": "^0.25.5",
"esbuild-plugin-clean": "^1.0.1",
"esbuild-plugin-copy": "^2.1.1",
- "eslint": "^8.57.0",
- "eslint-config-love": "^47.0.0",
- "eslint-config-standard": "^17.1.0",
- "eslint-define-config": "^2.1.0",
- "eslint-import-resolver-typescript": "^3.6.1",
- "eslint-plugin-import": "^2.29.1",
- "eslint-plugin-jsdoc": "^48.2.5",
- "eslint-plugin-n": "^17.7.0",
- "eslint-plugin-simple-import-sort": "^12.1.0",
- "eslint-plugin-tsdoc": "^0.2.17",
- "expect": "^29.7.0",
- "glob": "^10.3.15",
- "husky": "^9.0.11",
- "lint-staged": "^15.2.2",
- "prettier": "^3.2.5",
- "release-it": "^17.3.0",
- "rimraf": "^5.0.7",
- "semver": "^7.6.2",
+ "eslint": "^9.30.1",
+ "eslint-plugin-jsdoc": "^51.3.3",
+ "eslint-plugin-perfectionist": "^4.15.0",
+ "eslint-plugin-vue": "^10.3.0",
+ "glob": "^11.0.3",
+ "husky": "^9.1.7",
+ "lint-staged": "^16.1.2",
+ "neostandard": "^0.12.2",
+ "prettier": "^3.6.2",
+ "rimraf": "^6.0.1",
+ "semver": "^7.7.2",
"ts-node": "^10.9.2",
- "tsx": "^4.10.5",
- "typescript": "~5.4.5"
+ "tsx": "^4.20.3",
+ "typescript": "~5.8.3",
+ "vue-eslint-parser": "^10.2.0"
}
}
d3-color: ^3.1.0
ejs: ^3.1.9
got: ^12.6.1
+ nanoid: ^3.3.8
semver: ^7.5.3
uuid: ^9.0.0
tough-cookie: ^4.1.3
.:
dependencies:
'@mikro-orm/core':
- specifier: ^6.2.7
- version: 6.2.7
+ specifier: ^6.4.16
+ version: 6.4.16
'@mikro-orm/mariadb':
- specifier: ^6.2.7
- version: 6.2.7(@mikro-orm/core@6.2.7)
+ specifier: ^6.4.16
+ version: 6.4.16(@mikro-orm/core@6.4.16)
'@mikro-orm/reflection':
- specifier: ^6.2.7
- version: 6.2.7(@mikro-orm/core@6.2.7)
+ specifier: ^6.4.16
+ version: 6.4.16(@mikro-orm/core@6.4.16)
'@mikro-orm/sqlite':
- specifier: ^6.2.7
- version: 6.2.7(@mikro-orm/core@6.2.7)
+ specifier: ^6.4.16
+ version: 6.4.16(@mikro-orm/core@6.4.16)(mariadb@3.4.2)
ajv:
- specifier: ^8.13.0
- version: 8.13.0
+ specifier: ^8.17.1
+ version: 8.17.1
ajv-formats:
specifier: ^3.0.1
- version: 3.0.1(ajv@8.13.0)
+ version: 3.0.1(ajv@8.17.1)
basic-ftp:
specifier: ^5.0.5
version: 5.0.5
chalk:
- specifier: ^5.3.0
- version: 5.3.0
+ specifier: ^5.4.1
+ version: 5.4.1
date-fns:
- specifier: ^3.6.0
- version: 3.6.0
+ specifier: ^4.1.0
+ version: 4.1.0
http-status-codes:
specifier: ^2.3.0
version: 2.3.0
logform:
- specifier: ^2.6.0
- version: 2.6.0
+ specifier: ^2.7.0
+ version: 2.7.0
mnemonist:
- specifier: 0.40.0-rc1
- version: 0.40.0-rc1
+ specifier: 0.40.3
+ version: 0.40.3
mongodb:
- specifier: ^6.6.2
- version: 6.6.2(socks@2.8.3)
+ specifier: ^6.17.0
+ version: 6.17.0(socks@2.8.5)
poolifier:
- specifier: ^4.0.10
- version: 4.0.10
- rambda:
- specifier: ^9.2.0
- version: 9.2.0
+ specifier: ^5.0.2
+ version: 5.0.2
tar:
- specifier: ^7.1.0
- version: 7.1.0
+ specifier: ^7.4.3
+ version: 7.4.3
winston:
- specifier: ^3.13.0
- version: 3.13.0
+ specifier: ^3.17.0
+ version: 3.17.0
winston-daily-rotate-file:
specifier: ^5.0.0
- version: 5.0.0(winston@3.13.0)
+ version: 5.0.0(winston@3.17.0)
ws:
- specifier: ^8.17.0
- version: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)
- optionalDependencies:
- bufferutil:
- specifier: ^4.0.8
- version: 4.0.8
- utf-8-validate:
- specifier: ^6.0.4
- version: 6.0.4
+ specifier: ^8.18.3
+ version: 8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)
devDependencies:
'@commitlint/cli':
- specifier: ^19.3.0
- version: 19.3.0(@types/node@20.12.12)(typescript@5.4.5)
+ specifier: ^19.8.1
+ version: 19.8.1(@types/node@24.0.10)(typescript@5.8.3)
'@commitlint/config-conventional':
- specifier: ^19.2.2
- version: 19.2.2
+ specifier: ^19.8.1
+ version: 19.8.1
+ '@cspell/eslint-plugin':
+ specifier: ^9.1.2
+ version: 9.1.2(eslint@9.30.1(jiti@2.4.2))
+ '@eslint/js':
+ specifier: ^9.30.1
+ version: 9.30.1
'@mikro-orm/cli':
- specifier: ^6.2.7
- version: 6.2.7
- '@release-it/bumper':
- specifier: ^6.0.1
- version: 6.0.1(release-it@17.3.0(typescript@5.4.5))
+ specifier: ^6.4.16
+ version: 6.4.16(mariadb@3.4.2)
+ '@std/expect':
+ specifier: npm:@jsr/std__expect@^1.0.16
+ version: '@jsr/std__expect@1.0.16'
'@types/node':
- specifier: ^20.12.12
- version: 20.12.12
+ specifier: ^24.0.10
+ version: 24.0.10
'@types/semver':
- specifier: ^7.5.8
- version: 7.5.8
+ specifier: ^7.7.0
+ version: 7.7.0
'@types/ws':
- specifier: ^8.5.10
- version: 8.5.10
- '@typescript-eslint/eslint-plugin':
- specifier: ^7.10.0
- version: 7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)
- '@typescript-eslint/parser':
- specifier: ^7.10.0
- version: 7.10.0(eslint@8.57.0)(typescript@5.4.5)
- auto-changelog:
- specifier: ^2.4.0
- version: 2.4.0(encoding@0.1.13)
+ specifier: ^8.18.1
+ version: 8.18.1
c8:
- specifier: ^9.1.0
- version: 9.1.0
+ specifier: ^10.1.3
+ version: 10.1.3
clinic:
specifier: ^13.0.0
version: 13.0.0(encoding@0.1.13)
specifier: ^7.0.3
version: 7.0.3
esbuild:
- specifier: ^0.21.3
- version: 0.21.3
+ specifier: ^0.25.5
+ version: 0.25.5
esbuild-plugin-clean:
specifier: ^1.0.1
- version: 1.0.1(esbuild@0.21.3)
+ version: 1.0.1(esbuild@0.25.5)
esbuild-plugin-copy:
specifier: ^2.1.1
- version: 2.1.1(esbuild@0.21.3)
+ version: 2.1.1(esbuild@0.25.5)
eslint:
- specifier: ^8.57.0
- version: 8.57.0
- eslint-config-love:
- specifier: ^47.0.0
- version: 47.0.0(@typescript-eslint/eslint-plugin@7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint-plugin-n@17.7.0(eslint@8.57.0))(eslint-plugin-promise@6.1.1(eslint@8.57.0))(eslint@8.57.0)(typescript@5.4.5)
- eslint-config-standard:
- specifier: ^17.1.0
- version: 17.1.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint-plugin-n@17.7.0(eslint@8.57.0))(eslint-plugin-promise@6.1.1(eslint@8.57.0))(eslint@8.57.0)
- eslint-define-config:
- specifier: ^2.1.0
- version: 2.1.0
- eslint-import-resolver-typescript:
- specifier: ^3.6.1
- version: 3.6.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0)
- eslint-plugin-import:
- specifier: ^2.29.1
- version: 2.29.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
+ specifier: ^9.30.1
+ version: 9.30.1(jiti@2.4.2)
eslint-plugin-jsdoc:
- specifier: ^48.2.5
- version: 48.2.5(eslint@8.57.0)
- eslint-plugin-n:
- specifier: ^17.7.0
- version: 17.7.0(eslint@8.57.0)
- eslint-plugin-simple-import-sort:
- specifier: ^12.1.0
- version: 12.1.0(eslint@8.57.0)
- eslint-plugin-tsdoc:
- specifier: ^0.2.17
- version: 0.2.17
- expect:
- specifier: ^29.7.0
- version: 29.7.0
+ specifier: ^51.3.3
+ version: 51.3.3(eslint@9.30.1(jiti@2.4.2))
+ eslint-plugin-perfectionist:
+ specifier: ^4.15.0
+ version: 4.15.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
+ eslint-plugin-vue:
+ specifier: ^10.3.0
+ version: 10.3.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.1(jiti@2.4.2))(vue-eslint-parser@10.2.0(eslint@9.30.1(jiti@2.4.2)))
glob:
- specifier: ^10.3.15
- version: 10.3.15
+ specifier: ^11.0.3
+ version: 11.0.3
husky:
- specifier: ^9.0.11
- version: 9.0.11
+ specifier: ^9.1.7
+ version: 9.1.7
lint-staged:
- specifier: ^15.2.2
- version: 15.2.2
+ specifier: ^16.1.2
+ version: 16.1.2
+ neostandard:
+ specifier: ^0.12.2
+ version: 0.12.2(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
prettier:
- specifier: ^3.2.5
- version: 3.2.5
- release-it:
- specifier: ^17.3.0
- version: 17.3.0(typescript@5.4.5)
+ specifier: ^3.6.2
+ version: 3.6.2
rimraf:
- specifier: ^5.0.7
- version: 5.0.7
+ specifier: ^6.0.1
+ version: 6.0.1
semver:
specifier: ^7.5.3
- version: 7.6.2
+ version: 7.7.2
ts-node:
specifier: ^10.9.2
- version: 10.9.2(@types/node@20.12.12)(typescript@5.4.5)
+ version: 10.9.2(@types/node@24.0.10)(typescript@5.8.3)
tsx:
- specifier: ^4.10.5
- version: 4.10.5
+ specifier: ^4.20.3
+ version: 4.20.3
typescript:
- specifier: ~5.4.5
- version: 5.4.5
+ specifier: ~5.8.3
+ version: 5.8.3
+ vue-eslint-parser:
+ specifier: ^10.2.0
+ version: 10.2.0(eslint@9.30.1(jiti@2.4.2))
+ optionalDependencies:
+ bufferutil:
+ specifier: ^4.0.9
+ version: 4.0.9
+ utf-8-validate:
+ specifier: ^6.0.5
+ version: 6.0.5
ui/web:
dependencies:
finalhandler:
- specifier: ^1.2.0
- version: 1.2.0
+ specifier: ^2.1.0
+ version: 2.1.0
serve-static:
- specifier: ^1.15.0
- version: 1.15.0
+ specifier: ^2.2.0
+ version: 2.2.0
vue:
- specifier: ^3.4.27
- version: 3.4.27(typescript@5.4.5)
+ specifier: ^3.5.17
+ version: 3.5.17(typescript@5.8.3)
vue-router:
- specifier: ^4.3.2
- version: 4.3.2(vue@3.4.27(typescript@5.4.5))
+ specifier: ^4.5.1
+ version: 4.5.1(vue@3.5.17(typescript@5.8.3))
vue-toast-notification:
- specifier: ^3.1.2
- version: 3.1.2(vue@3.4.27(typescript@5.4.5))
+ specifier: ^3.1.3
+ version: 3.1.3(vue@3.5.17(typescript@5.8.3))
devDependencies:
- '@rushstack/eslint-patch':
- specifier: ^1.10.3
- version: 1.10.3
- '@tsconfig/node20':
- specifier: ^20.1.4
- version: 20.1.4
+ '@tsconfig/node22':
+ specifier: ^22.0.2
+ version: 22.0.2
'@types/jsdom':
- specifier: ^21.1.6
- version: 21.1.6
+ specifier: ^21.1.7
+ version: 21.1.7
'@types/node':
- specifier: ^20.12.12
- version: 20.12.12
- '@typescript-eslint/eslint-plugin':
- specifier: ^7.10.0
- version: 7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)
- '@typescript-eslint/parser':
- specifier: ^7.10.0
- version: 7.10.0(eslint@8.57.0)(typescript@5.4.5)
+ specifier: ^24.0.10
+ version: 24.0.10
'@vitejs/plugin-vue':
- specifier: ^5.0.4
- version: 5.0.4(vite@5.2.11(@types/node@20.12.12))(vue@3.4.27(typescript@5.4.5))
+ specifier: ^6.0.0
+ version: 6.0.0(vite@7.0.2(@types/node@24.0.10)(jiti@2.4.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))
'@vitejs/plugin-vue-jsx':
- specifier: ^3.1.0
- version: 3.1.0(vite@5.2.11(@types/node@20.12.12))(vue@3.4.27(typescript@5.4.5))
+ specifier: ^5.0.1
+ version: 5.0.1(vite@7.0.2(@types/node@24.0.10)(jiti@2.4.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))
'@vitest/coverage-v8':
- specifier: ^1.6.0
- version: 1.6.0(vitest@1.6.0(@types/node@20.12.12)(jsdom@24.0.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))
- '@vue/eslint-config-prettier':
- specifier: ^9.0.0
- version: 9.0.0(@types/eslint@8.56.10)(eslint@8.57.0)(prettier@3.2.5)
- '@vue/eslint-config-typescript':
- specifier: ^13.0.0
- version: 13.0.0(eslint-plugin-vue@9.26.0(eslint@8.57.0))(eslint@8.57.0)(typescript@5.4.5)
+ specifier: ^3.2.4
+ version: 3.2.4(vitest@3.2.4(@types/node@24.0.10)(jiti@2.4.2)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(tsx@4.20.3)(yaml@2.8.0))
'@vue/test-utils':
specifier: ^2.4.6
version: 2.4.6
'@vue/tsconfig':
- specifier: ^0.5.1
- version: 0.5.1
+ specifier: ^0.7.0
+ version: 0.7.0(typescript@5.8.3)(vue@3.5.17(typescript@5.8.3))
cross-env:
specifier: ^7.0.3
version: 7.0.3
- eslint:
- specifier: ^8.57.0
- version: 8.57.0
- eslint-define-config:
- specifier: ^2.1.0
- version: 2.1.0
- eslint-import-resolver-typescript:
- specifier: ^3.6.1
- version: 3.6.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0)
- eslint-plugin-import:
- specifier: ^2.29.1
- version: 2.29.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
- eslint-plugin-simple-import-sort:
- specifier: ^12.1.0
- version: 12.1.0(eslint@8.57.0)
- eslint-plugin-vue:
- specifier: ^9.26.0
- version: 9.26.0(eslint@8.57.0)
jsdom:
- specifier: ^24.0.0
- version: 24.0.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+ specifier: ^26.1.0
+ version: 26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)
prettier:
- specifier: ^3.2.5
- version: 3.2.5
+ specifier: ^3.6.2
+ version: 3.6.2
rimraf:
- specifier: ^5.0.7
- version: 5.0.7
+ specifier: ^6.0.1
+ version: 6.0.1
typescript:
- specifier: ~5.4.5
- version: 5.4.5
+ specifier: ~5.8.3
+ version: 5.8.3
vite:
- specifier: ^5.2.11
- version: 5.2.11(@types/node@20.12.12)
+ specifier: ^7.0.2
+ version: 7.0.2(@types/node@24.0.10)(jiti@2.4.2)(tsx@4.20.3)(yaml@2.8.0)
vitest:
- specifier: ^1.6.0
- version: 1.6.0(@types/node@20.12.12)(jsdom@24.0.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+ specifier: ^3.2.4
+ version: 3.2.4(@types/node@24.0.10)(jiti@2.4.2)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(tsx@4.20.3)(yaml@2.8.0)
packages:
- 0x@5.7.0:
- resolution: {integrity: sha512-oc5lqaJP7lu3C5zx+MRbsigfRlTTUg0LKjFDCr0NmR9g+nkZcR7yRU6jzMOiedSVKZ0p0b4y2TBQ+YYo6O3sZg==}
+ 0x@5.8.0:
+ resolution: {integrity: sha512-d07ToyEoxGz/u8JbaqeivEr3b2X6sPil6IDBINrXKBkgveiTW30EfjwDtHmE0TvP5Y4p5vE7ErbK3p68kYE0aw==}
engines: {node: '>=8.5.0'}
hasBin: true
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
engines: {node: '>=6.0.0'}
+ '@asamuzakjp/css-color@3.2.0':
+ resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==}
+
'@assemblyscript/loader@0.19.23':
resolution: {integrity: sha512-ulkCYfFbYj01ie1MDOyxv2F6SpRN1TOj7fQxbP07D6HmeR+gr2JLSmINKjga2emB+b1L2KGrFKBTc+e00p54nw==}
- '@babel/code-frame@7.24.2':
- resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==}
+ '@babel/code-frame@7.27.1':
+ resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
engines: {node: '>=6.9.0'}
- '@babel/compat-data@7.24.4':
- resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==}
+ '@babel/compat-data@7.28.0':
+ resolution: {integrity: sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==}
engines: {node: '>=6.9.0'}
- '@babel/core@7.24.5':
- resolution: {integrity: sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==}
+ '@babel/core@7.28.0':
+ resolution: {integrity: sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==}
engines: {node: '>=6.9.0'}
- '@babel/generator@7.24.5':
- resolution: {integrity: sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==}
+ '@babel/generator@7.28.0':
+ resolution: {integrity: sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==}
engines: {node: '>=6.9.0'}
- '@babel/helper-annotate-as-pure@7.22.5':
- resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==}
+ '@babel/helper-annotate-as-pure@7.27.3':
+ resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==}
engines: {node: '>=6.9.0'}
- '@babel/helper-compilation-targets@7.23.6':
- resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==}
+ '@babel/helper-compilation-targets@7.27.2':
+ resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==}
engines: {node: '>=6.9.0'}
- '@babel/helper-create-class-features-plugin@7.24.5':
- resolution: {integrity: sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==}
+ '@babel/helper-create-class-features-plugin@7.27.1':
+ resolution: {integrity: sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
- '@babel/helper-environment-visitor@7.22.20':
- resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-function-name@7.23.0':
- resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==}
+ '@babel/helper-globals@7.28.0':
+ resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
engines: {node: '>=6.9.0'}
- '@babel/helper-hoist-variables@7.22.5':
- resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
+ '@babel/helper-member-expression-to-functions@7.27.1':
+ resolution: {integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==}
engines: {node: '>=6.9.0'}
- '@babel/helper-member-expression-to-functions@7.24.5':
- resolution: {integrity: sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==}
+ '@babel/helper-module-imports@7.27.1':
+ resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==}
engines: {node: '>=6.9.0'}
- '@babel/helper-module-imports@7.22.15':
- resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-module-imports@7.24.3':
- resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-module-transforms@7.24.5':
- resolution: {integrity: sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==}
+ '@babel/helper-module-transforms@7.27.3':
+ resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
- '@babel/helper-optimise-call-expression@7.22.5':
- resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==}
+ '@babel/helper-optimise-call-expression@7.27.1':
+ resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==}
engines: {node: '>=6.9.0'}
- '@babel/helper-plugin-utils@7.24.5':
- resolution: {integrity: sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==}
+ '@babel/helper-plugin-utils@7.27.1':
+ resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==}
engines: {node: '>=6.9.0'}
- '@babel/helper-replace-supers@7.24.1':
- resolution: {integrity: sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==}
+ '@babel/helper-replace-supers@7.27.1':
+ resolution: {integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
- '@babel/helper-simple-access@7.24.5':
- resolution: {integrity: sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-skip-transparent-expression-wrappers@7.22.5':
- resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-split-export-declaration@7.24.5':
- resolution: {integrity: sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==}
- engines: {node: '>=6.9.0'}
-
- '@babel/helper-string-parser@7.24.1':
- resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==}
+ '@babel/helper-skip-transparent-expression-wrappers@7.27.1':
+ resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==}
engines: {node: '>=6.9.0'}
- '@babel/helper-validator-identifier@7.24.5':
- resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==}
+ '@babel/helper-string-parser@7.27.1':
+ resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
engines: {node: '>=6.9.0'}
- '@babel/helper-validator-option@7.23.5':
- resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==}
+ '@babel/helper-validator-identifier@7.27.1':
+ resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==}
engines: {node: '>=6.9.0'}
- '@babel/helpers@7.24.5':
- resolution: {integrity: sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==}
+ '@babel/helper-validator-option@7.27.1':
+ resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
engines: {node: '>=6.9.0'}
- '@babel/highlight@7.24.5':
- resolution: {integrity: sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==}
+ '@babel/helpers@7.27.6':
+ resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==}
engines: {node: '>=6.9.0'}
- '@babel/parser@7.24.5':
- resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==}
+ '@babel/parser@7.28.0':
+ resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==}
engines: {node: '>=6.0.0'}
hasBin: true
- '@babel/plugin-syntax-jsx@7.24.1':
- resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==}
+ '@babel/plugin-syntax-jsx@7.27.1':
+ resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
- '@babel/plugin-syntax-typescript@7.24.1':
- resolution: {integrity: sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==}
+ '@babel/plugin-syntax-typescript@7.27.1':
+ resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
- '@babel/plugin-transform-typescript@7.24.5':
- resolution: {integrity: sha512-E0VWu/hk83BIFUWnsKZ4D81KXjN5L3MobvevOHErASk9IPwKHOkTgvqzvNo1yP/ePJWqqK2SpUR5z+KQbl6NVw==}
+ '@babel/plugin-transform-typescript@7.28.0':
+ resolution: {integrity: sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
- '@babel/template@7.24.0':
- resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==}
+ '@babel/template@7.27.2':
+ resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
engines: {node: '>=6.9.0'}
- '@babel/traverse@7.24.5':
- resolution: {integrity: sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==}
+ '@babel/traverse@7.28.0':
+ resolution: {integrity: sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==}
engines: {node: '>=6.9.0'}
- '@babel/types@7.24.5':
- resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==}
+ '@babel/types@7.28.0':
+ resolution: {integrity: sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==}
engines: {node: '>=6.9.0'}
- '@bcoe/v8-coverage@0.2.3':
- resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
+ '@bcoe/v8-coverage@1.0.2':
+ resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==}
+ engines: {node: '>=18'}
'@clinic/bubbleprof@10.0.0':
resolution: {integrity: sha512-7Y0uYO4cz7+Y1advV891uMJLXbZMIriLsV1IHSSVJxmf8tEFm8vogKi/GdYyi4CY0D5heuqOFze/WNrv+U3LRw==}
resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==}
engines: {node: '>=0.1.90'}
- '@commitlint/cli@19.3.0':
- resolution: {integrity: sha512-LgYWOwuDR7BSTQ9OLZ12m7F/qhNY+NpAyPBgo4YNMkACE7lGuUnuQq1yi9hz1KA4+3VqpOYl8H1rY/LYK43v7g==}
+ '@commitlint/cli@19.8.1':
+ resolution: {integrity: sha512-LXUdNIkspyxrlV6VDHWBmCZRtkEVRpBKxi2Gtw3J54cGWhLCTouVD/Q6ZSaSvd2YaDObWK8mDjrz3TIKtaQMAA==}
engines: {node: '>=v18'}
hasBin: true
- '@commitlint/config-conventional@19.2.2':
- resolution: {integrity: sha512-mLXjsxUVLYEGgzbxbxicGPggDuyWNkf25Ht23owXIH+zV2pv1eJuzLK3t1gDY5Gp6pxdE60jZnWUY5cvgL3ufw==}
+ '@commitlint/config-conventional@19.8.1':
+ resolution: {integrity: sha512-/AZHJL6F6B/G959CsMAzrPKKZjeEiAVifRyEwXxcT6qtqbPwGw+iQxmNS+Bu+i09OCtdNRW6pNpBvgPrtMr9EQ==}
engines: {node: '>=v18'}
- '@commitlint/config-validator@19.0.3':
- resolution: {integrity: sha512-2D3r4PKjoo59zBc2auodrSCaUnCSALCx54yveOFwwP/i2kfEAQrygwOleFWswLqK0UL/F9r07MFi5ev2ohyM4Q==}
+ '@commitlint/config-validator@19.8.1':
+ resolution: {integrity: sha512-0jvJ4u+eqGPBIzzSdqKNX1rvdbSU1lPNYlfQQRIFnBgLy26BtC0cFnr7c/AyuzExMxWsMOte6MkTi9I3SQ3iGQ==}
engines: {node: '>=v18'}
- '@commitlint/ensure@19.0.3':
- resolution: {integrity: sha512-SZEpa/VvBLoT+EFZVb91YWbmaZ/9rPH3ESrINOl0HD2kMYsjvl0tF7nMHh0EpTcv4+gTtZBAe1y/SS6/OhfZzQ==}
+ '@commitlint/ensure@19.8.1':
+ resolution: {integrity: sha512-mXDnlJdvDzSObafjYrOSvZBwkD01cqB4gbnnFuVyNpGUM5ijwU/r/6uqUmBXAAOKRfyEjpkGVZxaDsCVnHAgyw==}
engines: {node: '>=v18'}
- '@commitlint/execute-rule@19.0.0':
- resolution: {integrity: sha512-mtsdpY1qyWgAO/iOK0L6gSGeR7GFcdW7tIjcNFxcWkfLDF5qVbPHKuGATFqRMsxcO8OUKNj0+3WOHB7EHm4Jdw==}
+ '@commitlint/execute-rule@19.8.1':
+ resolution: {integrity: sha512-YfJyIqIKWI64Mgvn/sE7FXvVMQER/Cd+s3hZke6cI1xgNT/f6ZAz5heND0QtffH+KbcqAwXDEE1/5niYayYaQA==}
engines: {node: '>=v18'}
- '@commitlint/format@19.3.0':
- resolution: {integrity: sha512-luguk5/aF68HiF4H23ACAfk8qS8AHxl4LLN5oxPc24H+2+JRPsNr1OS3Gaea0CrH7PKhArBMKBz5RX9sA5NtTg==}
+ '@commitlint/format@19.8.1':
+ resolution: {integrity: sha512-kSJj34Rp10ItP+Eh9oCItiuN/HwGQMXBnIRk69jdOwEW9llW9FlyqcWYbHPSGofmjsqeoxa38UaEA5tsbm2JWw==}
engines: {node: '>=v18'}
- '@commitlint/is-ignored@19.2.2':
- resolution: {integrity: sha512-eNX54oXMVxncORywF4ZPFtJoBm3Tvp111tg1xf4zWXGfhBPKpfKG6R+G3G4v5CPlRROXpAOpQ3HMhA9n1Tck1g==}
+ '@commitlint/is-ignored@19.8.1':
+ resolution: {integrity: sha512-AceOhEhekBUQ5dzrVhDDsbMaY5LqtN8s1mqSnT2Kz1ERvVZkNihrs3Sfk1Je/rxRNbXYFzKZSHaPsEJJDJV8dg==}
engines: {node: '>=v18'}
- '@commitlint/lint@19.2.2':
- resolution: {integrity: sha512-xrzMmz4JqwGyKQKTpFzlN0dx0TAiT7Ran1fqEBgEmEj+PU98crOFtysJgY+QdeSagx6EDRigQIXJVnfrI0ratA==}
+ '@commitlint/lint@19.8.1':
+ resolution: {integrity: sha512-52PFbsl+1EvMuokZXLRlOsdcLHf10isTPlWwoY1FQIidTsTvjKXVXYb7AvtpWkDzRO2ZsqIgPK7bI98x8LRUEw==}
engines: {node: '>=v18'}
- '@commitlint/load@19.2.0':
- resolution: {integrity: sha512-XvxxLJTKqZojCxaBQ7u92qQLFMMZc4+p9qrIq/9kJDy8DOrEa7P1yx7Tjdc2u2JxIalqT4KOGraVgCE7eCYJyQ==}
+ '@commitlint/load@19.8.1':
+ resolution: {integrity: sha512-9V99EKG3u7z+FEoe4ikgq7YGRCSukAcvmKQuTtUyiYPnOd9a2/H9Ak1J9nJA1HChRQp9OA/sIKPugGS+FK/k1A==}
engines: {node: '>=v18'}
- '@commitlint/message@19.0.0':
- resolution: {integrity: sha512-c9czf6lU+9oF9gVVa2lmKaOARJvt4soRsVmbR7Njwp9FpbBgste5i7l/2l5o8MmbwGh4yE1snfnsy2qyA2r/Fw==}
+ '@commitlint/message@19.8.1':
+ resolution: {integrity: sha512-+PMLQvjRXiU+Ae0Wc+p99EoGEutzSXFVwQfa3jRNUZLNW5odZAyseb92OSBTKCu+9gGZiJASt76Cj3dLTtcTdg==}
engines: {node: '>=v18'}
- '@commitlint/parse@19.0.3':
- resolution: {integrity: sha512-Il+tNyOb8VDxN3P6XoBBwWJtKKGzHlitEuXA5BP6ir/3loWlsSqDr5aecl6hZcC/spjq4pHqNh0qPlfeWu38QA==}
+ '@commitlint/parse@19.8.1':
+ resolution: {integrity: sha512-mmAHYcMBmAgJDKWdkjIGq50X4yB0pSGpxyOODwYmoexxxiUCy5JJT99t1+PEMK7KtsCtzuWYIAXYAiKR+k+/Jw==}
engines: {node: '>=v18'}
- '@commitlint/read@19.2.1':
- resolution: {integrity: sha512-qETc4+PL0EUv7Q36lJbPG+NJiBOGg7SSC7B5BsPWOmei+Dyif80ErfWQ0qXoW9oCh7GTpTNRoaVhiI8RbhuaNw==}
+ '@commitlint/read@19.8.1':
+ resolution: {integrity: sha512-03Jbjb1MqluaVXKHKRuGhcKWtSgh3Jizqy2lJCRbRrnWpcM06MYm8th59Xcns8EqBYvo0Xqb+2DoZFlga97uXQ==}
engines: {node: '>=v18'}
- '@commitlint/resolve-extends@19.1.0':
- resolution: {integrity: sha512-z2riI+8G3CET5CPgXJPlzftH+RiWYLMYv4C9tSLdLXdr6pBNimSKukYP9MS27ejmscqCTVA4almdLh0ODD2KYg==}
+ '@commitlint/resolve-extends@19.8.1':
+ resolution: {integrity: sha512-GM0mAhFk49I+T/5UCYns5ayGStkTt4XFFrjjf0L4S26xoMTSkdCf9ZRO8en1kuopC4isDFuEm7ZOm/WRVeElVg==}
engines: {node: '>=v18'}
- '@commitlint/rules@19.0.3':
- resolution: {integrity: sha512-TspKb9VB6svklxNCKKwxhELn7qhtY1rFF8ls58DcFd0F97XoG07xugPjjbVnLqmMkRjZDbDIwBKt9bddOfLaPw==}
+ '@commitlint/rules@19.8.1':
+ resolution: {integrity: sha512-Hnlhd9DyvGiGwjfjfToMi1dsnw1EXKGJNLTcsuGORHz6SS9swRgkBsou33MQ2n51/boIDrbsg4tIBbRpEWK2kw==}
engines: {node: '>=v18'}
- '@commitlint/to-lines@19.0.0':
- resolution: {integrity: sha512-vkxWo+VQU5wFhiP9Ub9Sre0FYe019JxFikrALVoD5UGa8/t3yOJEpEhxC5xKiENKKhUkTpEItMTRAjHw2SCpZw==}
+ '@commitlint/to-lines@19.8.1':
+ resolution: {integrity: sha512-98Mm5inzbWTKuZQr2aW4SReY6WUukdWXuZhrqf1QdKPZBCCsXuG87c+iP0bwtD6DBnmVVQjgp4whoHRVixyPBg==}
engines: {node: '>=v18'}
- '@commitlint/top-level@19.0.0':
- resolution: {integrity: sha512-KKjShd6u1aMGNkCkaX4aG1jOGdn7f8ZI8TR1VEuNqUOjWTOdcDSsmglinglJ18JTjuBX5I1PtjrhQCRcixRVFQ==}
+ '@commitlint/top-level@19.8.1':
+ resolution: {integrity: sha512-Ph8IN1IOHPSDhURCSXBz44+CIu+60duFwRsg6HqaISFHQHbmBtxVw4ZrFNIYUzEP7WwrNPxa2/5qJ//NK1FGcw==}
engines: {node: '>=v18'}
- '@commitlint/types@19.0.3':
- resolution: {integrity: sha512-tpyc+7i6bPG9mvaBbtKUeghfyZSDgWquIDfMgqYtTbmZ9Y9VzEm2je9EYcQ0aoz5o7NvGS+rcDec93yO08MHYA==}
+ '@commitlint/types@19.8.1':
+ resolution: {integrity: sha512-/yCrWGCoA1SVKOks25EGadP9Pnj0oAIHGpl2wH2M2Y46dPM2ueb8wyCVOD7O3WCTkaJ0IkKvzhl1JY7+uCT2Dw==}
engines: {node: '>=v18'}
+ '@cspell/cspell-bundled-dicts@9.1.2':
+ resolution: {integrity: sha512-mdhxj7j1zqXYKO/KPx2MgN3RPAvqoWvncxz2dOMFBcuUteZPt58NenUoi0VZXEhV/FM2V80NvhHZZafaIcxVjQ==}
+ engines: {node: '>=20'}
+
+ '@cspell/cspell-pipe@9.1.2':
+ resolution: {integrity: sha512-/pIhsf4SI4Q/kvehq9GsGKLgbQsRhiDgthQIgO6YOrEa761wOI2hVdRyc0Tgc1iAGiJEedDaFsAhabVRJBeo2g==}
+ engines: {node: '>=20'}
+
+ '@cspell/cspell-resolver@9.1.2':
+ resolution: {integrity: sha512-dNDx7yMl2h1Ousk08lizTou+BUvce4RPSnPXrQPB7B7CscgZloSyuP3Yyj1Zt81pHNpggrym4Ezx6tMdyPjESw==}
+ engines: {node: '>=20'}
+
+ '@cspell/cspell-service-bus@9.1.2':
+ resolution: {integrity: sha512-YOsUctzCMzEJbKdzNyvPkyMen/i7sGO3Xgcczn848GJPlRsJc50QwsoU67SY7zEARz6y2WS0tv5F5RMrRO4idw==}
+ engines: {node: '>=20'}
+
+ '@cspell/cspell-types@9.1.2':
+ resolution: {integrity: sha512-bSDDjoQi4pbh1BULEA596XCo1PMShTpTb4J2lj8jVYqYgXYQNjSmQFA1fj4NHesC84JpK1um4ybzXBcqtniC7Q==}
+ engines: {node: '>=20'}
+
+ '@cspell/dict-ada@4.1.0':
+ resolution: {integrity: sha512-7SvmhmX170gyPd+uHXrfmqJBY5qLcCX8kTGURPVeGxmt8XNXT75uu9rnZO+jwrfuU2EimNoArdVy5GZRGljGNg==}
+
+ '@cspell/dict-al@1.1.0':
+ resolution: {integrity: sha512-PtNI1KLmYkELYltbzuoztBxfi11jcE9HXBHCpID2lou/J4VMYKJPNqe4ZjVzSI9NYbMnMnyG3gkbhIdx66VSXg==}
+
+ '@cspell/dict-aws@4.0.10':
+ resolution: {integrity: sha512-0qW4sI0GX8haELdhfakQNuw7a2pnWXz3VYQA2MpydH2xT2e6EN9DWFpKAi8DfcChm8MgDAogKkoHtIo075iYng==}
+
+ '@cspell/dict-bash@4.2.0':
+ resolution: {integrity: sha512-HOyOS+4AbCArZHs/wMxX/apRkjxg6NDWdt0jF9i9XkvJQUltMwEhyA2TWYjQ0kssBsnof+9amax2lhiZnh3kCg==}
+
+ '@cspell/dict-companies@3.2.1':
+ resolution: {integrity: sha512-ryaeJ1KhTTKL4mtinMtKn8wxk6/tqD4vX5tFP+Hg89SiIXmbMk5vZZwVf+eyGUWJOyw5A1CVj9EIWecgoi+jYQ==}
+
+ '@cspell/dict-cpp@6.0.8':
+ resolution: {integrity: sha512-BzurRZilWqaJt32Gif6/yCCPi+FtrchjmnehVEIFzbWyeBd/VOUw77IwrEzehZsu5cRU91yPWuWp5fUsKfDAXA==}
+
+ '@cspell/dict-cryptocurrencies@5.0.4':
+ resolution: {integrity: sha512-6iFu7Abu+4Mgqq08YhTKHfH59mpMpGTwdzDB2Y8bbgiwnGFCeoiSkVkgLn1Kel2++hYcZ8vsAW/MJS9oXxuMag==}
+
+ '@cspell/dict-csharp@4.0.6':
+ resolution: {integrity: sha512-w/+YsqOknjQXmIlWDRmkW+BHBPJZ/XDrfJhZRQnp0wzpPOGml7W0q1iae65P2AFRtTdPKYmvSz7AL5ZRkCnSIw==}
+
+ '@cspell/dict-css@4.0.17':
+ resolution: {integrity: sha512-2EisRLHk6X/PdicybwlajLGKF5aJf4xnX2uuG5lexuYKt05xV/J/OiBADmi8q9obhxf1nesrMQbqAt+6CsHo/w==}
+
+ '@cspell/dict-dart@2.3.0':
+ resolution: {integrity: sha512-1aY90lAicek8vYczGPDKr70pQSTQHwMFLbmWKTAI6iavmb1fisJBS1oTmMOKE4ximDf86MvVN6Ucwx3u/8HqLg==}
+
+ '@cspell/dict-data-science@2.0.8':
+ resolution: {integrity: sha512-uyAtT+32PfM29wRBeAkUSbkytqI8bNszNfAz2sGPtZBRmsZTYugKMEO9eDjAIE/pnT9CmbjNuoiXhk+Ss4fCOg==}
+
+ '@cspell/dict-django@4.1.4':
+ resolution: {integrity: sha512-fX38eUoPvytZ/2GA+g4bbdUtCMGNFSLbdJJPKX2vbewIQGfgSFJKY56vvcHJKAvw7FopjvgyS/98Ta9WN1gckg==}
+
+ '@cspell/dict-docker@1.1.14':
+ resolution: {integrity: sha512-p6Qz5mokvcosTpDlgSUREdSbZ10mBL3ndgCdEKMqjCSZJFdfxRdNdjrGER3lQ6LMq5jGr1r7nGXA0gvUJK80nw==}
+
+ '@cspell/dict-dotnet@5.0.9':
+ resolution: {integrity: sha512-JGD6RJW5sHtO5lfiJl11a5DpPN6eKSz5M1YBa1I76j4dDOIqgZB6rQexlDlK1DH9B06X4GdDQwdBfnpAB0r2uQ==}
+
+ '@cspell/dict-elixir@4.0.7':
+ resolution: {integrity: sha512-MAUqlMw73mgtSdxvbAvyRlvc3bYnrDqXQrx5K9SwW8F7fRYf9V4vWYFULh+UWwwkqkhX9w03ZqFYRTdkFku6uA==}
+
+ '@cspell/dict-en-common-misspellings@2.1.2':
+ resolution: {integrity: sha512-r74AObInM1XOUxd3lASnNZNDOIA9Bka7mBDTkvkOeCGoLQhn+Cr7h1889u4K07KHbecKMHP6zw5zQhkdocNzCw==}
+
+ '@cspell/dict-en-gb-mit@3.1.3':
+ resolution: {integrity: sha512-4aY8ySQxSNSRILtf9lJIfSR+su86u8VL6z41gOIhvLIvYnHMFiohV7ebM91GbtdZXBazL7zmGFcpm2EnBzewug==}
+
+ '@cspell/dict-en_us@4.4.13':
+ resolution: {integrity: sha512-6TEHCJKmRqq7fQI7090p+ju12vhuGcNkc6YfxHrcjO816m53VPVaS6IfG6+6OqelQiOMjr0ZD8IHcDIkwThSFw==}
+
+ '@cspell/dict-filetypes@3.0.12':
+ resolution: {integrity: sha512-+ds5wgNdlUxuJvhg8A1TjuSpalDFGCh7SkANCWvIplg6QZPXL4j83lqxP7PgjHpx7PsBUS7vw0aiHPjZy9BItw==}
+
+ '@cspell/dict-flutter@1.1.0':
+ resolution: {integrity: sha512-3zDeS7zc2p8tr9YH9tfbOEYfopKY/srNsAa+kE3rfBTtQERAZeOhe5yxrnTPoufctXLyuUtcGMUTpxr3dO0iaA==}
+
+ '@cspell/dict-fonts@4.0.4':
+ resolution: {integrity: sha512-cHFho4hjojBcHl6qxidl9CvUb492IuSk7xIf2G2wJzcHwGaCFa2o3gRcxmIg1j62guetAeDDFELizDaJlVRIOg==}
+
+ '@cspell/dict-fsharp@1.1.0':
+ resolution: {integrity: sha512-oguWmHhGzgbgbEIBKtgKPrFSVAFtvGHaQS0oj+vacZqMObwkapcTGu7iwf4V3Bc2T3caf0QE6f6rQfIJFIAVsw==}
+
+ '@cspell/dict-fullstack@3.2.6':
+ resolution: {integrity: sha512-cSaq9rz5RIU9j+0jcF2vnKPTQjxGXclntmoNp4XB7yFX2621PxJcekGjwf/lN5heJwVxGLL9toR0CBlGKwQBgA==}
+
+ '@cspell/dict-gaming-terms@1.1.1':
+ resolution: {integrity: sha512-tb8GFxjTLDQstkJcJ90lDqF4rKKlMUKs5/ewePN9P+PYRSehqDpLI5S5meOfPit8LGszeOrjUdBQ4zXo7NpMyQ==}
+
+ '@cspell/dict-git@3.0.6':
+ resolution: {integrity: sha512-nazfOqyxlBOQGgcur9ssEOEQCEZkH8vXfQe8SDEx8sCN/g0SFm8ktabgLVmBOXjy3RzjVNLlM2nBfRQ7e6+5hQ==}
+
+ '@cspell/dict-golang@6.0.22':
+ resolution: {integrity: sha512-FvV0m3Y0nUFxw36uDCD8UtfOPv4wsZnnlabNwB3xNZ2IBn0gBURuMUZywScb9sd2wXM8VFBRoU//tc6NQsOVOg==}
+
+ '@cspell/dict-google@1.0.8':
+ resolution: {integrity: sha512-BnMHgcEeaLyloPmBs8phCqprI+4r2Jb8rni011A8hE+7FNk7FmLE3kiwxLFrcZnnb7eqM0agW4zUaNoB0P+z8A==}
+
+ '@cspell/dict-haskell@4.0.5':
+ resolution: {integrity: sha512-s4BG/4tlj2pPM9Ha7IZYMhUujXDnI0Eq1+38UTTCpatYLbQqDwRFf2KNPLRqkroU+a44yTUAe0rkkKbwy4yRtQ==}
+
+ '@cspell/dict-html-symbol-entities@4.0.3':
+ resolution: {integrity: sha512-aABXX7dMLNFdSE8aY844X4+hvfK7977sOWgZXo4MTGAmOzR8524fjbJPswIBK7GaD3+SgFZ2yP2o0CFvXDGF+A==}
+
+ '@cspell/dict-html@4.0.11':
+ resolution: {integrity: sha512-QR3b/PB972SRQ2xICR1Nw/M44IJ6rjypwzA4jn+GH8ydjAX9acFNfc+hLZVyNe0FqsE90Gw3evLCOIF0vy1vQw==}
+
+ '@cspell/dict-java@5.0.11':
+ resolution: {integrity: sha512-T4t/1JqeH33Raa/QK/eQe26FE17eUCtWu+JsYcTLkQTci2dk1DfcIKo8YVHvZXBnuM43ATns9Xs0s+AlqDeH7w==}
+
+ '@cspell/dict-julia@1.1.0':
+ resolution: {integrity: sha512-CPUiesiXwy3HRoBR3joUseTZ9giFPCydSKu2rkh6I2nVjXnl5vFHzOMLXpbF4HQ1tH2CNfnDbUndxD+I+7eL9w==}
+
+ '@cspell/dict-k8s@1.0.11':
+ resolution: {integrity: sha512-8ojNwB5j4PfZ1Gq9n5c/HKJCtZD3h6+wFy+zpALpDWFFQ2qT22Be30+3PVd+G5gng8or0LeK8VgKKd0l1uKPTA==}
+
+ '@cspell/dict-kotlin@1.1.0':
+ resolution: {integrity: sha512-vySaVw6atY7LdwvstQowSbdxjXG6jDhjkWVWSjg1XsUckyzH1JRHXe9VahZz1i7dpoFEUOWQrhIe5B9482UyJQ==}
+
+ '@cspell/dict-latex@4.0.3':
+ resolution: {integrity: sha512-2KXBt9fSpymYHxHfvhUpjUFyzrmN4c4P8mwIzweLyvqntBT3k0YGZJSriOdjfUjwSygrfEwiuPI1EMrvgrOMJw==}
+
+ '@cspell/dict-lorem-ipsum@4.0.4':
+ resolution: {integrity: sha512-+4f7vtY4dp2b9N5fn0za/UR0kwFq2zDtA62JCbWHbpjvO9wukkbl4rZg4YudHbBgkl73HRnXFgCiwNhdIA1JPw==}
+
+ '@cspell/dict-lua@4.0.7':
+ resolution: {integrity: sha512-Wbr7YSQw+cLHhTYTKV6cAljgMgcY+EUAxVIZW3ljKswEe4OLxnVJ7lPqZF5JKjlXdgCjbPSimsHqyAbC5pQN/Q==}
+
+ '@cspell/dict-makefile@1.0.4':
+ resolution: {integrity: sha512-E4hG/c0ekPqUBvlkrVvzSoAA+SsDA9bLi4xSV3AXHTVru7Y2bVVGMPtpfF+fI3zTkww/jwinprcU1LSohI3ylw==}
+
+ '@cspell/dict-markdown@2.0.11':
+ resolution: {integrity: sha512-stZieFKJyMQbzKTVoalSx2QqCpB0j8nPJF/5x+sBnDIWgMC65jp8Wil+jccWh9/vnUVukP3Ejewven5NC7SWuQ==}
+ peerDependencies:
+ '@cspell/dict-css': ^4.0.17
+ '@cspell/dict-html': ^4.0.11
+ '@cspell/dict-html-symbol-entities': ^4.0.3
+ '@cspell/dict-typescript': ^3.2.2
+
+ '@cspell/dict-monkeyc@1.0.10':
+ resolution: {integrity: sha512-7RTGyKsTIIVqzbvOtAu6Z/lwwxjGRtY5RkKPlXKHEoEAgIXwfDxb5EkVwzGQwQr8hF/D3HrdYbRT8MFBfsueZw==}
+
+ '@cspell/dict-node@5.0.7':
+ resolution: {integrity: sha512-ZaPpBsHGQCqUyFPKLyCNUH2qzolDRm1/901IO8e7btk7bEDF56DN82VD43gPvD4HWz3yLs/WkcLa01KYAJpnOw==}
+
+ '@cspell/dict-npm@5.2.9':
+ resolution: {integrity: sha512-1uxRQ0LGPweRX8U9EEoU/tk5GGtTLAJT0BMmeHbe2AfzxX3nYSZtK/q52h9yg/wZLgvnFYzha2DL70uuT8oZuA==}
+
+ '@cspell/dict-php@4.0.14':
+ resolution: {integrity: sha512-7zur8pyncYZglxNmqsRycOZ6inpDoVd4yFfz1pQRe5xaRWMiK3Km4n0/X/1YMWhh3e3Sl/fQg5Axb2hlN68t1g==}
+
+ '@cspell/dict-powershell@5.0.14':
+ resolution: {integrity: sha512-ktjjvtkIUIYmj/SoGBYbr3/+CsRGNXGpvVANrY0wlm/IoGlGywhoTUDYN0IsGwI2b8Vktx3DZmQkfb3Wo38jBA==}
+
+ '@cspell/dict-public-licenses@2.0.13':
+ resolution: {integrity: sha512-1Wdp/XH1ieim7CadXYE7YLnUlW0pULEjVl9WEeziZw3EKCAw8ZI8Ih44m4bEa5VNBLnuP5TfqC4iDautAleQzQ==}
+
+ '@cspell/dict-python@4.2.18':
+ resolution: {integrity: sha512-hYczHVqZBsck7DzO5LumBLJM119a3F17aj8a7lApnPIS7cmEwnPc2eACNscAHDk7qAo2127oI7axUoFMe9/g1g==}
+
+ '@cspell/dict-r@2.1.0':
+ resolution: {integrity: sha512-k2512wgGG0lTpTYH9w5Wwco+lAMf3Vz7mhqV8+OnalIE7muA0RSuD9tWBjiqLcX8zPvEJr4LdgxVju8Gk3OKyA==}
+
+ '@cspell/dict-ruby@5.0.8':
+ resolution: {integrity: sha512-ixuTneU0aH1cPQRbWJvtvOntMFfeQR2KxT8LuAv5jBKqQWIHSxzGlp+zX3SVyoeR0kOWiu64/O5Yn836A5yMcQ==}
+
+ '@cspell/dict-rust@4.0.11':
+ resolution: {integrity: sha512-OGWDEEzm8HlkSmtD8fV3pEcO2XBpzG2XYjgMCJCRwb2gRKvR+XIm6Dlhs04N/K2kU+iH8bvrqNpM8fS/BFl0uw==}
+
+ '@cspell/dict-scala@5.0.7':
+ resolution: {integrity: sha512-yatpSDW/GwulzO3t7hB5peoWwzo+Y3qTc0pO24Jf6f88jsEeKmDeKkfgPbYuCgbE4jisGR4vs4+jfQZDIYmXPA==}
+
+ '@cspell/dict-shell@1.1.0':
+ resolution: {integrity: sha512-D/xHXX7T37BJxNRf5JJHsvziFDvh23IF/KvkZXNSh8VqcRdod3BAz9VGHZf6VDqcZXr1VRqIYR3mQ8DSvs3AVQ==}
+
+ '@cspell/dict-software-terms@5.1.2':
+ resolution: {integrity: sha512-MssT9yyInezB6mFqHTDNOIVjbMakORllIt7IJ91LrgiQOcDLzidR0gN9pE340s655TJ8U5MJNAfRfH0oRU14KQ==}
+
+ '@cspell/dict-sql@2.2.0':
+ resolution: {integrity: sha512-MUop+d1AHSzXpBvQgQkCiok8Ejzb+nrzyG16E8TvKL2MQeDwnIvMe3bv90eukP6E1HWb+V/MA/4pnq0pcJWKqQ==}
+
+ '@cspell/dict-svelte@1.0.6':
+ resolution: {integrity: sha512-8LAJHSBdwHCoKCSy72PXXzz7ulGROD0rP1CQ0StOqXOOlTUeSFaJJlxNYjlONgd2c62XBQiN2wgLhtPN+1Zv7Q==}
+
+ '@cspell/dict-swift@2.0.5':
+ resolution: {integrity: sha512-3lGzDCwUmnrfckv3Q4eVSW3sK3cHqqHlPprFJZD4nAqt23ot7fic5ALR7J4joHpvDz36nHX34TgcbZNNZOC/JA==}
+
+ '@cspell/dict-terraform@1.1.1':
+ resolution: {integrity: sha512-07KFDwCU7EnKl4hOZLsLKlj6Zceq/IsQ3LRWUyIjvGFfZHdoGtFdCp3ZPVgnFaAcd/DKv+WVkrOzUBSYqHopQQ==}
+
+ '@cspell/dict-typescript@3.2.2':
+ resolution: {integrity: sha512-H9Y+uUHsTIDFO/jdfUAcqmcd5osT+2DB5b0aRCHfLWN/twUbGn/1qq3b7YwEvttxKlYzWHU3uNFf+KfA93VY7w==}
+
+ '@cspell/dict-vue@3.0.4':
+ resolution: {integrity: sha512-0dPtI0lwHcAgSiQFx8CzvqjdoXROcH+1LyqgROCpBgppommWpVhbQ0eubnKotFEXgpUCONVkeZJ6Ql8NbTEu+w==}
+
+ '@cspell/dynamic-import@9.1.2':
+ resolution: {integrity: sha512-Kg22HCx5m0znVPLea2jRrvMnzHZAAzqcDr5g6Dbd4Pizs5b3SPQuRpFmYaDvKo26JNZnfRqA9eweiuE5aQAf2A==}
+ engines: {node: '>=20'}
+
+ '@cspell/eslint-plugin@9.1.2':
+ resolution: {integrity: sha512-UUCCBAyv3gTL1P19fX9C+cknkwCXHvnHUAaFBz25dX6PhJSPyYPmVdA8jm/2H6+GQYKBnHvWgfjkkiZgtqoQRA==}
+ engines: {node: '>=20'}
+ peerDependencies:
+ eslint: ^7 || ^8 || ^9
+
+ '@cspell/filetypes@9.1.2':
+ resolution: {integrity: sha512-j+6kDz3GbeYwwtlzVosqVaSiFGMhf0u3y8eAP3IV2bTelhP2ZiOLD+yNbAyYGao7p10/Sqv+Ri0yT7IsGLniww==}
+ engines: {node: '>=20'}
+
+ '@cspell/strong-weak-map@9.1.2':
+ resolution: {integrity: sha512-6X9oXnklvdt1pd0x0Mh6qXaaIRxjt0G50Xz5ZGm3wpAagv0MFvTThdmYVFfBuZ91x7fDT3u77y3d1uqdGQW1CA==}
+ engines: {node: '>=20'}
+
+ '@cspell/url@9.1.2':
+ resolution: {integrity: sha512-PMJBuLYQIdFnEfPHQXaVE5hHUkbbOxOIRmHyZwWEc9+79tIaIkiwLpjZvbm8p6f9WXAaESqXs/uK2tUC/bjwmw==}
+ engines: {node: '>=20'}
+
'@cspotcode/source-map-support@0.8.1':
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
+ '@csstools/color-helpers@5.0.2':
+ resolution: {integrity: sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==}
+ engines: {node: '>=18'}
+
+ '@csstools/css-calc@2.1.4':
+ resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@csstools/css-parser-algorithms': ^3.0.5
+ '@csstools/css-tokenizer': ^3.0.4
+
+ '@csstools/css-color-parser@3.0.10':
+ resolution: {integrity: sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@csstools/css-parser-algorithms': ^3.0.5
+ '@csstools/css-tokenizer': ^3.0.4
+
+ '@csstools/css-parser-algorithms@3.0.5':
+ resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@csstools/css-tokenizer': ^3.0.4
+
+ '@csstools/css-tokenizer@3.0.4':
+ resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==}
+ engines: {node: '>=18'}
+
'@dabh/diagnostics@2.0.3':
resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==}
- '@es-joy/jsdoccomment@0.43.0':
- resolution: {integrity: sha512-Q1CnsQrytI3TlCB1IVWXWeqUIPGVEKGaE7IbVdt13Nq/3i0JESAkQQERrfiQkmlpijl+++qyqPgaS31Bvc1jRQ==}
- engines: {node: '>=16'}
+ '@emnapi/core@1.4.3':
+ resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==}
- '@esbuild/aix-ppc64@0.20.2':
- resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==}
- engines: {node: '>=12'}
- cpu: [ppc64]
- os: [aix]
+ '@emnapi/runtime@1.4.3':
+ resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==}
- '@esbuild/aix-ppc64@0.21.3':
- resolution: {integrity: sha512-yTgnwQpFVYfvvo4SvRFB0SwrW8YjOxEoT7wfMT7Ol5v7v5LDNvSGo67aExmxOb87nQNeWPVvaGBNfQ7BXcrZ9w==}
- engines: {node: '>=12'}
+ '@emnapi/wasi-threads@1.0.2':
+ resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==}
+
+ '@es-joy/jsdoccomment@0.52.0':
+ resolution: {integrity: sha512-BXuN7BII+8AyNtn57euU2Yxo9yA/KUDNzrpXyi3pfqKmBhhysR6ZWOebFh3vyPoqA3/j1SOvGgucElMGwlXing==}
+ engines: {node: '>=20.11.0'}
+
+ '@esbuild/aix-ppc64@0.25.5':
+ resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==}
+ engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
- '@esbuild/android-arm64@0.20.2':
- resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [android]
-
- '@esbuild/android-arm64@0.21.3':
- resolution: {integrity: sha512-c+ty9necz3zB1Y+d/N+mC6KVVkGUUOcm4ZmT5i/Fk5arOaY3i6CA3P5wo/7+XzV8cb4GrI/Zjp8NuOQ9Lfsosw==}
- engines: {node: '>=12'}
+ '@esbuild/android-arm64@0.25.5':
+ resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==}
+ engines: {node: '>=18'}
cpu: [arm64]
os: [android]
- '@esbuild/android-arm@0.20.2':
- resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==}
- engines: {node: '>=12'}
- cpu: [arm]
- os: [android]
-
- '@esbuild/android-arm@0.21.3':
- resolution: {integrity: sha512-bviJOLMgurLJtF1/mAoJLxDZDL6oU5/ztMHnJQRejbJrSc9FFu0QoUoFhvi6qSKJEw9y5oGyvr9fuDtzJ30rNQ==}
- engines: {node: '>=12'}
+ '@esbuild/android-arm@0.25.5':
+ resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==}
+ engines: {node: '>=18'}
cpu: [arm]
os: [android]
- '@esbuild/android-x64@0.20.2':
- resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [android]
-
- '@esbuild/android-x64@0.21.3':
- resolution: {integrity: sha512-JReHfYCRK3FVX4Ra+y5EBH1b9e16TV2OxrPAvzMsGeES0X2Ndm9ImQRI4Ket757vhc5XBOuGperw63upesclRw==}
- engines: {node: '>=12'}
+ '@esbuild/android-x64@0.25.5':
+ resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==}
+ engines: {node: '>=18'}
cpu: [x64]
os: [android]
- '@esbuild/darwin-arm64@0.20.2':
- resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [darwin]
-
- '@esbuild/darwin-arm64@0.21.3':
- resolution: {integrity: sha512-U3fuQ0xNiAkXOmQ6w5dKpEvXQRSpHOnbw7gEfHCRXPeTKW9sBzVck6C5Yneb8LfJm0l6le4NQfkNPnWMSlTFUQ==}
- engines: {node: '>=12'}
+ '@esbuild/darwin-arm64@0.25.5':
+ resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==}
+ engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
- '@esbuild/darwin-x64@0.20.2':
- resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [darwin]
-
- '@esbuild/darwin-x64@0.21.3':
- resolution: {integrity: sha512-3m1CEB7F07s19wmaMNI2KANLcnaqryJxO1fXHUV5j1rWn+wMxdUYoPyO2TnAbfRZdi7ADRwJClmOwgT13qlP3Q==}
- engines: {node: '>=12'}
+ '@esbuild/darwin-x64@0.25.5':
+ resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==}
+ engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
- '@esbuild/freebsd-arm64@0.20.2':
- resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [freebsd]
-
- '@esbuild/freebsd-arm64@0.21.3':
- resolution: {integrity: sha512-fsNAAl5pU6wmKHq91cHWQT0Fz0vtyE1JauMzKotrwqIKAswwP5cpHUCxZNSTuA/JlqtScq20/5KZ+TxQdovU/g==}
- engines: {node: '>=12'}
+ '@esbuild/freebsd-arm64@0.25.5':
+ resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==}
+ engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
- '@esbuild/freebsd-x64@0.20.2':
- resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [freebsd]
-
- '@esbuild/freebsd-x64@0.21.3':
- resolution: {integrity: sha512-tci+UJ4zP5EGF4rp8XlZIdq1q1a/1h9XuronfxTMCNBslpCtmk97Q/5qqy1Mu4zIc0yswN/yP/BLX+NTUC1bXA==}
- engines: {node: '>=12'}
+ '@esbuild/freebsd-x64@0.25.5':
+ resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==}
+ engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
- '@esbuild/linux-arm64@0.20.2':
- resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [linux]
-
- '@esbuild/linux-arm64@0.21.3':
- resolution: {integrity: sha512-vvG6R5g5ieB4eCJBQevyDMb31LMHthLpXTc2IGkFnPWS/GzIFDnaYFp558O+XybTmYrVjxnryru7QRleJvmZ6Q==}
- engines: {node: '>=12'}
+ '@esbuild/linux-arm64@0.25.5':
+ resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==}
+ engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
- '@esbuild/linux-arm@0.20.2':
- resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==}
- engines: {node: '>=12'}
- cpu: [arm]
- os: [linux]
-
- '@esbuild/linux-arm@0.21.3':
- resolution: {integrity: sha512-f6kz2QpSuyHHg01cDawj0vkyMwuIvN62UAguQfnNVzbge2uWLhA7TCXOn83DT0ZvyJmBI943MItgTovUob36SQ==}
- engines: {node: '>=12'}
+ '@esbuild/linux-arm@0.25.5':
+ resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==}
+ engines: {node: '>=18'}
cpu: [arm]
os: [linux]
- '@esbuild/linux-ia32@0.20.2':
- resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==}
- engines: {node: '>=12'}
- cpu: [ia32]
- os: [linux]
-
- '@esbuild/linux-ia32@0.21.3':
- resolution: {integrity: sha512-HjCWhH7K96Na+66TacDLJmOI9R8iDWDDiqe17C7znGvvE4sW1ECt9ly0AJ3dJH62jHyVqW9xpxZEU1jKdt+29A==}
- engines: {node: '>=12'}
+ '@esbuild/linux-ia32@0.25.5':
+ resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==}
+ engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
- '@esbuild/linux-loong64@0.20.2':
- resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==}
- engines: {node: '>=12'}
- cpu: [loong64]
- os: [linux]
-
- '@esbuild/linux-loong64@0.21.3':
- resolution: {integrity: sha512-BGpimEccmHBZRcAhdlRIxMp7x9PyJxUtj7apL2IuoG9VxvU/l/v1z015nFs7Si7tXUwEsvjc1rOJdZCn4QTU+Q==}
- engines: {node: '>=12'}
+ '@esbuild/linux-loong64@0.25.5':
+ resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==}
+ engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
- '@esbuild/linux-mips64el@0.20.2':
- resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==}
- engines: {node: '>=12'}
- cpu: [mips64el]
- os: [linux]
-
- '@esbuild/linux-mips64el@0.21.3':
- resolution: {integrity: sha512-5rMOWkp7FQGtAH3QJddP4w3s47iT20hwftqdm7b+loe95o8JU8ro3qZbhgMRy0VuFU0DizymF1pBKkn3YHWtsw==}
- engines: {node: '>=12'}
+ '@esbuild/linux-mips64el@0.25.5':
+ resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==}
+ engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
- '@esbuild/linux-ppc64@0.20.2':
- resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==}
- engines: {node: '>=12'}
- cpu: [ppc64]
- os: [linux]
-
- '@esbuild/linux-ppc64@0.21.3':
- resolution: {integrity: sha512-h0zj1ldel89V5sjPLo5H1SyMzp4VrgN1tPkN29TmjvO1/r0MuMRwJxL8QY05SmfsZRs6TF0c/IDH3u7XYYmbAg==}
- engines: {node: '>=12'}
+ '@esbuild/linux-ppc64@0.25.5':
+ resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==}
+ engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
- '@esbuild/linux-riscv64@0.20.2':
- resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==}
- engines: {node: '>=12'}
- cpu: [riscv64]
- os: [linux]
-
- '@esbuild/linux-riscv64@0.21.3':
- resolution: {integrity: sha512-dkAKcTsTJ+CRX6bnO17qDJbLoW37npd5gSNtSzjYQr0svghLJYGYB0NF1SNcU1vDcjXLYS5pO4qOW4YbFama4A==}
- engines: {node: '>=12'}
+ '@esbuild/linux-riscv64@0.25.5':
+ resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==}
+ engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
- '@esbuild/linux-s390x@0.20.2':
- resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==}
- engines: {node: '>=12'}
- cpu: [s390x]
- os: [linux]
-
- '@esbuild/linux-s390x@0.21.3':
- resolution: {integrity: sha512-vnD1YUkovEdnZWEuMmy2X2JmzsHQqPpZElXx6dxENcIwTu+Cu5ERax6+Ke1QsE814Zf3c6rxCfwQdCTQ7tPuXA==}
- engines: {node: '>=12'}
+ '@esbuild/linux-s390x@0.25.5':
+ resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==}
+ engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
- '@esbuild/linux-x64@0.20.2':
- resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [linux]
-
- '@esbuild/linux-x64@0.21.3':
- resolution: {integrity: sha512-IOXOIm9WaK7plL2gMhsWJd+l2bfrhfilv0uPTptoRoSb2p09RghhQQp9YY6ZJhk/kqmeRt6siRdMSLLwzuT0KQ==}
- engines: {node: '>=12'}
+ '@esbuild/linux-x64@0.25.5':
+ resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==}
+ engines: {node: '>=18'}
cpu: [x64]
os: [linux]
- '@esbuild/netbsd-x64@0.20.2':
- resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==}
- engines: {node: '>=12'}
- cpu: [x64]
+ '@esbuild/netbsd-arm64@0.25.5':
+ resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
os: [netbsd]
- '@esbuild/netbsd-x64@0.21.3':
- resolution: {integrity: sha512-uTgCwsvQ5+vCQnqM//EfDSuomo2LhdWhFPS8VL8xKf+PKTCrcT/2kPPoWMTs22aB63MLdGMJiE3f1PHvCDmUOw==}
- engines: {node: '>=12'}
+ '@esbuild/netbsd-x64@0.25.5':
+ resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==}
+ engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
- '@esbuild/openbsd-x64@0.20.2':
- resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==}
- engines: {node: '>=12'}
- cpu: [x64]
+ '@esbuild/openbsd-arm64@0.25.5':
+ resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
os: [openbsd]
- '@esbuild/openbsd-x64@0.21.3':
- resolution: {integrity: sha512-vNAkR17Ub2MgEud2Wag/OE4HTSI6zlb291UYzHez/psiKarp0J8PKGDnAhMBcHFoOHMXHfExzmjMojJNbAStrQ==}
- engines: {node: '>=12'}
+ '@esbuild/openbsd-x64@0.25.5':
+ resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==}
+ engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
- '@esbuild/sunos-x64@0.20.2':
- resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [sunos]
-
- '@esbuild/sunos-x64@0.21.3':
- resolution: {integrity: sha512-W8H9jlGiSBomkgmouaRoTXo49j4w4Kfbl6I1bIdO/vT0+0u4f20ko3ELzV3hPI6XV6JNBVX+8BC+ajHkvffIJA==}
- engines: {node: '>=12'}
+ '@esbuild/sunos-x64@0.25.5':
+ resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==}
+ engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
- '@esbuild/win32-arm64@0.20.2':
- resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [win32]
-
- '@esbuild/win32-arm64@0.21.3':
- resolution: {integrity: sha512-EjEomwyLSCg8Ag3LDILIqYCZAq/y3diJ04PnqGRgq8/4O3VNlXyMd54j/saShaN4h5o5mivOjAzmU6C3X4v0xw==}
- engines: {node: '>=12'}
+ '@esbuild/win32-arm64@0.25.5':
+ resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==}
+ engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
- '@esbuild/win32-ia32@0.20.2':
- resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==}
- engines: {node: '>=12'}
- cpu: [ia32]
- os: [win32]
-
- '@esbuild/win32-ia32@0.21.3':
- resolution: {integrity: sha512-WGiE/GgbsEwR33++5rzjiYsKyHywE8QSZPF7Rfx9EBfK3Qn3xyR6IjyCr5Uk38Kg8fG4/2phN7sXp4NPWd3fcw==}
- engines: {node: '>=12'}
+ '@esbuild/win32-ia32@0.25.5':
+ resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==}
+ engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
- '@esbuild/win32-x64@0.20.2':
- resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [win32]
-
- '@esbuild/win32-x64@0.21.3':
- resolution: {integrity: sha512-xRxC0jaJWDLYvcUvjQmHCJSfMrgmUuvsoXgDeU/wTorQ1ngDdUBuFtgY3W1Pc5sprGAvZBtWdJX7RPg/iZZUqA==}
- engines: {node: '>=12'}
+ '@esbuild/win32-x64@0.25.5':
+ resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==}
+ engines: {node: '>=18'}
cpu: [x64]
os: [win32]
- '@eslint-community/eslint-utils@4.4.0':
- resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
+ '@eslint-community/eslint-utils@4.7.0':
+ resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
- '@eslint-community/regexpp@4.10.0':
- resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==}
+ '@eslint-community/regexpp@4.12.1':
+ resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
- '@eslint/eslintrc@2.1.4':
- resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ '@eslint/config-array@0.21.0':
+ resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/js@8.57.0':
- resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ '@eslint/config-helpers@0.3.0':
+ resolution: {integrity: sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/core@0.14.0':
+ resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/core@0.15.1':
+ resolution: {integrity: sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/eslintrc@3.3.1':
+ resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/js@9.30.1':
+ resolution: {integrity: sha512-zXhuECFlyep42KZUhWjfvsmXGX39W8K8LFb8AWXM9gSV9dQB+MrJGLKvW6Zw0Ggnbpw0VHTtrhFXYe3Gym18jg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/object-schema@2.1.6':
+ resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/plugin-kit@0.3.3':
+ resolution: {integrity: sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@gar/promisify@1.1.3':
resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==}
- '@humanwhocodes/config-array@0.11.14':
- resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
- engines: {node: '>=10.10.0'}
+ '@humanfs/core@0.19.1':
+ resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
+ engines: {node: '>=18.18.0'}
+
+ '@humanfs/node@0.16.6':
+ resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==}
+ engines: {node: '>=18.18.0'}
+
+ '@humanwhocodes/gitignore-to-minimatch@1.0.2':
+ resolution: {integrity: sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==}
'@humanwhocodes/module-importer@1.0.1':
resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
engines: {node: '>=12.22'}
- '@humanwhocodes/object-schema@2.0.3':
- resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
+ '@humanwhocodes/retry@0.3.1':
+ resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==}
+ engines: {node: '>=18.18'}
- '@iarna/toml@2.2.5':
- resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==}
+ '@humanwhocodes/retry@0.4.3':
+ resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
+ engines: {node: '>=18.18'}
- '@inquirer/figures@1.0.2':
- resolution: {integrity: sha512-4F1MBwVr3c/m4bAUef6LgkvBfSjzwH+OfldgHqcuacWwSUetFebM2wi58WfG9uk1rR98U6GwLed4asLJbwdV5w==}
- engines: {node: '>=18'}
+ '@isaacs/balanced-match@4.0.1':
+ resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
+ engines: {node: 20 || >=22}
+
+ '@isaacs/brace-expansion@5.0.0':
+ resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==}
+ engines: {node: 20 || >=22}
'@isaacs/cliui@8.0.2':
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
'@jercle/yargonaut@1.1.5':
resolution: {integrity: sha512-zBp2myVvBHp1UaJsNTyS6q4UDKT7eRiqTS4oNTS6VQMd6mpxYOdbeK4pY279cDCdakGy6hG0J3ejoXZVsPwHqw==}
- '@jest/expect-utils@29.7.0':
- resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
-
- '@jest/schemas@29.6.3':
- resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
-
- '@jest/types@29.6.3':
- resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
-
- '@jridgewell/gen-mapping@0.3.5':
- resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
- engines: {node: '>=6.0.0'}
+ '@jridgewell/gen-mapping@0.3.12':
+ resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==}
'@jridgewell/resolve-uri@3.1.2':
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
engines: {node: '>=6.0.0'}
- '@jridgewell/set-array@1.2.1':
- resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
- engines: {node: '>=6.0.0'}
-
- '@jridgewell/sourcemap-codec@1.4.15':
- resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
+ '@jridgewell/sourcemap-codec@1.5.4':
+ resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==}
- '@jridgewell/trace-mapping@0.3.25':
- resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
+ '@jridgewell/trace-mapping@0.3.29':
+ resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==}
'@jridgewell/trace-mapping@0.3.9':
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
- '@ljharb/through@2.3.13':
- resolution: {integrity: sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==}
- engines: {node: '>= 0.4'}
+ '@jsr/std__assert@1.0.13':
+ resolution: {integrity: sha512-rZ44REoi2/p+gqu8OfkcNeaTOSiG1kD6v8gyA0YjkXsOkDsiGw9g8h7JuGC/OD7GgOVgTEY+9Cih49Y18rkrCQ==, tarball: https://npm.jsr.io/~/11/@jsr/std__assert/1.0.13.tgz}
- '@microsoft/tsdoc-config@0.16.2':
- resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==}
+ '@jsr/std__expect@1.0.16':
+ resolution: {integrity: sha512-ni+i1uwOnU9PMOcSQAHsNTYYD5o137871udJi9hiGneXlZTrD4/fVcNJ5AyH+GEF5yZzjeCjfaeHdXLFKZFCfQ==, tarball: https://npm.jsr.io/~/11/@jsr/std__expect/1.0.16.tgz}
- '@microsoft/tsdoc@0.14.2':
- resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==}
+ '@jsr/std__internal@1.0.9':
+ resolution: {integrity: sha512-s+f4qrJzZgPAy7XuFOtgaSaxyPLnnEmAfXGLvRXGxPTL76URLVHkF+hOzqXz+bmk8/awybF6BRsasxtAQOV23Q==, tarball: https://npm.jsr.io/~/11/@jsr/std__internal/1.0.9.tgz}
- '@mikro-orm/cli@6.2.7':
- resolution: {integrity: sha512-P+ifBdGkQbdot6oABh7w6IT30Il1O6BQMDWhy/VvdvucO0FosaDtF64GAnpAqoweUpxlVDyD4Osg0AZwblGDbw==}
+ '@mikro-orm/cli@6.4.16':
+ resolution: {integrity: sha512-O1uP+5j/xMYR8aPTamzQKYJnL1GCootGLR5UVH1bQJS9/ukFuAKDsu6VpJkJxE9j0TLxAhTmo56iZFUIS04sFQ==}
engines: {node: '>= 18.12.0'}
hasBin: true
- '@mikro-orm/core@6.2.7':
- resolution: {integrity: sha512-XTgeNsah4QpiYs0t/AaTjlpnBMEHx8rCvn6uPlg2nONYzGHHL7L28WvTCMsMsmj7V8U8NhTEu2dQhma/OXfViA==}
+ '@mikro-orm/core@6.4.16':
+ resolution: {integrity: sha512-BW/My1VlI0R25Eojdh0UiET8J+mEruThksGVfllEnjJQ0uwGs3mm/TbMclv0g+d7Qp4+mpzDQU4+lIo8okHYsw==}
engines: {node: '>= 18.12.0'}
- '@mikro-orm/knex@6.2.7':
- resolution: {integrity: sha512-gndT5begmE0hcK5i1w7jMRclFMobkXRD6kfu1h76lrBUmNFJqLYip8o11W2X7IIxE6gxv4Z23DFl4/7d9fvTww==}
+ '@mikro-orm/knex@6.4.16':
+ resolution: {integrity: sha512-2xQodj3uh8maPGsLR7PZMmECtdyLutGxzzrGrrhSX2b+7v9k4MeMazTi4/627hJvivdUpuofypW5zMpw3TU1vQ==}
engines: {node: '>= 18.12.0'}
peerDependencies:
'@mikro-orm/core': ^6.0.0
+ better-sqlite3: '*'
+ libsql: '*'
+ mariadb: '*'
+ peerDependenciesMeta:
+ better-sqlite3:
+ optional: true
+ libsql:
+ optional: true
+ mariadb:
+ optional: true
- '@mikro-orm/mariadb@6.2.7':
- resolution: {integrity: sha512-9bAXoJOc4GrYdN7zx3uh3WAlpIj7mqNPhH3C/AACYhoi/MqdGET732Kkoa0fDM6YPMQrhFZUvRxykPf92A6NwQ==}
+ '@mikro-orm/mariadb@6.4.16':
+ resolution: {integrity: sha512-J9Hr6pkqZh287YIl2NsKGs932EYPPQU0pSES0UYORO56o8g1mGqAsLnYQL0T6fy4UuptUnJKSjHvjpLpKd/pcw==}
engines: {node: '>= 18.12.0'}
peerDependencies:
'@mikro-orm/core': ^6.0.0
- '@mikro-orm/reflection@6.2.7':
- resolution: {integrity: sha512-piJKaUlgRVvNjCYYuxzMYKUezw8eXljKoIvHKPjOlZAVzeTNVYzDhHyahXACuXwrpjJaAFfBZ5EKUkJZ3v56/w==}
+ '@mikro-orm/reflection@6.4.16':
+ resolution: {integrity: sha512-waPaDZwOlwNUUuD00rj8HrByhs1y5hvTEFIc14LX0mgtP+OHkarM7+JTJ68RB2UaDVyZ/Bmof9uhH7TOH2awVw==}
engines: {node: '>= 18.12.0'}
peerDependencies:
'@mikro-orm/core': ^6.0.0
- '@mikro-orm/sqlite@6.2.7':
- resolution: {integrity: sha512-WnPbBWv8sHwxdPmCux1GvtnRN7au1QcSMQ/20atqyC51EpIA5y2sH4B3PkRezL5Cil6E+G6dfiqJscJvaa5CKw==}
+ '@mikro-orm/sqlite@6.4.16':
+ resolution: {integrity: sha512-mwmv+ZkZiA8HMt+UvA7jI/3qv4R3Sz1zOcLfAo9QMov2DdnPxJYkDxQ+9fAnrswurOzoo0ApqUGZ4hF6J0djfw==}
engines: {node: '>= 18.12.0'}
peerDependencies:
'@mikro-orm/core': ^6.0.0
- '@mongodb-js/saslprep@1.1.7':
- resolution: {integrity: sha512-dCHW/oEX0KJ4NjDULBo3JiOaK5+6axtpBbS+ao2ZInoAL9/YRQLhXzSNAFz7hP4nzLkIqsfYAK/PDE3+XHny0Q==}
+ '@mongodb-js/saslprep@1.3.0':
+ resolution: {integrity: sha512-zlayKCsIjYb7/IdfqxorK5+xUMyi4vOKcFy10wKJYc63NSdKI8mNME+uJqfatkPmOSMMUiojrL58IePKBm3gvQ==}
+
+ '@napi-rs/wasm-runtime@0.2.11':
+ resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==}
'@nearform/heap-profiler@2.0.0':
resolution: {integrity: sha512-846CWyq3Ky5rzcl8Z3S+VT3z6GQSlYD1G/dqbtANu29NUHoCO+W7tOZRK6eA6FjLHnNX0DvP1Mrt2oFBPnkxLw==}
engines: {node: '>= 8'}
'@nodelib/fs.stat@2.0.5':
- resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
- engines: {node: '>= 8'}
-
- '@nodelib/fs.walk@1.2.8':
- resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
- engines: {node: '>= 8'}
-
- '@npmcli/fs@1.1.1':
- resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==}
-
- '@npmcli/move-file@1.1.2':
- resolution: {integrity: sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==}
- engines: {node: '>=10'}
- deprecated: This functionality has been moved to @npmcli/fs
-
- '@octokit/auth-token@4.0.0':
- resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==}
- engines: {node: '>= 18'}
-
- '@octokit/core@5.2.0':
- resolution: {integrity: sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==}
- engines: {node: '>= 18'}
-
- '@octokit/endpoint@9.0.5':
- resolution: {integrity: sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==}
- engines: {node: '>= 18'}
-
- '@octokit/graphql@7.1.0':
- resolution: {integrity: sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==}
- engines: {node: '>= 18'}
-
- '@octokit/openapi-types@22.2.0':
- resolution: {integrity: sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==}
-
- '@octokit/plugin-paginate-rest@11.3.1':
- resolution: {integrity: sha512-ryqobs26cLtM1kQxqeZui4v8FeznirUsksiA+RYemMPJ7Micju0WSkv50dBksTuZks9O5cg4wp+t8fZ/cLY56g==}
- engines: {node: '>= 18'}
- peerDependencies:
- '@octokit/core': '5'
-
- '@octokit/plugin-request-log@4.0.1':
- resolution: {integrity: sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==}
- engines: {node: '>= 18'}
- peerDependencies:
- '@octokit/core': '5'
-
- '@octokit/plugin-rest-endpoint-methods@13.2.2':
- resolution: {integrity: sha512-EI7kXWidkt3Xlok5uN43suK99VWqc8OaIMktY9d9+RNKl69juoTyxmLoWPIZgJYzi41qj/9zU7G/ljnNOJ5AFA==}
- engines: {node: '>= 18'}
- peerDependencies:
- '@octokit/core': ^5
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
- '@octokit/request-error@5.1.0':
- resolution: {integrity: sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==}
- engines: {node: '>= 18'}
+ '@nodelib/fs.walk@1.2.8':
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
- '@octokit/request@8.4.0':
- resolution: {integrity: sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==}
- engines: {node: '>= 18'}
+ '@nolyfill/is-core-module@1.0.39':
+ resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
+ engines: {node: '>=12.4.0'}
- '@octokit/rest@20.1.1':
- resolution: {integrity: sha512-MB4AYDsM5jhIHro/dq4ix1iWTLGToIGk6cWF5L6vanFaMble5jTX/UBQyiv05HsWnwUtY8JrfHy2LWfKwihqMw==}
- engines: {node: '>= 18'}
+ '@npmcli/fs@1.1.1':
+ resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==}
- '@octokit/types@13.5.0':
- resolution: {integrity: sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==}
+ '@npmcli/move-file@1.1.2':
+ resolution: {integrity: sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==}
+ engines: {node: '>=10'}
+ deprecated: This functionality has been moved to @npmcli/fs
'@one-ini/wasm@0.1.1':
resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==}
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
- '@pkgr/core@0.1.1':
- resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==}
+ '@pkgr/core@0.2.7':
+ resolution: {integrity: sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
- '@pnpm/config.env-replace@1.1.0':
- resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==}
- engines: {node: '>=12.22.0'}
-
- '@pnpm/network.ca-file@1.0.2':
- resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==}
- engines: {node: '>=12.22.0'}
-
- '@pnpm/npm-conf@2.2.2':
- resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==}
- engines: {node: '>=12'}
+ '@rolldown/pluginutils@1.0.0-beta.19':
+ resolution: {integrity: sha512-3FL3mnMbPu0muGOCaKAhhFEYmqv9eTfPSJRJmANrCwtgK8VuxpsZDGK+m0LYAGoyO8+0j5uRe4PeyPDK1yA/hA==}
- '@release-it/bumper@6.0.1':
- resolution: {integrity: sha512-yeQsbGNMzzN0c/5JV1awXP6UHX/kJamXCKR6/daS0YQfj98SZXAcLn3JEq+qfK/Jq/cnATnlz5r6UY0cfBkm1A==}
- engines: {node: '>=18'}
- peerDependencies:
- release-it: ^17.0.0
+ '@rolldown/pluginutils@1.0.0-beta.23':
+ resolution: {integrity: sha512-lLCP4LUecUGBLq8EfkbY2esGYyvZj5ee+WZG12+mVnQH48b46SVbwp+0vJkD+6Pnsc+u9SWarBV9sQ5mVwmb5g==}
- '@rollup/rollup-android-arm-eabi@4.17.2':
- resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==}
+ '@rollup/rollup-android-arm-eabi@4.44.1':
+ resolution: {integrity: sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w==}
cpu: [arm]
os: [android]
- '@rollup/rollup-android-arm64@4.17.2':
- resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==}
+ '@rollup/rollup-android-arm64@4.44.1':
+ resolution: {integrity: sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ==}
cpu: [arm64]
os: [android]
- '@rollup/rollup-darwin-arm64@4.17.2':
- resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==}
+ '@rollup/rollup-darwin-arm64@4.44.1':
+ resolution: {integrity: sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg==}
cpu: [arm64]
os: [darwin]
- '@rollup/rollup-darwin-x64@4.17.2':
- resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==}
+ '@rollup/rollup-darwin-x64@4.44.1':
+ resolution: {integrity: sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw==}
cpu: [x64]
os: [darwin]
- '@rollup/rollup-linux-arm-gnueabihf@4.17.2':
- resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==}
+ '@rollup/rollup-freebsd-arm64@4.44.1':
+ resolution: {integrity: sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.44.1':
+ resolution: {integrity: sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.44.1':
+ resolution: {integrity: sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ==}
cpu: [arm]
os: [linux]
- '@rollup/rollup-linux-arm-musleabihf@4.17.2':
- resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==}
+ '@rollup/rollup-linux-arm-musleabihf@4.44.1':
+ resolution: {integrity: sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw==}
cpu: [arm]
os: [linux]
- '@rollup/rollup-linux-arm64-gnu@4.17.2':
- resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==}
+ '@rollup/rollup-linux-arm64-gnu@4.44.1':
+ resolution: {integrity: sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ==}
cpu: [arm64]
os: [linux]
- '@rollup/rollup-linux-arm64-musl@4.17.2':
- resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==}
+ '@rollup/rollup-linux-arm64-musl@4.44.1':
+ resolution: {integrity: sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g==}
cpu: [arm64]
os: [linux]
- '@rollup/rollup-linux-powerpc64le-gnu@4.17.2':
- resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==}
+ '@rollup/rollup-linux-loongarch64-gnu@4.44.1':
+ resolution: {integrity: sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew==}
+ cpu: [loong64]
+ os: [linux]
+
+ '@rollup/rollup-linux-powerpc64le-gnu@4.44.1':
+ resolution: {integrity: sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA==}
cpu: [ppc64]
os: [linux]
- '@rollup/rollup-linux-riscv64-gnu@4.17.2':
- resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==}
+ '@rollup/rollup-linux-riscv64-gnu@4.44.1':
+ resolution: {integrity: sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw==}
cpu: [riscv64]
os: [linux]
- '@rollup/rollup-linux-s390x-gnu@4.17.2':
- resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==}
+ '@rollup/rollup-linux-riscv64-musl@4.44.1':
+ resolution: {integrity: sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-s390x-gnu@4.44.1':
+ resolution: {integrity: sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw==}
cpu: [s390x]
os: [linux]
- '@rollup/rollup-linux-x64-gnu@4.17.2':
- resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==}
+ '@rollup/rollup-linux-x64-gnu@4.44.1':
+ resolution: {integrity: sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw==}
cpu: [x64]
os: [linux]
- '@rollup/rollup-linux-x64-musl@4.17.2':
- resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==}
+ '@rollup/rollup-linux-x64-musl@4.44.1':
+ resolution: {integrity: sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g==}
cpu: [x64]
os: [linux]
- '@rollup/rollup-win32-arm64-msvc@4.17.2':
- resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==}
+ '@rollup/rollup-win32-arm64-msvc@4.44.1':
+ resolution: {integrity: sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg==}
cpu: [arm64]
os: [win32]
- '@rollup/rollup-win32-ia32-msvc@4.17.2':
- resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==}
+ '@rollup/rollup-win32-ia32-msvc@4.44.1':
+ resolution: {integrity: sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A==}
cpu: [ia32]
os: [win32]
- '@rollup/rollup-win32-x64-msvc@4.17.2':
- resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==}
+ '@rollup/rollup-win32-x64-msvc@4.44.1':
+ resolution: {integrity: sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug==}
cpu: [x64]
os: [win32]
- '@rushstack/eslint-patch@1.10.3':
- resolution: {integrity: sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==}
-
- '@sinclair/typebox@0.27.8':
- resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
-
'@sindresorhus/is@5.6.0':
resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==}
engines: {node: '>=14.16'}
- '@sindresorhus/merge-streams@2.3.0':
- resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==}
- engines: {node: '>=18'}
+ '@stylistic/eslint-plugin@2.11.0':
+ resolution: {integrity: sha512-PNRHbydNG5EH8NK4c+izdJlxajIR6GxcUhzsYNRsn6Myep4dsZt0qFCz3rCPnkvgO5FYibDcMqgNHUT+zvjYZw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: '>=8.40.0'
'@szmarczak/http-timer@5.0.1':
resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==}
resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==}
engines: {node: '>= 6'}
- '@tootallnate/quickjs-emscripten@0.23.0':
- resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==}
-
- '@ts-morph/common@0.23.0':
- resolution: {integrity: sha512-m7Lllj9n/S6sOkCkRftpM7L24uvmfXQFedlW/4hENcuJH1HHm9u5EgxZb9uVjQSCGrbBWBkOGgcTxNg36r6ywA==}
+ '@ts-morph/common@0.27.0':
+ resolution: {integrity: sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ==}
'@tsconfig/node10@1.0.11':
resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==}
'@tsconfig/node16@1.0.4':
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
- '@tsconfig/node20@20.1.4':
- resolution: {integrity: sha512-sqgsT69YFeLWf5NtJ4Xq/xAF8p4ZQHlmGW74Nu2tD4+g5fAsposc4ZfaaPixVu4y01BEiDCWLRDCvDM5JOsRxg==}
+ '@tsconfig/node22@22.0.2':
+ resolution: {integrity: sha512-Kmwj4u8sDRDrMYRoN9FDEcXD8UpBSaPQQ24Gz+Gamqfm7xxn+GBR7ge/Z7pK8OXNGyUzbSwJj+TH6B+DS/epyA==}
+
+ '@tybys/wasm-util@0.9.0':
+ resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==}
- '@types/conventional-commits-parser@5.0.0':
- resolution: {integrity: sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==}
+ '@types/chai@5.2.2':
+ resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==}
- '@types/eslint@8.56.10':
- resolution: {integrity: sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==}
+ '@types/conventional-commits-parser@5.0.1':
+ resolution: {integrity: sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==}
- '@types/estree@1.0.5':
- resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
+ '@types/deep-eql@4.0.2':
+ resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
- '@types/geojson@7946.0.14':
- resolution: {integrity: sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==}
+ '@types/estree@1.0.8':
+ resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+
+ '@types/geojson@7946.0.16':
+ resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==}
'@types/http-cache-semantics@4.0.4':
resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==}
'@types/istanbul-lib-coverage@2.0.6':
resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
- '@types/istanbul-lib-report@3.0.3':
- resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==}
-
- '@types/istanbul-reports@3.0.4':
- resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==}
-
- '@types/jsdom@21.1.6':
- resolution: {integrity: sha512-/7kkMsC+/kMs7gAYmmBR9P0vGTnOoLhQhyhQJSlXGI5bzTHp6xdo0TtKWQAsz6pmSAeVqKSbqeyP6hytqr9FDw==}
+ '@types/jsdom@21.1.7':
+ resolution: {integrity: sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==}
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
- '@types/json5@0.0.29':
- resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
-
'@types/long@4.0.2':
resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==}
- '@types/node@20.12.12':
- resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==}
+ '@types/node@22.16.0':
+ resolution: {integrity: sha512-B2egV9wALML1JCpv3VQoQ+yesQKAmNMBIAY7OteVrikcOcAkWm+dGL6qpeCktPjAv6N1JLnhbNiqS35UpFyBsQ==}
+
+ '@types/node@24.0.10':
+ resolution: {integrity: sha512-ENHwaH+JIRTDIEEbDK6QSQntAYGtbvdDXnMXnZaZ6k13Du1dPMmprkEHIL7ok2Wl2aZevetwTAb5S+7yIF+enA==}
'@types/offscreencanvas@2019.3.0':
resolution: {integrity: sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q==}
'@types/seedrandom@2.4.34':
resolution: {integrity: sha512-ytDiArvrn/3Xk6/vtylys5tlY6eo7Ane0hvcx++TKo6RxQXuVfW0AF/oeWqAj9dN29SyhtawuXstgmPlwNcv/A==}
- '@types/semver@7.5.8':
- resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==}
-
- '@types/stack-utils@2.0.3':
- resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==}
+ '@types/semver@7.7.0':
+ resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==}
'@types/tough-cookie@4.0.5':
resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==}
'@types/whatwg-url@11.0.5':
resolution: {integrity: sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==}
- '@types/ws@8.5.10':
- resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==}
+ '@types/ws@8.18.1':
+ resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}
- '@types/yargs-parser@21.0.3':
- resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
-
- '@types/yargs@17.0.32':
- resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==}
+ '@typescript-eslint/eslint-plugin@8.35.1':
+ resolution: {integrity: sha512-9XNTlo7P7RJxbVeICaIIIEipqxLKguyh+3UbXuT2XQuFp6d8VOeDEGuz5IiX0dgZo8CiI6aOFLg4e8cF71SFVg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ '@typescript-eslint/parser': ^8.35.1
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/eslint-plugin@7.10.0':
- resolution: {integrity: sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==}
- engines: {node: ^18.18.0 || >=20.0.0}
+ '@typescript-eslint/parser@8.35.1':
+ resolution: {integrity: sha512-3MyiDfrfLeK06bi/g9DqJxP5pV74LNv4rFTyvGDmT3x2p1yp1lOd+qYZfiRPIOf/oON+WRZR5wxxuF85qOar+w==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- '@typescript-eslint/parser': ^7.0.0
- eslint: ^8.56.0
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/parser@7.10.0':
- resolution: {integrity: sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w==}
- engines: {node: ^18.18.0 || >=20.0.0}
+ '@typescript-eslint/project-service@8.35.1':
+ resolution: {integrity: sha512-VYxn/5LOpVxADAuP3NrnxxHYfzVtQzLKeldIhDhzC8UHaiQvYlXvKuVho1qLduFbJjjy5U5bkGwa3rUGUb1Q6Q==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- eslint: ^8.56.0
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
+ typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/scope-manager@7.10.0':
- resolution: {integrity: sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==}
- engines: {node: ^18.18.0 || >=20.0.0}
+ '@typescript-eslint/scope-manager@8.35.1':
+ resolution: {integrity: sha512-s/Bpd4i7ht2934nG+UoSPlYXd08KYz3bmjLEb7Ye1UVob0d1ENiT3lY8bsCmik4RqfSbPw9xJJHbugpPpP5JUg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/type-utils@7.10.0':
- resolution: {integrity: sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g==}
- engines: {node: ^18.18.0 || >=20.0.0}
+ '@typescript-eslint/tsconfig-utils@8.35.1':
+ resolution: {integrity: sha512-K5/U9VmT9dTHoNowWZpz+/TObS3xqC5h0xAIjXPw+MNcKV9qg6eSatEnmeAwkjHijhACH0/N7bkhKvbt1+DXWQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- eslint: ^8.56.0
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
+ typescript: '>=4.8.4 <5.9.0'
+
+ '@typescript-eslint/type-utils@8.35.1':
+ resolution: {integrity: sha512-HOrUBlfVRz5W2LIKpXzZoy6VTZzMu2n8q9C2V/cFngIC5U1nStJgv0tMV4sZPzdf4wQm9/ToWUFPMN9Vq9VJQQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/types@7.10.0':
- resolution: {integrity: sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==}
- engines: {node: ^18.18.0 || >=20.0.0}
+ '@typescript-eslint/types@8.35.1':
+ resolution: {integrity: sha512-q/O04vVnKHfrrhNAscndAn1tuQhIkwqnaW+eu5waD5IPts2eX1dgJxgqcPx5BX109/qAz7IG6VrEPTOYKCNfRQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/typescript-estree@7.10.0':
- resolution: {integrity: sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==}
- engines: {node: ^18.18.0 || >=20.0.0}
+ '@typescript-eslint/typescript-estree@8.35.1':
+ resolution: {integrity: sha512-Vvpuvj4tBxIka7cPs6Y1uvM7gJgdF5Uu9F+mBJBPY4MhvjrjWGK4H0lVgLJd/8PWZ23FTqsaJaLEkBCFUk8Y9g==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
+ typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/utils@7.10.0':
- resolution: {integrity: sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==}
- engines: {node: ^18.18.0 || >=20.0.0}
+ '@typescript-eslint/utils@8.35.1':
+ resolution: {integrity: sha512-lhnwatFmOFcazAsUm3ZnZFpXSxiwoa1Lj50HphnDe1Et01NF4+hrdXONSUHIcbVu2eFb1bAf+5yjXkGVkXBKAQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- eslint: ^8.56.0
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <5.9.0'
+
+ '@typescript-eslint/visitor-keys@8.35.1':
+ resolution: {integrity: sha512-VRwixir4zBWCSTP/ljEo091lbpypz57PoeAQ9imjG+vbeof9LplljsL1mos4ccG6H9IjfrVGM359RozUnuFhpw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/visitor-keys@7.10.0':
- resolution: {integrity: sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==}
- engines: {node: ^18.18.0 || >=20.0.0}
+ '@unrs/resolver-binding-android-arm-eabi@1.10.1':
+ resolution: {integrity: sha512-zohDKXT1Ok0yhbVGff4YAg9HUs5ietG5GpvJBPFSApZnGe7uf2cd26DRhKZbn0Be6xHUZrSzP+RAgMmzyc71EA==}
+ cpu: [arm]
+ os: [android]
- '@ungap/structured-clone@1.2.0':
- resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
+ '@unrs/resolver-binding-android-arm64@1.10.1':
+ resolution: {integrity: sha512-tAN6k5UrTd4nicpA7s2PbjR/jagpDzAmvXFjbpTazUe5FRsFxVcBlS1F5Lzp5jtWU6bdiqRhSvd4X8rdpCffeA==}
+ cpu: [arm64]
+ os: [android]
- '@vitejs/plugin-vue-jsx@3.1.0':
- resolution: {integrity: sha512-w9M6F3LSEU5kszVb9An2/MmXNxocAnUb3WhRr8bHlimhDrXNt6n6D2nJQR3UXpGlZHh/EsgouOHCsM8V3Ln+WA==}
- engines: {node: ^14.18.0 || >=16.0.0}
+ '@unrs/resolver-binding-darwin-arm64@1.10.1':
+ resolution: {integrity: sha512-+FCsag8WkauI4dQ50XumCXdfvDCZEpMUnvZDsKMxfOisnEklpDFXc6ThY0WqybBYZbiwR5tWcFaZmI0G6b4vrg==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@unrs/resolver-binding-darwin-x64@1.10.1':
+ resolution: {integrity: sha512-qYKGGm5wk71ONcXTMZ0+J11qQeOAPz3nw6VtqrBUUELRyXFyvK8cHhHsLBFR4GHnilc2pgY1HTB2TvdW9wO26Q==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@unrs/resolver-binding-freebsd-x64@1.10.1':
+ resolution: {integrity: sha512-hOHMAhbvIQ63gkpgeNsXcWPSyvXH7ZEyeg254hY0Lp/hX8NdW+FsUWq73g9946Pc/BrcVI/I3C1cmZ4RCX9bNw==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@unrs/resolver-binding-linux-arm-gnueabihf@1.10.1':
+ resolution: {integrity: sha512-6ds7+zzHJgTDmpe0gmFcOTvSUhG5oZukkt+cCsSb3k4Uiz2yEQB4iCRITX2hBwSW+p8gAieAfecITjgqCkswXw==}
+ cpu: [arm]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-arm-musleabihf@1.10.1':
+ resolution: {integrity: sha512-P7A0G2/jW00diNJyFeq4W9/nxovD62Ay8CMP4UK9OymC7qO7rG1a8Upad68/bdfpIOn7KSp7Aj/6lEW3yyznAA==}
+ cpu: [arm]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-arm64-gnu@1.10.1':
+ resolution: {integrity: sha512-Cg6xzdkrpltcTPO4At+A79zkC7gPDQIgosJmVV8M104ImB6KZi1MrNXgDYIAfkhUYjPzjNooEDFRAwwPadS7ZA==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-arm64-musl@1.10.1':
+ resolution: {integrity: sha512-aNeg99bVkXa4lt+oZbjNRPC8ZpjJTKxijg/wILrJdzNyAymO2UC/HUK1UfDjt6T7U5p/mK24T3CYOi3/+YEQSA==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-ppc64-gnu@1.10.1':
+ resolution: {integrity: sha512-ylz5ojeXrkPrtnzVhpCO+YegG63/aKhkoTlY8PfMfBfLaUG8v6m6iqrL7sBUKdVBgOB4kSTUPt9efQdA/Y3Z/w==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-riscv64-gnu@1.10.1':
+ resolution: {integrity: sha512-xcWyhmJfXXOxK7lvE4+rLwBq+on83svlc0AIypfe6x4sMJR+S4oD7n9OynaQShfj2SufPw2KJAotnsNb+4nN2g==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-riscv64-musl@1.10.1':
+ resolution: {integrity: sha512-mW9JZAdOCyorgi1eLJr4gX7xS67WNG9XNPYj5P8VuttK72XNsmdw9yhOO4tDANMgiLXFiSFaiL1gEpoNtRPw/A==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-s390x-gnu@1.10.1':
+ resolution: {integrity: sha512-NZGKhBy6xkJ0k09cWNZz4DnhBcGlhDd3W+j7EYoNvf5TSwj2K6kbmfqTWITEgkvjsMUjm1wsrc4IJaH6VtjyHQ==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-x64-gnu@1.10.1':
+ resolution: {integrity: sha512-VsjgckJ0gNMw7p0d8In6uPYr+s0p16yrT2rvG4v2jUpEMYkpnfnCiALa9SWshbvlGjKQ98Q2x19agm3iFk8w8Q==}
+ cpu: [x64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-x64-musl@1.10.1':
+ resolution: {integrity: sha512-idMnajMeejnaFi0Mx9UTLSYFDAOTfAEP7VjXNgxKApso3Eu2Njs0p2V95nNIyFi4oQVGFmIuCkoznAXtF/Zbmw==}
+ cpu: [x64]
+ os: [linux]
+
+ '@unrs/resolver-binding-wasm32-wasi@1.10.1':
+ resolution: {integrity: sha512-7jyhjIRNFjzlr8x5pth6Oi9hv3a7ubcVYm2GBFinkBQKcFhw4nIs5BtauSNtDW1dPIGrxF0ciynCZqzxMrYMsg==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+
+ '@unrs/resolver-binding-win32-arm64-msvc@1.10.1':
+ resolution: {integrity: sha512-TY79+N+Gkoo7E99K+zmsKNeiuNJYlclZJtKqsHSls8We2iGhgxtletVsiBYie93MSTDRDMI8pkBZJlIJSZPrdA==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@unrs/resolver-binding-win32-ia32-msvc@1.10.1':
+ resolution: {integrity: sha512-BAJN5PEPlEV+1m8+PCtFoKm3LQ1P57B4Z+0+efU0NzmCaGk7pUaOxuPgl+m3eufVeeNBKiPDltG0sSB9qEfCxw==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@unrs/resolver-binding-win32-x64-msvc@1.10.1':
+ resolution: {integrity: sha512-2v3erKKmmCyIVvvhI2nF15qEbdBpISTq44m9pyd5gfIJB1PN94oePTLWEd82XUbIbvKhv76xTSeUQSCOGesLeg==}
+ cpu: [x64]
+ os: [win32]
+
+ '@vitejs/plugin-vue-jsx@5.0.1':
+ resolution: {integrity: sha512-X7qmQMXbdDh+sfHUttXokPD0cjPkMFoae7SgbkF9vi3idGUKmxLcnU2Ug49FHwiKXebfzQRIm5yK3sfCJzNBbg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
peerDependencies:
- vite: ^4.0.0 || ^5.0.0
+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0
vue: ^3.0.0
- '@vitejs/plugin-vue@5.0.4':
- resolution: {integrity: sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==}
- engines: {node: ^18.0.0 || >=20.0.0}
+ '@vitejs/plugin-vue@6.0.0':
+ resolution: {integrity: sha512-iAliE72WsdhjzTOp2DtvKThq1VBC4REhwRcaA+zPAAph6I+OQhUXv+Xu2KS7ElxYtb7Zc/3R30Hwv1DxEo7NXQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
peerDependencies:
- vite: ^5.0.0
+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0
vue: ^3.2.25
- '@vitest/coverage-v8@1.6.0':
- resolution: {integrity: sha512-KvapcbMY/8GYIG0rlwwOKCVNRc0OL20rrhFkg/CHNzncV03TE2XWvO5w9uZYoxNiMEBacAJt3unSOiZ7svePew==}
+ '@vitest/coverage-v8@3.2.4':
+ resolution: {integrity: sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==}
+ peerDependencies:
+ '@vitest/browser': 3.2.4
+ vitest: 3.2.4
+ peerDependenciesMeta:
+ '@vitest/browser':
+ optional: true
+
+ '@vitest/expect@3.2.4':
+ resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==}
+
+ '@vitest/mocker@3.2.4':
+ resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==}
peerDependencies:
- vitest: 1.6.0
+ msw: ^2.4.9
+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0
+ peerDependenciesMeta:
+ msw:
+ optional: true
+ vite:
+ optional: true
- '@vitest/expect@1.6.0':
- resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==}
+ '@vitest/pretty-format@3.2.4':
+ resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==}
- '@vitest/runner@1.6.0':
- resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==}
+ '@vitest/runner@3.2.4':
+ resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==}
- '@vitest/snapshot@1.6.0':
- resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==}
+ '@vitest/snapshot@3.2.4':
+ resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==}
- '@vitest/spy@1.6.0':
- resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==}
+ '@vitest/spy@3.2.4':
+ resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==}
- '@vitest/utils@1.6.0':
- resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==}
+ '@vitest/utils@3.2.4':
+ resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==}
- '@vue/babel-helper-vue-transform-on@1.2.2':
- resolution: {integrity: sha512-nOttamHUR3YzdEqdM/XXDyCSdxMA9VizUKoroLX6yTyRtggzQMHXcmwh8a7ZErcJttIBIc9s68a1B8GZ+Dmvsw==}
+ '@vue/babel-helper-vue-transform-on@1.4.0':
+ resolution: {integrity: sha512-mCokbouEQ/ocRce/FpKCRItGo+013tHg7tixg3DUNS+6bmIchPt66012kBMm476vyEIJPafrvOf4E5OYj3shSw==}
- '@vue/babel-plugin-jsx@1.2.2':
- resolution: {integrity: sha512-nYTkZUVTu4nhP199UoORePsql0l+wj7v/oyQjtThUVhJl1U+6qHuoVhIvR3bf7eVKjbCK+Cs2AWd7mi9Mpz9rA==}
+ '@vue/babel-plugin-jsx@1.4.0':
+ resolution: {integrity: sha512-9zAHmwgMWlaN6qRKdrg1uKsBKHvnUU+Py+MOCTuYZBoZsopa90Di10QRjB+YPnVss0BZbG/H5XFwJY1fTxJWhA==}
peerDependencies:
'@babel/core': ^7.0.0-0
peerDependenciesMeta:
'@babel/core':
optional: true
- '@vue/babel-plugin-resolve-type@1.2.2':
- resolution: {integrity: sha512-EntyroPwNg5IPVdUJupqs0CFzuf6lUrVvCspmv2J1FITLeGnUCuoGNNk78dgCusxEiYj6RMkTJflGSxk5aIC4A==}
+ '@vue/babel-plugin-resolve-type@1.4.0':
+ resolution: {integrity: sha512-4xqDRRbQQEWHQyjlYSgZsWj44KfiF6D+ktCuXyZ8EnVDYV3pztmXJDf1HveAjUAXxAnR8daCQT51RneWWxtTyQ==}
peerDependencies:
'@babel/core': ^7.0.0-0
- '@vue/compiler-core@3.4.27':
- resolution: {integrity: sha512-E+RyqY24KnyDXsCuQrI+mlcdW3ALND6U7Gqa/+bVwbcpcR3BRRIckFoz7Qyd4TTlnugtwuI7YgjbvsLmxb+yvg==}
-
- '@vue/compiler-dom@3.4.27':
- resolution: {integrity: sha512-kUTvochG/oVgE1w5ViSr3KUBh9X7CWirebA3bezTbB5ZKBQZwR2Mwj9uoSKRMFcz4gSMzzLXBPD6KpCLb9nvWw==}
+ '@vue/compiler-core@3.5.17':
+ resolution: {integrity: sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA==}
- '@vue/compiler-sfc@3.4.27':
- resolution: {integrity: sha512-nDwntUEADssW8e0rrmE0+OrONwmRlegDA1pD6QhVeXxjIytV03yDqTey9SBDiALsvAd5U4ZrEKbMyVXhX6mCGA==}
+ '@vue/compiler-dom@3.5.17':
+ resolution: {integrity: sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ==}
- '@vue/compiler-ssr@3.4.27':
- resolution: {integrity: sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==}
+ '@vue/compiler-sfc@3.5.17':
+ resolution: {integrity: sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww==}
- '@vue/devtools-api@6.6.1':
- resolution: {integrity: sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==}
-
- '@vue/eslint-config-prettier@9.0.0':
- resolution: {integrity: sha512-z1ZIAAUS9pKzo/ANEfd2sO+v2IUalz7cM/cTLOZ7vRFOPk5/xuRKQteOu1DErFLAh/lYGXMVZ0IfYKlyInuDVg==}
- peerDependencies:
- eslint: '>= 8.0.0'
- prettier: '>= 3.0.0'
+ '@vue/compiler-ssr@3.5.17':
+ resolution: {integrity: sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ==}
- '@vue/eslint-config-typescript@13.0.0':
- resolution: {integrity: sha512-MHh9SncG/sfqjVqjcuFLOLD6Ed4dRAis4HNt0dXASeAuLqIAx4YMB1/m2o4pUKK1vCt8fUvYG8KKX2Ot3BVZTg==}
- engines: {node: ^18.18.0 || >=20.0.0}
- peerDependencies:
- eslint: ^8.56.0
- eslint-plugin-vue: ^9.0.0
- typescript: '>=4.7.4'
- peerDependenciesMeta:
- typescript:
- optional: true
+ '@vue/devtools-api@6.6.4':
+ resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==}
- '@vue/reactivity@3.4.27':
- resolution: {integrity: sha512-kK0g4NknW6JX2yySLpsm2jlunZJl2/RJGZ0H9ddHdfBVHcNzxmQ0sS0b09ipmBoQpY8JM2KmUw+a6sO8Zo+zIA==}
+ '@vue/reactivity@3.5.17':
+ resolution: {integrity: sha512-l/rmw2STIscWi7SNJp708FK4Kofs97zc/5aEPQh4bOsReD/8ICuBcEmS7KGwDj5ODQLYWVN2lNibKJL1z5b+Lw==}
- '@vue/runtime-core@3.4.27':
- resolution: {integrity: sha512-7aYA9GEbOOdviqVvcuweTLe5Za4qBZkUY7SvET6vE8kyypxVgaT1ixHLg4urtOlrApdgcdgHoTZCUuTGap/5WA==}
+ '@vue/runtime-core@3.5.17':
+ resolution: {integrity: sha512-QQLXa20dHg1R0ri4bjKeGFKEkJA7MMBxrKo2G+gJikmumRS7PTD4BOU9FKrDQWMKowz7frJJGqBffYMgQYS96Q==}
- '@vue/runtime-dom@3.4.27':
- resolution: {integrity: sha512-ScOmP70/3NPM+TW9hvVAz6VWWtZJqkbdf7w6ySsws+EsqtHvkhxaWLecrTorFxsawelM5Ys9FnDEMt6BPBDS0Q==}
+ '@vue/runtime-dom@3.5.17':
+ resolution: {integrity: sha512-8El0M60TcwZ1QMz4/os2MdlQECgGoVHPuLnQBU3m9h3gdNRW9xRmI8iLS4t/22OQlOE6aJvNNlBiCzPHur4H9g==}
- '@vue/server-renderer@3.4.27':
- resolution: {integrity: sha512-dlAMEuvmeA3rJsOMJ2J1kXU7o7pOxgsNHVr9K8hB3ImIkSuBrIdy0vF66h8gf8Tuinf1TK3mPAz2+2sqyf3KzA==}
+ '@vue/server-renderer@3.5.17':
+ resolution: {integrity: sha512-BOHhm8HalujY6lmC3DbqF6uXN/K00uWiEeF22LfEsm9Q93XeJ/plHTepGwf6tqFcF7GA5oGSSAAUock3VvzaCA==}
peerDependencies:
- vue: 3.4.27
+ vue: 3.5.17
- '@vue/shared@3.4.27':
- resolution: {integrity: sha512-DL3NmY2OFlqmYYrzp39yi3LDkKxa5vZVwxWdQ3rG0ekuWscHraeIbnI8t+aZK7qhYqEqWKTUdijadunb9pnrgA==}
+ '@vue/shared@3.5.17':
+ resolution: {integrity: sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==}
'@vue/test-utils@2.4.6':
resolution: {integrity: sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==}
- '@vue/tsconfig@0.5.1':
- resolution: {integrity: sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==}
+ '@vue/tsconfig@0.7.0':
+ resolution: {integrity: sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg==}
+ peerDependencies:
+ typescript: 5.x
+ vue: ^3.4.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ vue:
+ optional: true
'@webgpu/types@0.1.16':
resolution: {integrity: sha512-9E61voMP4+Rze02jlTXud++Htpjyyk8vw5Hyw9FGRrmhHQg2GqbuOfwf5Klrb8vTxc2XWI3EfO7RUHMpxTj26A==}
resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==}
engines: {node: '>=0.4.0'}
- acorn-walk@8.3.2:
- resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==}
+ acorn-walk@8.3.4:
+ resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==}
engines: {node: '>=0.4.0'}
acorn@7.4.1:
engines: {node: '>=0.4.0'}
hasBin: true
- acorn@8.11.3:
- resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==}
+ acorn@8.15.0:
+ resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
engines: {node: '>=0.4.0'}
hasBin: true
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
engines: {node: '>= 6.0.0'}
- agent-base@7.1.1:
- resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==}
+ agent-base@7.1.3:
+ resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==}
engines: {node: '>= 14'}
- agentkeepalive@4.5.0:
- resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==}
+ agentkeepalive@4.6.0:
+ resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==}
engines: {node: '>= 8.0.0'}
aggregate-error@3.1.0:
ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
- ajv@8.13.0:
- resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==}
+ ajv@8.17.1:
+ resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==}
ansi-align@3.0.1:
resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==}
resolution: {integrity: sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==}
engines: {node: '>=4'}
- ansi-escapes@4.3.2:
- resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
- engines: {node: '>=8'}
-
- ansi-escapes@6.2.1:
- resolution: {integrity: sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==}
- engines: {node: '>=14.16'}
+ ansi-escapes@7.0.0:
+ resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==}
+ engines: {node: '>=18'}
ansi-regex@2.1.1:
resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==}
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
- ansi-regex@6.0.1:
- resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
+ ansi-regex@6.1.0:
+ resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==}
engines: {node: '>=12'}
ansi-styles@2.2.1:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
- ansi-styles@5.2.0:
- resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
- engines: {node: '>=10'}
-
ansi-styles@6.2.1:
resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
engines: {node: '>=12'}
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
- array-buffer-byte-length@1.0.1:
- resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==}
+ array-buffer-byte-length@1.0.2:
+ resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==}
engines: {node: '>= 0.4'}
array-flatten@3.0.0:
array-ify@1.0.0:
resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==}
- array-includes@3.1.8:
- resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==}
+ array-includes@3.1.9:
+ resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==}
engines: {node: '>= 0.4'}
+ array-timsort@1.0.3:
+ resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==}
+
array-union@2.1.0:
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
engines: {node: '>=8'}
- array.prototype.findlastindex@1.2.5:
- resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==}
+ array.prototype.findlast@1.2.5:
+ resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==}
engines: {node: '>= 0.4'}
- array.prototype.flat@1.3.2:
- resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==}
+ array.prototype.flat@1.3.3:
+ resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==}
engines: {node: '>= 0.4'}
- array.prototype.flatmap@1.3.2:
- resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==}
+ array.prototype.flatmap@1.3.3:
+ resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==}
engines: {node: '>= 0.4'}
- array.prototype.map@1.0.7:
- resolution: {integrity: sha512-XpcFfLoBEAhezrrNw1V+yLXkE7M6uR7xJEsxbG6c/V9v043qurwVJB9r9UTnoSioFDoz1i1VOydpWGmJpfVZbg==}
+ array.prototype.tosorted@1.1.4:
+ resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==}
engines: {node: '>= 0.4'}
- arraybuffer.prototype.slice@1.0.3:
- resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==}
+ arraybuffer.prototype.slice@1.0.4:
+ resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
engines: {node: '>= 0.4'}
asn1.js@4.10.1:
assert@1.5.1:
resolution: {integrity: sha512-zzw1uCAgLbsKwBfFc8CX78DDg+xZeBksSO3vwVIDDN5i94eOrPsSSyiVhmsSABFDM/OcpE2aagCat9dnWQLG1A==}
- assertion-error@1.1.0:
- resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
+ assertion-error@2.0.1:
+ resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
+ engines: {node: '>=12'}
- ast-types@0.13.4:
- resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==}
- engines: {node: '>=4'}
+ ast-v8-to-istanbul@0.3.3:
+ resolution: {integrity: sha512-MuXMrSLVVoA6sYN/6Hke18vMzrT4TZNbZIj/hvh0fnYFpO+/kFXcLIaiPwXXWaQUPg4yJD8fj+lfJ7/1EBconw==}
- async-retry@1.3.3:
- resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==}
+ async-function@1.0.0:
+ resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
+ engines: {node: '>= 0.4'}
async@2.6.4:
resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==}
- async@3.2.5:
- resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==}
+ async@3.2.6:
+ resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==}
asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
resolution: {integrity: sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==}
engines: {node: '>=10.12.0'}
- auto-changelog@2.4.0:
- resolution: {integrity: sha512-vh17hko1c0ItsEcw6m7qPRf3m45u+XK5QyCrrBFViElZ8jnKrPC1roSznrd1fIB/0vR/zawdECCRJtTuqIXaJw==}
- engines: {node: '>=8.3'}
- hasBin: true
-
autocannon@7.15.0:
resolution: {integrity: sha512-NaP2rQyA+tcubOJMFv2+oeW9jv2pq/t+LM6BL3cfJic0HEfscEcnWgAyU5YovE/oTHUzAgTliGdLPR+RQAWUbg==}
hasBin: true
aws-sign2@0.7.0:
resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==}
- aws4@1.13.0:
- resolution: {integrity: sha512-3AungXC4I8kKsS9PuS4JH2nc+0bVY/mjgrephHTIi8fpEeGsTHBUJeosp0Wc1myYMElmD0B3Oc4XL/HVJ4PV2g==}
+ aws4@1.13.2:
+ resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==}
- b4a@1.6.6:
- resolution: {integrity: sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==}
+ b4a@1.6.7:
+ resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==}
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
bcrypt-pbkdf@1.0.2:
resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==}
- before-after-hook@2.2.3:
- resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
-
binary-extensions@2.3.0:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
bl@4.1.0:
resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
- bn.js@4.12.0:
- resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==}
+ bn.js@4.12.2:
+ resolution: {integrity: sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==}
- bn.js@5.2.1:
- resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==}
+ bn.js@5.2.2:
+ resolution: {integrity: sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==}
boolbase@1.0.0:
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==}
engines: {node: '>=10'}
- boxen@7.1.1:
- resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==}
- engines: {node: '>=14.16'}
-
- brace-expansion@1.1.11:
- resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+ brace-expansion@1.1.12:
+ resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
- brace-expansion@2.0.1:
- resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+ brace-expansion@2.0.2:
+ resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
braces@3.0.3:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
browserify-des@1.0.2:
resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==}
- browserify-rsa@4.1.0:
- resolution: {integrity: sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==}
+ browserify-rsa@4.1.1:
+ resolution: {integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==}
+ engines: {node: '>= 0.10'}
browserify-sign@4.2.3:
resolution: {integrity: sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==}
browserify-zlib@0.2.0:
resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==}
- browserify@17.0.0:
- resolution: {integrity: sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==}
+ browserify@17.0.1:
+ resolution: {integrity: sha512-pxhT00W3ylMhCHwG5yfqtZjNnFuX5h2IJdaBfSo4ChaaBsIp9VLrEMQ1bHV+Xr1uLPXuNDDM1GlJkjli0qkRsw==}
engines: {node: '>= 0.8'}
hasBin: true
- browserslist@4.23.0:
- resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==}
+ browserslist@4.25.1:
+ resolution: {integrity: sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
- bson@6.7.0:
- resolution: {integrity: sha512-w2IquM5mYzYZv6rs3uN2DZTOBe2a0zXLj53TGDqwF4l6Sz/XsISrisXOJihArF9+BZ6Cq/GjVht7Sjfmri7ytQ==}
+ bson@6.10.4:
+ resolution: {integrity: sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==}
engines: {node: '>=16.20.1'}
buffer-equal@0.0.1:
buffer@5.7.1:
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
- bufferutil@4.0.8:
- resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==}
+ bufferutil@4.0.9:
+ resolution: {integrity: sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw==}
engines: {node: '>=6.14.2'}
- builtin-modules@3.3.0:
- resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==}
- engines: {node: '>=6'}
-
builtin-status-codes@3.0.0:
resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==}
- bundle-name@4.1.0:
- resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
+ c8@10.1.3:
+ resolution: {integrity: sha512-LvcyrOAaOnrrlMpW22n690PUvxiq4Uf9WMhQwNJ9vgagkL/ph1+D4uvjvDA5XCbykrc0sx+ay6pVi9YZ1GnhyA==}
engines: {node: '>=18'}
-
- c8@9.1.0:
- resolution: {integrity: sha512-mBWcT5iqNir1zIkzSPyI3NCR9EZCVI3WUD+AVO17MVWTSFNyUueXE82qTeampNtTr+ilN/5Ua3j24LgbCKjDVg==}
- engines: {node: '>=14.14.0'}
hasBin: true
+ peerDependencies:
+ monocart-coverage-reports: ^2
+ peerDependenciesMeta:
+ monocart-coverage-reports:
+ optional: true
cac@6.7.14:
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
cached-path-relative@1.1.0:
resolution: {integrity: sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==}
- call-bind@1.0.7:
- resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==}
+ call-bind-apply-helpers@1.0.2:
+ resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
+ engines: {node: '>= 0.4'}
+
+ call-bind@1.0.8:
+ resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==}
+ engines: {node: '>= 0.4'}
+
+ call-bound@1.0.4:
+ resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
engines: {node: '>= 0.4'}
callsites@3.1.0:
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
engines: {node: '>=10'}
- camelcase@7.0.1:
- resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==}
- engines: {node: '>=14.16'}
-
- caniuse-lite@1.0.30001620:
- resolution: {integrity: sha512-WJvYsOjd1/BYUY6SNGUosK9DUidBPDTnOARHp3fSmFO1ekdxaY6nKRttEVrfMmYi80ctS0kz1wiWmm14fVc3ew==}
+ caniuse-lite@1.0.30001726:
+ resolution: {integrity: sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==}
caseless@0.12.0:
resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==}
cephes@2.0.0:
resolution: {integrity: sha512-4GMUzkcXHZ0HMZ3gZdBrv8pQs1/zkJh2Q9rQOF8NJZHanM359y3XOSdeqmDBPfxQKYQpJt58R3dUpofrIXJ2mg==}
- chai@4.4.1:
- resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==}
- engines: {node: '>=4'}
+ chai@5.2.0:
+ resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==}
+ engines: {node: '>=12'}
chalk@1.1.3:
resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==}
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
- chalk@5.3.0:
- resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==}
+ chalk@5.4.1:
+ resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==}
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
char-spinner@1.0.1:
chardet@0.7.0:
resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
- check-error@1.0.3:
- resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==}
+ check-error@2.1.1:
+ resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==}
+ engines: {node: '>= 16'}
chokidar@3.6.0:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
ci-info@2.0.0:
resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==}
- ci-info@3.9.0:
- resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
- engines: {node: '>=8'}
-
- cipher-base@1.0.4:
- resolution: {integrity: sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==}
+ cipher-base@1.0.6:
+ resolution: {integrity: sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==}
+ engines: {node: '>= 0.10'}
clean-stack@2.2.0:
resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
engines: {node: '>=6'}
+ clear-module@4.1.2:
+ resolution: {integrity: sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==}
+ engines: {node: '>=8'}
+
cli-boxes@2.2.1:
resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==}
engines: {node: '>=6'}
- cli-boxes@3.0.0:
- resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==}
- engines: {node: '>=10'}
-
cli-cursor@2.1.0:
resolution: {integrity: sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==}
engines: {node: '>=4'}
resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
engines: {node: '>=8'}
- cli-cursor@4.0.0:
- resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ cli-cursor@5.0.0:
+ resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==}
+ engines: {node: '>=18'}
cli-spinners@2.9.2:
resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
cli-width@2.2.1:
resolution: {integrity: sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==}
- cli-width@4.1.0:
- resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==}
- engines: {node: '>= 12'}
-
clinic@13.0.0:
resolution: {integrity: sha512-QAD3cLgA1OqEC7fJSDbAt4U0BKGAK1c5yopN5tu1OtmmsbRHHYxBeSMiElQfuMMdbkAuLEE7HOffZ0hKMzaYVw==}
hasBin: true
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
engines: {node: '>=0.8'}
- code-block-writer@13.0.1:
- resolution: {integrity: sha512-c5or4P6erEA69TxaxTNcHUNcIn+oyxSRTOWV+pSYF+z4epXqNvwvJ70XPGjPNgue83oAFAPBRQYwpAJ/Hpe/Sg==}
+ code-block-writer@13.0.3:
+ resolution: {integrity: sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==}
code-point-at@1.1.0:
resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==}
resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
engines: {node: '>=14'}
- commander@11.1.0:
- resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
- engines: {node: '>=16'}
+ commander@14.0.0:
+ resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==}
+ engines: {node: '>=20'}
commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
- commander@7.2.0:
- resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
- engines: {node: '>= 10'}
+ comment-json@4.2.5:
+ resolution: {integrity: sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==}
+ engines: {node: '>= 6'}
comment-parser@1.4.1:
resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==}
resolution: {integrity: sha512-8fLl9F04EJqjSqH+QjITQfJF8BrOVaYr1jewVgSRAEWePfxT0sku4w2hrGQ60BC/TNLGQ2pgxNlTbWQmMPFvXg==}
engines: {node: '>=12'}
- confbox@0.1.7:
- resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==}
-
config-chain@1.1.13:
resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==}
resolution: {integrity: sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==}
engines: {node: '>=8'}
- configstore@6.0.0:
- resolution: {integrity: sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==}
- engines: {node: '>=12'}
-
console-browserify@1.2.0:
resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==}
core-util-is@1.0.3:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
- cosmiconfig-typescript-loader@5.0.0:
- resolution: {integrity: sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==}
- engines: {node: '>=v16'}
+ cosmiconfig-typescript-loader@6.1.0:
+ resolution: {integrity: sha512-tJ1w35ZRUiM5FeTzT7DtYWAFFv37ZLqSRkGi2oeCK1gPhvaWjkAtfXvLmvE1pRfxxp9aQo6ba/Pvg1dKj05D4g==}
+ engines: {node: '>=v18'}
peerDependencies:
'@types/node': '*'
- cosmiconfig: '>=8.2'
- typescript: '>=4'
+ cosmiconfig: '>=9'
+ typescript: '>=5'
cosmiconfig@9.0.0:
resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==}
create-ecdh@4.0.4:
resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==}
+ create-hash@1.1.3:
+ resolution: {integrity: sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==}
+
create-hash@1.2.0:
resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==}
engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'}
hasBin: true
- cross-spawn@7.0.3:
- resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
+ cross-spawn@7.0.6:
+ resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
- crypto-browserify@3.12.0:
- resolution: {integrity: sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==}
+ crypto-browserify@3.12.1:
+ resolution: {integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==}
+ engines: {node: '>= 0.10'}
crypto-random-string@2.0.0:
resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==}
engines: {node: '>=8'}
- crypto-random-string@4.0.0:
- resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==}
- engines: {node: '>=12'}
+ cspell-config-lib@9.1.2:
+ resolution: {integrity: sha512-QvHHGUuMI5h3ymU6O/Qz8zfhMhvPTuopT1FgebYRBB1cyggl4KnEJKU9m7wy/SQ1IGSlFDtQp6rCy70ujTfavQ==}
+ engines: {node: '>=20'}
+
+ cspell-dictionary@9.1.2:
+ resolution: {integrity: sha512-Osn5f9ugkX/zA3PVtSmYKRer3gZX3YqVB0UH0wVNzi8Ryl/1RUuYLIcvd0SDEhiVW56WKxFLfZ5sggTz/l9cDA==}
+ engines: {node: '>=20'}
+
+ cspell-glob@9.1.2:
+ resolution: {integrity: sha512-l7Mqirn5h2tilTXgRamRIqqnzeA7R5iJEtJkY/zHDMEBeLWTR/5ai7dBp2+ooe8gIebpDtvv4938IXa5/75E6g==}
+ engines: {node: '>=20'}
+
+ cspell-grammar@9.1.2:
+ resolution: {integrity: sha512-vUcnlUqJKK0yhwYHfGC71zjGyEn918l64U/NWb1ijn1VXrL6gsh3w8Acwdo++zbpOASd9HTAuuZelveDJKLLgA==}
+ engines: {node: '>=20'}
+ hasBin: true
+
+ cspell-io@9.1.2:
+ resolution: {integrity: sha512-oLPxbteI+uFV9ZPcJjII7Lr/C/gVXpdmDLlAMwR8/7LHGnEfxXR0lqYu5GZVEvZ7riX9whCUOsQWQQqr2u2Fzw==}
+ engines: {node: '>=20'}
+
+ cspell-lib@9.1.2:
+ resolution: {integrity: sha512-OFCssgfp6Z2gd1K8j2FsYr9YGoA/C6xXlcUwgU75Ut/XMZ/S44chdA9fUupGd4dUOw+CZl0qKzSP21J6kYObIw==}
+ engines: {node: '>=20'}
+
+ cspell-trie-lib@9.1.2:
+ resolution: {integrity: sha512-TkIQaknRRusUznqy+HwpqKCETCAznrzPJJHRHi8m6Zo3tAMsnIpaBQPRN8xem6w8/r/yJqFhLrsLSma0swyviQ==}
+ engines: {node: '>=20'}
cssesc@3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'}
hasBin: true
- cssstyle@4.0.1:
- resolution: {integrity: sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==}
+ cssstyle@4.6.0:
+ resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==}
engines: {node: '>=18'}
csstype@3.1.3:
resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==}
engines: {node: '>=0.10'}
- data-uri-to-buffer@4.0.1:
- resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
- engines: {node: '>= 12'}
-
- data-uri-to-buffer@6.0.2:
- resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==}
- engines: {node: '>= 14'}
-
data-urls@5.0.0:
resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==}
engines: {node: '>=18'}
- data-view-buffer@1.0.1:
- resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==}
+ data-view-buffer@1.0.2:
+ resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
engines: {node: '>= 0.4'}
- data-view-byte-length@1.0.1:
- resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==}
+ data-view-byte-length@1.0.2:
+ resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==}
engines: {node: '>= 0.4'}
- data-view-byte-offset@1.0.0:
- resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==}
+ data-view-byte-offset@1.0.1:
+ resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==}
engines: {node: '>= 0.4'}
- dataloader@2.2.2:
- resolution: {integrity: sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==}
+ dataloader@2.2.3:
+ resolution: {integrity: sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA==}
- date-fns@3.6.0:
- resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==}
+ date-fns@4.1.0:
+ resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==}
debounce-fn@4.0.0:
resolution: {integrity: sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==}
debounce@1.2.1:
resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==}
- debug@2.6.9:
- resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
+ debug@3.2.7:
+ resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
- debug@3.2.7:
- resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+ debug@4.3.4:
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
- debug@4.3.4:
- resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ debug@4.4.1:
+ resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==}
engines: {node: '>=6.0'}
peerDependencies:
supports-color: '*'
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
engines: {node: '>=0.10.0'}
- decimal.js@10.4.3:
- resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==}
+ decimal.js@10.5.0:
+ resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==}
decompress-response@6.0.0:
resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
engines: {node: '>=10'}
- deep-eql@4.1.3:
- resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==}
+ deep-eql@5.0.2:
+ resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
engines: {node: '>=6'}
deep-extend@0.6.0:
deep-is@0.1.4:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
- default-browser-id@5.0.0:
- resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==}
- engines: {node: '>=18'}
-
- default-browser@5.2.1:
- resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==}
- engines: {node: '>=18'}
-
defaults@1.0.4:
resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
engines: {node: '>= 0.4'}
- define-lazy-prop@3.0.0:
- resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
- engines: {node: '>=12'}
-
define-properties@1.2.1:
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
engines: {node: '>= 0.4'}
defined@1.0.1:
resolution: {integrity: sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==}
- degenerator@5.0.1:
- resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==}
- engines: {node: '>= 14'}
-
del@6.1.1:
resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==}
engines: {node: '>=10'}
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
engines: {node: '>= 0.8'}
- deprecation@2.3.1:
- resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==}
-
deps-sort@2.0.1:
resolution: {integrity: sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==}
hasBin: true
des.js@1.1.0:
resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==}
- destroy@1.2.0:
- resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
- engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
-
- detect-indent@7.0.1:
- resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==}
- engines: {node: '>=12.20'}
-
- detect-libc@2.0.3:
- resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
+ detect-libc@2.0.4:
+ resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
engines: {node: '>=8'}
detective@5.2.1:
engines: {node: '>=0.8.0'}
hasBin: true
- diff-sequences@29.6.3:
- resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
-
diff@4.0.2:
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
engines: {node: '>=0.3.1'}
resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
engines: {node: '>=0.10.0'}
- doctrine@3.0.0:
- resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
- engines: {node: '>=6.0.0'}
-
domain-browser@1.2.0:
resolution: {integrity: sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==}
engines: {node: '>=0.4', npm: '>=1.2'}
resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==}
engines: {node: '>=10'}
- dotenv@16.4.5:
- resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==}
+ dotenv@16.5.0:
+ resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==}
engines: {node: '>=12'}
+ dunder-proto@1.0.1:
+ resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
+ engines: {node: '>= 0.4'}
+
dup@1.0.0:
resolution: {integrity: sha512-Bz5jxMMC0wgp23Zm15ip1x8IhYRqJvF3nFC0UInJUDkN1z4uNPk9jTnfCUJXbOGiQ1JbXLQsiV41Fb+HXcj5BA==}
ee-first@1.1.1:
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
- electron-to-chromium@1.4.776:
- resolution: {integrity: sha512-s694bi3+gUzlliqxjPHpa9NRTlhzTgB34aan+pVKZmOTGy2xoZXl+8E1B8i5p5rtev3PKMK/H4asgNejC+YHNg==}
+ electron-to-chromium@1.5.179:
+ resolution: {integrity: sha512-UWKi/EbBopgfFsc5k61wFpV7WrnnSlSzW/e2XcBmS6qKYTivZlLtoll5/rdqRTxGglGHkmkW0j0pFNJG10EUIQ==}
- elliptic@6.5.5:
- resolution: {integrity: sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==}
+ elliptic@6.6.1:
+ resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==}
- emoji-regex@10.3.0:
- resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==}
+ emoji-regex@10.4.0:
+ resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==}
emoji-regex@7.0.3:
resolution: {integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==}
enabled@2.0.0:
resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==}
- encodeurl@1.0.2:
- resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
+ encodeurl@2.0.0:
+ resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
engines: {node: '>= 0.8'}
encoding@0.1.13:
resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==}
- end-of-stream@1.4.4:
- resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
+ end-of-stream@1.4.5:
+ resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
endpoint@0.4.5:
resolution: {integrity: sha512-oA2ALUF+d4Y0I8/WMV/0BuAZGHxfIdAygr9ZXP4rfzmp5zpYZmYKHKAbqRQnrE1YGdPhVg4D24CQkyx2qYEoHg==}
- enhanced-resolve@5.16.1:
- resolution: {integrity: sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==}
+ enhanced-resolve@5.18.2:
+ resolution: {integrity: sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==}
engines: {node: '>=10.13.0'}
entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'}
+ entities@6.0.1:
+ resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
+ engines: {node: '>=0.12'}
+
env-paths@2.2.1:
resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
engines: {node: '>=6'}
+ env-paths@3.0.0:
+ resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
env-string@1.0.1:
resolution: {integrity: sha512-/DhCJDf5DSFK32joQiWRpWrT0h7p3hVQfMKxiBb7Nt8C8IF8BYyPtclDnuGGLOoj16d/8udKeiE7JbkotDmorQ==}
+ environment@1.1.0:
+ resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==}
+ engines: {node: '>=18'}
+
err-code@2.0.3:
resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==}
error-ex@1.3.2:
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
- es-abstract@1.23.3:
- resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==}
+ es-abstract@1.24.0:
+ resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==}
engines: {node: '>= 0.4'}
- es-array-method-boxes-properly@1.0.0:
- resolution: {integrity: sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==}
-
- es-define-property@1.0.0:
- resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==}
+ es-define-property@1.0.1:
+ resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
engines: {node: '>= 0.4'}
es-errors@1.3.0:
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
engines: {node: '>= 0.4'}
- es-get-iterator@1.1.3:
- resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==}
+ es-iterator-helpers@1.2.1:
+ resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==}
+ engines: {node: '>= 0.4'}
+
+ es-module-lexer@1.7.0:
+ resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
- es-object-atoms@1.0.0:
- resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==}
+ es-object-atoms@1.1.1:
+ resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
engines: {node: '>= 0.4'}
- es-set-tostringtag@2.0.3:
- resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==}
+ es-set-tostringtag@2.1.0:
+ resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
engines: {node: '>= 0.4'}
- es-shim-unscopables@1.0.2:
- resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==}
+ es-shim-unscopables@1.1.0:
+ resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==}
+ engines: {node: '>= 0.4'}
- es-to-primitive@1.2.1:
- resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
+ es-to-primitive@1.3.0:
+ resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
engines: {node: '>= 0.4'}
es5-ext@0.10.64:
peerDependencies:
esbuild: '>= 0.14.0'
- esbuild@0.20.2:
- resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==}
- engines: {node: '>=12'}
- hasBin: true
-
- esbuild@0.21.3:
- resolution: {integrity: sha512-Kgq0/ZsAPzKrbOjCQcjoSmPoWhlcVnGAUo7jvaLHoxW1Drto0KGkR1xBNg2Cp43b9ImvxmPEJZ9xkfcnqPsfBw==}
- engines: {node: '>=12'}
+ esbuild@0.25.5:
+ resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==}
+ engines: {node: '>=18'}
hasBin: true
- escalade@3.1.2:
- resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
+ escalade@3.2.0:
+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
escape-goat@2.1.1:
resolution: {integrity: sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==}
engines: {node: '>=8'}
- escape-goat@4.0.0:
- resolution: {integrity: sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==}
- engines: {node: '>=12'}
-
escape-html@1.0.3:
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
engines: {node: '>=0.8.0'}
- escape-string-regexp@2.0.0:
- resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==}
- engines: {node: '>=8'}
-
escape-string-regexp@4.0.0:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'}
engines: {node: '>=6.0'}
hasBin: true
- eslint-compat-utils@0.5.0:
- resolution: {integrity: sha512-dc6Y8tzEcSYZMHa+CMPLi/hyo1FzNeonbhJL7Ol0ccuKQkwopJcJBA9YL/xmMTLU1eKigXo9vj9nALElWYSowg==}
+ eslint-compat-utils@0.5.1:
+ resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==}
engines: {node: '>=12'}
peerDependencies:
eslint: '>=6.0.0'
- eslint-config-love@47.0.0:
- resolution: {integrity: sha512-wIeJhb4/NF7nE5Ltppg1e9dp1Auxx0+ZPRysrXQ3uBKlW4Nj/UiTZu4r3sKWCxo6HGcRcI4MC1Q5421y3fny2w==}
- peerDependencies:
- '@typescript-eslint/eslint-plugin': ^7.0.1
- eslint: ^8.0.1
- eslint-plugin-import: ^2.25.2
- eslint-plugin-n: '^15.0.0 || ^16.0.0 '
- eslint-plugin-promise: ^6.0.0
- typescript: '*'
-
- eslint-config-prettier@9.1.0:
- resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==}
- hasBin: true
- peerDependencies:
- eslint: '>=7.0.0'
-
- eslint-config-standard@17.1.0:
- resolution: {integrity: sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==}
- engines: {node: '>=12.0.0'}
+ eslint-import-context@0.1.9:
+ resolution: {integrity: sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==}
+ engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
peerDependencies:
- eslint: ^8.0.1
- eslint-plugin-import: ^2.25.2
- eslint-plugin-n: '^15.0.0 || ^16.0.0 '
- eslint-plugin-promise: ^6.0.0
-
- eslint-define-config@2.1.0:
- resolution: {integrity: sha512-QUp6pM9pjKEVannNAbSJNeRuYwW3LshejfyBBpjeMGaJjaDUpVps4C6KVR8R7dWZnD3i0synmrE36znjTkJvdQ==}
- engines: {node: '>=18.0.0', npm: '>=9.0.0', pnpm: '>=8.6.0'}
+ unrs-resolver: ^1.0.0
+ peerDependenciesMeta:
+ unrs-resolver:
+ optional: true
eslint-import-resolver-node@0.3.9:
resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
- eslint-import-resolver-typescript@3.6.1:
- resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==}
+ eslint-import-resolver-typescript@3.10.1:
+ resolution: {integrity: sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==}
engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies:
eslint: '*'
eslint-plugin-import: '*'
-
- eslint-module-utils@2.8.1:
- resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==}
- engines: {node: '>=4'}
- peerDependencies:
- '@typescript-eslint/parser': '*'
- eslint: '*'
- eslint-import-resolver-node: '*'
- eslint-import-resolver-typescript: '*'
- eslint-import-resolver-webpack: '*'
+ eslint-plugin-import-x: '*'
peerDependenciesMeta:
- '@typescript-eslint/parser':
- optional: true
- eslint:
- optional: true
- eslint-import-resolver-node:
- optional: true
- eslint-import-resolver-typescript:
+ eslint-plugin-import:
optional: true
- eslint-import-resolver-webpack:
+ eslint-plugin-import-x:
optional: true
- eslint-plugin-es-x@7.6.0:
- resolution: {integrity: sha512-I0AmeNgevgaTR7y2lrVCJmGYF0rjoznpDvqV/kIkZSZbZ8Rw3eu4cGlvBBULScfkSOCzqKbff5LR4CNrV7mZHA==}
+ eslint-plugin-es-x@7.8.0:
+ resolution: {integrity: sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==}
engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies:
eslint: '>=8'
- eslint-plugin-import@2.29.1:
- resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==}
- engines: {node: '>=4'}
+ eslint-plugin-import-x@4.16.1:
+ resolution: {integrity: sha512-vPZZsiOKaBAIATpFE2uMI4w5IRwdv/FpQ+qZZMR4E+PeOcM4OeoEbqxRMnywdxP19TyB/3h6QBB0EWon7letSQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- '@typescript-eslint/parser': '*'
- eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
+ '@typescript-eslint/utils': ^8.0.0
+ eslint: ^8.57.0 || ^9.0.0
+ eslint-import-resolver-node: '*'
peerDependenciesMeta:
- '@typescript-eslint/parser':
+ '@typescript-eslint/utils':
+ optional: true
+ eslint-import-resolver-node:
optional: true
- eslint-plugin-jsdoc@48.2.5:
- resolution: {integrity: sha512-ZeTfKV474W1N9niWfawpwsXGu+ZoMXu4417eBROX31d7ZuOk8zyG66SO77DpJ2+A9Wa2scw/jRqBPnnQo7VbcQ==}
- engines: {node: '>=18'}
+ eslint-plugin-jsdoc@51.3.3:
+ resolution: {integrity: sha512-8XK/9wncTh4PPntQfM4iYJ2v/kvX4qsfBzp+dTnyxpERWhl2R9hEJw1ihws+yAecg9CC6ExTfMInEg3wSK9kWA==}
+ engines: {node: '>=20.11.0'}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
- eslint-plugin-n@17.7.0:
- resolution: {integrity: sha512-4Jg4ZKVE4VjHig2caBqPHYNW5na84RVufUuipFLJbgM/G57O6FdpUKJbHakCDJb/yjQuyqVzYWRtU3HNYaZUwg==}
+ eslint-plugin-n@17.21.0:
+ resolution: {integrity: sha512-1+iZ8We4ZlwVMtb/DcHG3y5/bZOdazIpa/4TySo22MLKdwrLcfrX0hbadnCvykSQCCmkAnWmIP8jZVb2AAq29A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: '>=8.23.0'
- eslint-plugin-prettier@5.1.3:
- resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==}
- engines: {node: ^14.18.0 || >=16.0.0}
+ eslint-plugin-perfectionist@4.15.0:
+ resolution: {integrity: sha512-pC7PgoXyDnEXe14xvRUhBII8A3zRgggKqJFx2a82fjrItDs1BSI7zdZnQtM2yQvcyod6/ujmzb7ejKPx8lZTnw==}
+ engines: {node: ^18.0.0 || >=20.0.0}
peerDependencies:
- '@types/eslint': '>=8.0.0'
- eslint: '>=8.0.0'
- eslint-config-prettier: '*'
- prettier: '>=3.0.0'
- peerDependenciesMeta:
- '@types/eslint':
- optional: true
- eslint-config-prettier:
- optional: true
+ eslint: '>=8.45.0'
- eslint-plugin-promise@6.1.1:
- resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ eslint-plugin-promise@7.2.1:
+ resolution: {integrity: sha512-SWKjd+EuvWkYaS+uN2csvj0KoP43YTu7+phKQ5v+xw6+A0gutVX2yqCeCkC3uLCJFiPfR2dD8Es5L7yUsmvEaA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- eslint: ^7.0.0 || ^8.0.0
+ eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
- eslint-plugin-simple-import-sort@12.1.0:
- resolution: {integrity: sha512-Y2fqAfC11TcG/WP3TrI1Gi3p3nc8XJyEOJYHyEPEGI/UAgNx6akxxlX74p7SbAQdLcgASKhj8M0GKvH3vq/+ig==}
+ eslint-plugin-react@7.37.5:
+ resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==}
+ engines: {node: '>=4'}
peerDependencies:
- eslint: '>=5.0.0'
+ eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7
- eslint-plugin-tsdoc@0.2.17:
- resolution: {integrity: sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==}
-
- eslint-plugin-vue@9.26.0:
- resolution: {integrity: sha512-eTvlxXgd4ijE1cdur850G6KalZqk65k1JKoOI2d1kT3hr8sPD07j1q98FRFdNnpxBELGPWxZmInxeHGF/GxtqQ==}
- engines: {node: ^14.17.0 || >=16.0.0}
+ eslint-plugin-vue@10.3.0:
+ resolution: {integrity: sha512-A0u9snqjCfYaPnqqOaH6MBLVWDUIN4trXn8J3x67uDcXvR7X6Ut8p16N+nYhMCQ9Y7edg2BIRGzfyZsY0IdqoQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
+ '@typescript-eslint/parser': ^7.0.0 || ^8.0.0
+ eslint: ^8.57.0 || ^9.0.0
+ vue-eslint-parser: ^10.0.0
+ peerDependenciesMeta:
+ '@typescript-eslint/parser':
+ optional: true
- eslint-scope@7.2.2:
- resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ eslint-scope@8.4.0:
+ resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
eslint-visitor-keys@3.4.3:
resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- eslint@8.57.0:
- resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ eslint-visitor-keys@4.2.1:
+ resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ eslint@9.30.1:
+ resolution: {integrity: sha512-zmxXPNMOXmwm9E0yQLi5uqXHs7uq2UIiqEKo3Gq+3fwo1XrJ+hijAZImyF7hclW3E6oHz43Yk3RP8at6OTKflQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
hasBin: true
+ peerDependencies:
+ jiti: '*'
+ peerDependenciesMeta:
+ jiti:
+ optional: true
esm@3.2.25:
resolution: {integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==}
resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==}
engines: {node: '>=0.10'}
- espree@9.6.1:
- resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ espree@10.4.0:
+ resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
esprima@4.0.1:
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
engines: {node: '>=4'}
hasBin: true
- esquery@1.5.0:
- resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
+ esquery@1.6.0:
+ resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
engines: {node: '>=0.10'}
esrecurse@4.3.0:
resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==}
engines: {node: '>=10'}
- execa@5.1.1:
- resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
- engines: {node: '>=10'}
-
- execa@8.0.1:
- resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
- engines: {node: '>=16.17'}
-
execspawn@1.0.1:
resolution: {integrity: sha512-s2k06Jy9i8CUkYe0+DxRlvtkZoOkwwfhB+Xxo5HGUtrISVW2m98jO2tr67DGRFxZwkjQqloA3v/tNtjhBRBieg==}
resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
engines: {node: '>=6'}
- expect@29.7.0:
- resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ expect-type@1.2.1:
+ resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==}
+ engines: {node: '>=12.0.0'}
ext@1.7.0:
resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==}
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
- fast-diff@1.3.0:
- resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
+ fast-equals@5.2.2:
+ resolution: {integrity: sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==}
+ engines: {node: '>=6.0.0'}
- fast-glob@3.3.2:
- resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
+ fast-glob@3.3.3:
+ resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
engines: {node: '>=8.6.0'}
fast-json-stable-stringify@2.1.0:
fast-safe-stringify@2.1.1:
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
- fastq@1.17.1:
- resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
+ fast-uri@3.0.6:
+ resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==}
+
+ fastq@1.19.1:
+ resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
+
+ fdir@6.4.6:
+ resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
fecha@4.2.3:
resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==}
- fetch-blob@3.2.0:
- resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
- engines: {node: ^12.20 || >= 14.13}
-
- figlet@1.7.0:
- resolution: {integrity: sha512-gO8l3wvqo0V7wEFLXPbkX83b7MVjRrk1oRLfYlZXol8nEpb/ON9pcKLI4qpBv5YtOTfrINtqb7b40iYY2FTWFg==}
+ figlet@1.8.1:
+ resolution: {integrity: sha512-kEC3Sme+YvA8Hkibv0NR1oClGcWia0VB2fC1SlMy027cwe795Xx40Xiv/nw/iFAwQLupymWh+uhAAErn/7hwPg==}
engines: {node: '>= 0.4.0'}
hasBin: true
resolution: {integrity: sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==}
engines: {node: '>=4'}
- file-entry-cache@6.0.1:
- resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
- engines: {node: ^10.12.0 || >=12.0.0}
+ file-entry-cache@8.0.0:
+ resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
+ engines: {node: '>=16.0.0'}
file-stream-rotator@0.6.1:
resolution: {integrity: sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==}
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
- finalhandler@1.2.0:
- resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==}
+ finalhandler@2.1.0:
+ resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==}
engines: {node: '>= 0.8'}
find-up@3.0.0:
flame-gradient@1.0.0:
resolution: {integrity: sha512-9ejk16/DqvQJ4dHsh68W/4N0zmVQ60zukyUuEHrTbf5pJvP4JqlIdke86Z9174PZokRCXAntY5+H1txSyC7mUA==}
- flat-cache@3.2.0:
- resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==}
- engines: {node: ^10.12.0 || >=12.0.0}
+ flat-cache@4.0.1:
+ resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
+ engines: {node: '>=16'}
flatstr@1.0.12:
resolution: {integrity: sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==}
- flatted@3.3.1:
- resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
+ flatted@3.3.3:
+ resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
fn.name@1.1.0:
resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==}
- for-each@0.3.3:
- resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
+ for-each@0.3.5:
+ resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
+ engines: {node: '>= 0.4'}
- foreground-child@3.1.1:
- resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
+ foreground-child@3.3.1:
+ resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'}
forever-agent@0.6.1:
resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==}
engines: {node: '>= 0.12'}
- form-data@4.0.0:
- resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
+ form-data@4.0.3:
+ resolution: {integrity: sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==}
engines: {node: '>= 6'}
- formdata-polyfill@4.0.10:
- resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
- engines: {node: '>=12.20.0'}
-
- fresh@0.5.2:
- resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
- engines: {node: '>= 0.6'}
+ fresh@2.0.0:
+ resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
+ engines: {node: '>= 0.8'}
from2-string@1.1.0:
resolution: {integrity: sha512-m8vCh+KnXXXBtfF2VUbiYlQ+nczLcntB0BrtNgpmLkHylhObe9WF1b2LZjBBzrZzA6P4mkEla6ZYQoOUTG8cYA==}
resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
engines: {node: '>=12'}
- fs-extra@11.2.0:
- resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==}
+ fs-extra@11.3.0:
+ resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==}
engines: {node: '>=14.14'}
fs-minipass@2.1.0:
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
- function.prototype.name@1.1.6:
- resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==}
+ function.prototype.name@1.1.8:
+ resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==}
engines: {node: '>= 0.4'}
functions-have-names@1.2.3:
generate-object-property@1.2.0:
resolution: {integrity: sha512-TuOwZWgJ2VAMEGJvAyPWvpqxSANF0LDpmyHauMjFYzaACvn+QTT/AZomvPCzVBV7yDN3OmwHQ5OvHaeLKre3JQ==}
+ gensequence@7.0.0:
+ resolution: {integrity: sha512-47Frx13aZh01afHJTB3zTtKIlFI6vWY+MYCN9Qpew6i52rfKjnhCF/l1YlC8UmEMvvntZZ6z4PiCcmyuedR2aQ==}
+ engines: {node: '>=18'}
+
gensync@1.0.0-beta.2:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'}
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
- get-east-asian-width@1.2.0:
- resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==}
+ get-east-asian-width@1.3.0:
+ resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==}
engines: {node: '>=18'}
- get-func-name@2.0.2:
- resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==}
-
- get-intrinsic@1.2.4:
- resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==}
+ get-intrinsic@1.3.0:
+ resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
engines: {node: '>= 0.4'}
get-package-type@0.1.0:
resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==}
engines: {node: '>=8.0.0'}
+ get-proto@1.0.1:
+ resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
+ engines: {node: '>= 0.4'}
+
get-stream@5.2.0:
resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
engines: {node: '>=8'}
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
engines: {node: '>=10'}
- get-stream@8.0.1:
- resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
- engines: {node: '>=16'}
-
- get-symbol-description@1.0.2:
- resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==}
+ get-symbol-description@1.1.0:
+ resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
engines: {node: '>= 0.4'}
- get-tsconfig@4.7.5:
- resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==}
-
- get-uri@6.0.3:
- resolution: {integrity: sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==}
- engines: {node: '>= 14'}
+ get-tsconfig@4.10.1:
+ resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==}
getopts@2.3.0:
resolution: {integrity: sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==}
engines: {node: '>=16'}
hasBin: true
- git-up@7.0.0:
- resolution: {integrity: sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==}
-
- git-url-parse@14.0.0:
- resolution: {integrity: sha512-NnLweV+2A4nCvn4U/m2AoYu0pPKlsmhK9cknG7IMwsjFY1S2jxM+mAhsDxyxfCIGfGaD+dozsyX4b6vkYc83yQ==}
-
github-from-package@0.0.0:
resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
engines: {node: '>=10.13.0'}
- glob@10.3.15:
- resolution: {integrity: sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==}
- engines: {node: '>=16 || 14 >=14.18'}
+ glob@10.4.5:
+ resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
+ hasBin: true
+
+ glob@11.0.3:
+ resolution: {integrity: sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==}
+ engines: {node: 20 || >=22}
hasBin: true
glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+ deprecated: Glob versions prior to v9 are no longer supported
global-directory@4.0.1:
resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==}
resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==}
engines: {node: '>=10'}
- globals@11.12.0:
- resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
- engines: {node: '>=4'}
-
- globals@13.24.0:
- resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
- engines: {node: '>=8'}
+ globals@14.0.0:
+ resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
+ engines: {node: '>=18'}
- globals@15.3.0:
- resolution: {integrity: sha512-cCdyVjIUVTtX8ZsPkq1oCsOsLmGIswqnjZYMJJTGaNApj1yHtLSymKhwH51ttirREn75z3p4k051clwg7rvNKA==}
+ globals@15.15.0:
+ resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==}
engines: {node: '>=18'}
globalthis@1.0.4:
resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
engines: {node: '>=10'}
- globby@14.0.1:
- resolution: {integrity: sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==}
- engines: {node: '>=18'}
-
- gopd@1.0.1:
- resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
+ gopd@1.2.0:
+ resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
+ engines: {node: '>= 0.4'}
got@12.6.1:
resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==}
engines: {node: '>=14.16'}
- graceful-fs@4.2.10:
- resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
-
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
- handlebars@4.7.8:
- resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==}
- engines: {node: '>=0.4.7'}
- hasBin: true
-
har-schema@2.0.0:
resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==}
engines: {node: '>=4'}
has-async-hooks@1.0.0:
resolution: {integrity: sha512-YF0VPGjkxr7AyyQQNykX8zK4PvtEDsUJAPqwu06UFz1lb6EvI53sPh5H1kWxg8NXI5LsfRCZ8uX9NkYDZBb/mw==}
- has-bigints@1.0.2:
- resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
+ has-bigints@1.1.0:
+ resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
+ engines: {node: '>= 0.4'}
has-flag@3.0.0:
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
+ has-own-prop@2.0.0:
+ resolution: {integrity: sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==}
+ engines: {node: '>=8'}
+
has-property-descriptors@1.0.2:
resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
- has-proto@1.0.3:
- resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==}
+ has-proto@1.2.0:
+ resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==}
engines: {node: '>= 0.4'}
- has-symbols@1.0.3:
- resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
+ has-symbols@1.1.0:
+ resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
engines: {node: '>= 0.4'}
has-tostringtag@1.0.2:
resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==}
engines: {node: '>= 0.4.0'}
- hash-base@3.0.4:
- resolution: {integrity: sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow==}
- engines: {node: '>=4'}
+ hash-base@2.0.2:
+ resolution: {integrity: sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==}
- hash-base@3.1.0:
- resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==}
- engines: {node: '>=4'}
+ hash-base@3.0.5:
+ resolution: {integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==}
+ engines: {node: '>= 0.10'}
hash.js@1.1.7:
resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==}
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
- hdr-histogram-js@3.0.0:
- resolution: {integrity: sha512-/EpvQI2/Z98mNFYEnlqJ8Ogful8OpArLG/6Tf2bPnkutBVLIeMVNHjk1ZDfshF2BUweipzbk+dB1hgSB7SIakw==}
+ hdr-histogram-js@3.0.1:
+ resolution: {integrity: sha512-l3GSdZL1Jr1C0kyb461tUjEdrRPZr8Qry7jByltf5JGrA0xvqOSrxRBfcrJqqV/AMEtqqhHhC6w8HW0gn76tRQ==}
engines: {node: '>=14'}
hdr-histogram-percentiles-obj@3.0.0:
html-escaper@2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
- html-tags@3.3.1:
- resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==}
- engines: {node: '>=8'}
-
htmlescape@1.1.1:
resolution: {integrity: sha512-eVcrzgbR4tim7c7soKQKtxa/kQM4TzjnlU83rcZ9bHU6t31ehfV7SktN6McWgwPWg+JYMA/O3qpGxBvFq1z2Jg==}
engines: {node: '>=0.10'}
- http-cache-semantics@4.1.1:
- resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==}
+ http-cache-semantics@4.2.0:
+ resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
http-errors@2.0.0:
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
engines: {node: '>= 0.8'}
- http-parser-js@0.5.8:
- resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==}
+ http-parser-js@0.5.10:
+ resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==}
http-proxy-agent@4.0.1:
resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==}
resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
engines: {node: '>= 6'}
- https-proxy-agent@7.0.4:
- resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==}
+ https-proxy-agent@7.0.6:
+ resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
engines: {node: '>= 14'}
human-signals@1.1.1:
resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==}
engines: {node: '>=8.12.0'}
- human-signals@2.1.0:
- resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
- engines: {node: '>=10.17.0'}
-
- human-signals@5.0.0:
- resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
- engines: {node: '>=16.17.0'}
-
humanize-ms@1.2.1:
resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==}
- husky@9.0.11:
- resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==}
+ husky@9.1.7:
+ resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==}
engines: {node: '>=18'}
hasBin: true
- hyperid@3.2.0:
- resolution: {integrity: sha512-PdTtDo+Rmza9nEhTunaDSUKwbC69TIzLEpZUwiB6f+0oqmY0UPfhyHCPt6K1NQ4WFv5yJBTG5vELztVWP+nEVQ==}
+ hyperid@3.3.0:
+ resolution: {integrity: sha512-7qhCVT4MJIoEsNcbhglhdmBKb09QtcmJNiIQGq7js/Khf5FtQQ9bzcAuloeqBeee7XD7JqDeve9KNlQya5tSGQ==}
hyperscript-attribute-to-property@1.0.2:
resolution: {integrity: sha512-oerMul16jZCmrbNsUw8QgrtDzF8lKgFri1bKQjReLw1IhiiNkI59CWuzZjJDGT79UQ1YiWqXhJMv/tRMVqgtkA==}
ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
- ignore@5.3.1:
- resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==}
+ ignore@5.3.2:
+ resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
+ engines: {node: '>= 4'}
+
+ ignore@7.0.5:
+ resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
engines: {node: '>= 4'}
- import-fresh@3.3.0:
- resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
+ import-fresh@3.3.1:
+ resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
engines: {node: '>=6'}
import-lazy@2.1.0:
resolution: {integrity: sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==}
engines: {node: '>=4'}
- import-lazy@4.0.0:
- resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==}
- engines: {node: '>=8'}
-
import-meta-resolve@4.1.0:
resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==}
inflight@1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
inherits@2.0.3:
resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==}
resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
- ini@4.1.2:
- resolution: {integrity: sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==}
- engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
-
inline-source-map@0.6.3:
resolution: {integrity: sha512-1aVsPEsJWMJq/pdMU61CDlm1URcW702MTB4w9/zUjMus6H/Py8o7g68Pr9D4I6QluWGt/KdmswuRhaA05xVR1w==}
resolution: {integrity: sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==}
engines: {node: '>=6.0.0'}
- inquirer@9.2.22:
- resolution: {integrity: sha512-SqLLa/Oe5rZUagTR9z+Zd6izyatHglbmbvVofo1KzuVB54YHleWzeHNLoR7FOICGOeQSqeLh1cordb3MzhGcEw==}
- engines: {node: '>=18'}
-
insert-module-globals@7.2.1:
resolution: {integrity: sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==}
hasBin: true
resolution: {integrity: sha512-TBcZ0qC9dgdmcxL93OoqkY/RZXJtIi0i07phX/QyYk2ysmJtZex59dgTj4Doq50N9CG9dLRe/RIudc/5CCoFNw==}
engines: {node: '>=12.20'}
- internal-slot@1.0.7:
- resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==}
+ internal-slot@1.1.0:
+ resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
internmap@1.0.1:
resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==}
- interpret@1.4.0:
- resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==}
- engines: {node: '>= 0.10'}
-
interpret@2.2.0:
resolution: {integrity: sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==}
engines: {node: '>= 0.10'}
is-any-array@2.0.1:
resolution: {integrity: sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ==}
- is-arguments@1.1.1:
- resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==}
+ is-arguments@1.2.0:
+ resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==}
engines: {node: '>= 0.4'}
- is-array-buffer@3.0.4:
- resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==}
+ is-array-buffer@3.0.5:
+ resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
engines: {node: '>= 0.4'}
is-arrayish@0.2.1:
is-arrayish@0.3.2:
resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
- is-bigint@1.0.4:
- resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
+ is-async-function@2.1.1:
+ resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==}
+ engines: {node: '>= 0.4'}
+
+ is-bigint@1.1.0:
+ resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==}
+ engines: {node: '>= 0.4'}
is-binary-path@2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
is-boolean-attribute@0.0.1:
resolution: {integrity: sha512-0kXT52Scokg2Miscvsn5UVqg6y1691vcLJcagie1YHJB4zOEuAhMERLX992jtvaStGy2xQTqOtJhvmG/MK1T5w==}
- is-boolean-object@1.1.2:
- resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
+ is-boolean-object@1.2.2:
+ resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==}
engines: {node: '>= 0.4'}
is-buffer@1.1.6:
resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==}
engines: {node: '>=4'}
- is-builtin-module@3.2.1:
- resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==}
- engines: {node: '>=6'}
+ is-bun-module@2.0.0:
+ resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==}
is-callable@1.2.7:
resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==}
hasBin: true
- is-ci@3.0.1:
- resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==}
- hasBin: true
-
- is-core-module@2.13.1:
- resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==}
+ is-core-module@2.16.1:
+ resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
+ engines: {node: '>= 0.4'}
- is-data-view@1.0.1:
- resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==}
+ is-data-view@1.0.2:
+ resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==}
engines: {node: '>= 0.4'}
- is-date-object@1.0.5:
- resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
+ is-date-object@1.1.0:
+ resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
engines: {node: '>= 0.4'}
is-docker@2.2.1:
engines: {node: '>=8'}
hasBin: true
- is-docker@3.0.0:
- resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- hasBin: true
-
is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
+ is-finalizationregistry@1.1.1:
+ resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==}
+ engines: {node: '>= 0.4'}
+
is-fullwidth-code-point@1.0.0:
resolution: {integrity: sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==}
engines: {node: '>=0.10.0'}
resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==}
engines: {node: '>=18'}
- is-generator-function@1.0.10:
- resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==}
+ is-generator-function@1.1.0:
+ resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==}
engines: {node: '>= 0.4'}
is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
- is-in-ci@0.1.0:
- resolution: {integrity: sha512-d9PXLEY0v1iJ64xLiQMJ51J128EYHAaOR4yZqQi8aHGfw6KgifM3/Viw1oZZ1GCVmb3gBuyhLyHj0HgR2DhSXQ==}
- engines: {node: '>=18'}
- hasBin: true
-
- is-inside-container@1.0.0:
- resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
- engines: {node: '>=14.16'}
- hasBin: true
-
is-installed-globally@0.4.0:
resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==}
engines: {node: '>=10'}
resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==}
engines: {node: '>=8'}
- is-interactive@2.0.0:
- resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==}
- engines: {node: '>=12'}
-
is-lambda@1.0.1:
resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==}
resolution: {integrity: sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==}
engines: {node: '>=10'}
- is-npm@6.0.0:
- resolution: {integrity: sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
- is-number-object@1.0.7:
- resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==}
+ is-number-object@1.1.1:
+ resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==}
engines: {node: '>= 0.4'}
is-number@7.0.0:
is-property@1.0.2:
resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==}
- is-regex@1.1.4:
- resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
+ is-regex@1.2.1:
+ resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
engines: {node: '>= 0.4'}
is-set@2.0.3:
resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==}
engines: {node: '>= 0.4'}
- is-shared-array-buffer@1.0.3:
- resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==}
+ is-shared-array-buffer@1.0.4:
+ resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==}
engines: {node: '>= 0.4'}
- is-ssh@1.4.0:
- resolution: {integrity: sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==}
-
is-stream@2.0.1:
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
engines: {node: '>=8'}
- is-stream@3.0.0:
- resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
- is-string@1.0.7:
- resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
+ is-string@1.1.1:
+ resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==}
engines: {node: '>= 0.4'}
- is-symbol@1.0.4:
- resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==}
+ is-symbol@1.1.1:
+ resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==}
engines: {node: '>= 0.4'}
is-text-path@2.0.0:
resolution: {integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==}
engines: {node: '>=8'}
- is-typed-array@1.1.13:
- resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==}
+ is-typed-array@1.1.15:
+ resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
engines: {node: '>= 0.4'}
is-typedarray@1.0.0:
resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
engines: {node: '>=10'}
- is-unicode-supported@1.3.0:
- resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==}
- engines: {node: '>=12'}
+ is-weakmap@2.0.2:
+ resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
+ engines: {node: '>= 0.4'}
- is-unicode-supported@2.0.0:
- resolution: {integrity: sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==}
- engines: {node: '>=18'}
+ is-weakref@1.1.1:
+ resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==}
+ engines: {node: '>= 0.4'}
- is-weakref@1.0.2:
- resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==}
+ is-weakset@2.0.4:
+ resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
+ engines: {node: '>= 0.4'}
is-wsl@1.1.0:
resolution: {integrity: sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==}
resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
engines: {node: '>=8'}
- is-wsl@3.1.0:
- resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==}
- engines: {node: '>=16'}
-
is-yarn-global@0.3.0:
resolution: {integrity: sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==}
isstream@0.1.2:
resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==}
- issue-parser@7.0.0:
- resolution: {integrity: sha512-jgAw78HO3gs9UrKqJNQvfDj9Ouy8Mhu40fbEJ8yXff4MW8+/Fcn9iFjyWUQ6SKbX8ipPk3X5A3AyfYHRu6uVLw==}
- engines: {node: ^18.17 || >=20.6.1}
-
istanbul-lib-coverage@3.2.2:
resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
engines: {node: '>=8'}
resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==}
engines: {node: '>=10'}
- istanbul-lib-source-maps@5.0.4:
- resolution: {integrity: sha512-wHOoEsNJTVltaJp8eVkm8w+GVkVNHT2YDYo53YdzQEL2gWm1hBX5cGFR9hQJtuGLebidVX7et3+dmDZrmclduw==}
+ istanbul-lib-source-maps@5.0.6:
+ resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==}
engines: {node: '>=10'}
istanbul-reports@3.1.7:
resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==}
engines: {node: '>=8'}
- iterate-iterator@1.0.2:
- resolution: {integrity: sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==}
-
- iterate-value@1.0.2:
- resolution: {integrity: sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==}
-
- jackspeak@2.3.6:
- resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==}
- engines: {node: '>=14'}
-
- jest-diff@29.7.0:
- resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
-
- jest-get-type@29.6.3:
- resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
-
- jest-matcher-utils@29.7.0:
- resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ iterator.prototype@1.1.5:
+ resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==}
+ engines: {node: '>= 0.4'}
- jest-message-util@29.7.0:
- resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ jackspeak@3.4.3:
+ resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
- jest-util@29.7.0:
- resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ jackspeak@4.1.1:
+ resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==}
+ engines: {node: 20 || >=22}
- jiti@1.21.0:
- resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==}
+ jiti@2.4.2:
+ resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==}
hasBin: true
- jju@1.4.0:
- resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==}
-
- js-beautify@1.15.1:
- resolution: {integrity: sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA==}
+ js-beautify@1.15.4:
+ resolution: {integrity: sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==}
engines: {node: '>=14'}
hasBin: true
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
- js-tokens@9.0.0:
- resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==}
+ js-tokens@9.0.1:
+ resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
js-yaml@4.1.0:
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
jsbn@1.1.0:
resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==}
- jsdoc-type-pratt-parser@4.0.0:
- resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==}
+ jsdoc-type-pratt-parser@4.1.0:
+ resolution: {integrity: sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==}
engines: {node: '>=12.0.0'}
- jsdom@24.0.0:
- resolution: {integrity: sha512-UDS2NayCvmXSXVP6mpTj+73JnNQadZlr9N68189xib2tx5Mls7swlTNao26IoHv46BZJFvXygyRtyXd1feAk1A==}
+ jsdom@26.1.0:
+ resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==}
engines: {node: '>=18'}
peerDependencies:
- canvas: ^2.11.2
+ canvas: ^3.0.0
peerDependenciesMeta:
canvas:
optional: true
- jsesc@2.5.2:
- resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
- engines: {node: '>=4'}
+ jsesc@3.1.0:
+ resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
+ engines: {node: '>=6'}
hasBin: true
json-buffer@3.0.1:
json-stringify-safe@5.0.1:
resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==}
- json5@1.0.2:
- resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
- hasBin: true
-
json5@2.2.3:
resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
engines: {node: '>=6'}
resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==}
engines: {node: '>=0.6.0'}
+ jsx-ast-utils@3.3.5:
+ resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
+ engines: {node: '>=4.0'}
+
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
resolution: {integrity: sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==}
engines: {node: '>=8'}
- latest-version@7.0.0:
- resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==}
- engines: {node: '>=14.16'}
-
leven@2.1.0:
resolution: {integrity: sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==}
engines: {node: '>=0.10.0'}
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
- lilconfig@3.0.0:
- resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==}
+ lilconfig@3.1.3:
+ resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
engines: {node: '>=14'}
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
- lint-staged@15.2.2:
- resolution: {integrity: sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==}
- engines: {node: '>=18.12.0'}
+ lint-staged@16.1.2:
+ resolution: {integrity: sha512-sQKw2Si2g9KUZNY3XNvRuDq4UJqpHwF0/FQzZR2M7I5MvtpWvibikCjUVJzZdGE0ByurEl3KQNvsGetd1ty1/Q==}
+ engines: {node: '>=20.17'}
hasBin: true
- listr2@8.0.1:
- resolution: {integrity: sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==}
+ listr2@8.3.3:
+ resolution: {integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==}
engines: {node: '>=18.0.0'}
- local-pkg@0.5.0:
- resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==}
- engines: {node: '>=14'}
-
locate-path@3.0.0:
resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==}
engines: {node: '>=6'}
resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- lodash-es@4.17.21:
- resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
-
lodash.camelcase@4.3.0:
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
- lodash.capitalize@4.2.1:
- resolution: {integrity: sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==}
-
lodash.chunk@4.2.0:
resolution: {integrity: sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w==}
lodash.debounce@4.0.8:
resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
- lodash.escaperegexp@4.1.2:
- resolution: {integrity: sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==}
-
lodash.flatten@4.4.0:
resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==}
lodash.isplainobject@4.0.6:
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
- lodash.isstring@4.0.1:
- resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
-
lodash.kebabcase@4.1.1:
resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==}
lodash.uniq@4.5.0:
resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==}
- lodash.uniqby@4.7.0:
- resolution: {integrity: sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==}
-
lodash.upperfirst@4.3.1:
resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==}
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
engines: {node: '>=10'}
- log-symbols@6.0.0:
- resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==}
+ log-update@6.1.0:
+ resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==}
engines: {node: '>=18'}
- log-update@6.0.0:
- resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==}
- engines: {node: '>=18'}
-
- logform@2.6.0:
- resolution: {integrity: sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==}
+ logform@2.7.0:
+ resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==}
engines: {node: '>= 12.0.0'}
long@4.0.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
- loupe@2.3.7:
- resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==}
+ loupe@3.1.4:
+ resolution: {integrity: sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==}
lower-case@1.1.4:
resolution: {integrity: sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==}
resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- lru-cache@10.2.2:
- resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==}
- engines: {node: 14 || >=16.14}
+ lru-cache@10.4.3:
+ resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
+
+ lru-cache@11.1.0:
+ resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==}
+ engines: {node: 20 || >=22}
lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
engines: {node: '>=10'}
- lru-cache@7.18.3:
- resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
- engines: {node: '>=12'}
-
macos-release@2.5.1:
resolution: {integrity: sha512-DXqXhEM7gW59OjZO8NIjBCz9AQ1BEMrfiOAl4AYByHCtVHRF4KoGNO8mqQeM8lRCtQe/UnJ4imO/d2HdkKsd+A==}
engines: {node: '>=6'}
- macos-release@3.2.0:
- resolution: {integrity: sha512-fSErXALFNsnowREYZ49XCdOHF8wOPWuFOGQrAhP7x5J/BqQv+B02cNsTykGpDgRVx43EKg++6ANmTaGTtW+hUA==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
magic-string@0.23.2:
resolution: {integrity: sha512-oIUZaAxbcxYIp4AyLafV6OVKoB3YouZs0UTCJ8mOKBHNyJgGDaMJ4TgA+VylJh6fx7EQCC52XkbURxxG9IoJXA==}
magic-string@0.25.1:
resolution: {integrity: sha512-sCuTz6pYom8Rlt4ISPFn6wuFodbKMIHUMv4Qko9P17dpxb7s52KJTmRuZZqHdGmLCK9AOcDare039nRIcfdkEg==}
- magic-string@0.30.10:
- resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==}
+ magic-string@0.30.17:
+ resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
- magicast@0.3.4:
- resolution: {integrity: sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==}
+ magicast@0.3.5:
+ resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==}
make-dir@3.1.0:
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
manage-path@2.0.0:
resolution: {integrity: sha512-NJhyB+PJYTpxhxZJ3lecIGgh4kwIY2RAh44XvAz9UlqthlQwtPBf62uBVR8XaD8CRuSjQ6TnZH2lNJkbLPZM2A==}
- mariadb@3.3.0:
- resolution: {integrity: sha512-sAL4bJgbfCAtXcE8bXI+NAMzVaPNkIU8hRZUXYfgNFoWB9U57G3XQiMeCx/A6IrS6y7kGwBLylrwgsZQ8kUYlw==}
+ mariadb@3.4.2:
+ resolution: {integrity: sha512-B17vhYRHDMQ1XXvhSWsvKJbpw3Q8B6py93ThBEXZXSgxIbqnKqoHK1RzoPLbIxoEzWN3jA86ZaMMc3IG6L5wsw==}
engines: {node: '>= 14'}
+ math-intrinsics@1.1.0:
+ resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
+ engines: {node: '>= 0.4'}
+
md5.js@1.3.5:
resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==}
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
- micromatch@4.0.5:
- resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
+ micromatch@4.0.8:
+ resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
- mikro-orm@6.2.7:
- resolution: {integrity: sha512-1NHDdwcy4X7Jfu3KLXKXClAbPq8/BTgsXblKRUt1tTA0dvJSl8k4LCu9sCx/ren1wDq8B1VkoE7EFG+M6YRmhQ==}
+ mikro-orm@6.4.16:
+ resolution: {integrity: sha512-a+19cRuEPEJ3qf5Vpv4HO9TAxo/I6/rP1bZT93ln8YtNzAbCrcLC766EG6upLS6Sf7OLqdq0cXs5mUN9ESQQrg==}
engines: {node: '>= 18.12.0'}
miller-rabin@4.0.1:
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
engines: {node: '>= 0.6'}
+ mime-db@1.54.0:
+ resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
+ engines: {node: '>= 0.6'}
+
mime-types@2.1.35:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
- mime@1.6.0:
- resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
- engines: {node: '>=4'}
- hasBin: true
+ mime-types@3.0.1:
+ resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==}
+ engines: {node: '>= 0.6'}
mimic-fn@1.2.0:
resolution: {integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==}
resolution: {integrity: sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==}
engines: {node: '>=8'}
- mimic-fn@4.0.0:
- resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
- engines: {node: '>=12'}
+ mimic-function@5.0.1:
+ resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
+ engines: {node: '>=18'}
mimic-response@3.1.0:
resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
minimalistic-crypto-utils@1.0.1:
resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==}
+ minimatch@10.0.3:
+ resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==}
+ engines: {node: 20 || >=22}
+
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==}
engines: {node: '>=16 || 14 >=14.17'}
- minimatch@9.0.4:
- resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==}
+ minimatch@9.0.5:
+ resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
engines: {node: '>=16 || 14 >=14.17'}
minimist@1.2.8:
resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
engines: {node: '>=8'}
- minipass@7.1.1:
- resolution: {integrity: sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==}
+ minipass@7.1.2:
+ resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
engines: {node: '>=16 || 14 >=14.17'}
minizlib@2.1.2:
resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
engines: {node: '>= 8'}
- minizlib@3.0.1:
- resolution: {integrity: sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==}
+ minizlib@3.0.2:
+ resolution: {integrity: sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==}
engines: {node: '>= 18'}
mkdirp-classic@0.5.3:
ml-xsadd@2.0.0:
resolution: {integrity: sha512-VoAYUqmPRmzKbbqRejjqceGFp3VF81Qe8XXFGU0UXLxB7Mf4GGvyGq5Qn3k4AiQgDEV6WzobqlPOd+j0+m6IrA==}
- mlly@1.7.0:
- resolution: {integrity: sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==}
-
- mnemonist@0.40.0-rc1:
- resolution: {integrity: sha512-38L0xGDezsPweee5i7duiaCRzlkkCJorozW6Rta60iel7ZkT4vF6jDIfr101NxE3rsAsumuOvc8yiTGZD5gG4w==}
+ mnemonist@0.40.3:
+ resolution: {integrity: sha512-Vjyr90sJ23CKKH/qPAgUKicw/v6pRoamxIEDFOF8uSgFME7DqPRpHgRTejWVjkdGg5dXj0/NyxZHZ9bcjH+2uQ==}
module-deps@6.2.3:
resolution: {integrity: sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==}
moment@2.30.1:
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
- mongodb-connection-string-url@3.0.1:
- resolution: {integrity: sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==}
+ mongodb-connection-string-url@3.0.2:
+ resolution: {integrity: sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==}
- mongodb@6.6.2:
- resolution: {integrity: sha512-ZF9Ugo2JCG/GfR7DEb4ypfyJJyiKbg5qBYKRintebj8+DNS33CyGMkWbrS9lara+u+h+yEOGSRiLhFO/g1s1aw==}
+ mongodb@6.17.0:
+ resolution: {integrity: sha512-neerUzg/8U26cgruLysKEjJvoNSXhyID3RvzvdcpsIi2COYM3FS3o9nlH7fxFtefTb942dX3W9i37oPfCVj4wA==}
engines: {node: '>=16.20.1'}
peerDependencies:
'@aws-sdk/credential-providers': ^3.188.0
- '@mongodb-js/zstd': ^1.1.0
+ '@mongodb-js/zstd': ^1.1.0 || ^2.0.0
gcp-metadata: ^5.2.0
kerberos: ^2.0.1
mongodb-client-encryption: '>=6.0.0 <7'
socks:
optional: true
- morphdom@2.7.2:
- resolution: {integrity: sha512-Dqb/lHFyTi7SZpY0a5R4I/0Edo+iPMbaUexsHHsLAByyixCDiLHPHyVoKVmrpL0THcT7V9Cgev9y21TQYq6wQg==}
-
- ms@2.0.0:
- resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
+ morphdom@2.7.5:
+ resolution: {integrity: sha512-z6bfWFMra7kBqDjQGHud1LSXtq5JJC060viEkQFMBX6baIecpkNr2Ywrn2OQfWP3rXiNFQRPoFjD8/TvJcWcDg==}
ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
mute-stream@0.0.7:
resolution: {integrity: sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==}
- mute-stream@1.0.0:
- resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==}
- engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
-
mutexify@1.4.0:
resolution: {integrity: sha512-pbYSsOrSB/AKN5h/WzzLRMFgZhClWccf2XIB4RSMC8JbquiB0e0/SH5AIfdQMdyHmYtv4seU7yV/TvAwPLJ1Yg==}
+ nano-spawn@1.0.2:
+ resolution: {integrity: sha512-21t+ozMQDAL/UGgQVBbZ/xXvNO10++ZPuTmKRO8k9V3AClVRht49ahtDjfY8l1q6nSHOrE5ASfthzH3ol6R/hg==}
+ engines: {node: '>=20.17'}
+
nanoassert@1.1.0:
resolution: {integrity: sha512-C40jQ3NzfkP53NsO8kEOFd79p4b9kDXQMwgiY1z8ZwrDZgUyom0AHwGegF4Dm99L+YoYhuaB0ceerUcXmqr1rQ==}
nanohtml@1.10.0:
resolution: {integrity: sha512-r/3AQl+jxAxUIJRiKExUjBtFcE1cm4yTOsTIdVqqlxPNtBxJh522ANrcQYzdNHhPzbPgb7j6qujq6eGehBX0kg==}
- nanoid@3.3.7:
- resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
+ nanoid@3.3.11:
+ resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
- napi-build-utils@1.0.2:
- resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==}
+ napi-build-utils@2.0.0:
+ resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==}
+
+ napi-postinstall@0.3.0:
+ resolution: {integrity: sha512-M7NqKyhODKV1gRLdkwE7pDsZP2/SC2a2vHkOYh9MCpKMbWVfyVfUw5MaH83Fv6XMjxr5jryUp3IDDL9rlxsTeA==}
+ engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+ hasBin: true
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+ natural-orderby@5.0.0:
+ resolution: {integrity: sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==}
+ engines: {node: '>=18'}
+
ndarray-blas-level1@1.1.3:
resolution: {integrity: sha512-g0Qzf+W0J2S/w1GeYlGuFjGRGGE+f+u8x4O8lhBtsrCaf++n/+YLTPKk1tovYmciL3zUePmwi/szoP5oj8zQvg==}
ndarray@1.0.19:
resolution: {integrity: sha512-B4JHA4vdyZU30ELBw3g7/p9bZupyew5a7tX1Y/gGeF2hafrPaQZhgrGQfsvgfYbgdFZjYwuEcnaobeM/WMW+HQ==}
- negotiator@0.6.3:
- resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
+ negotiator@0.6.4:
+ resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==}
engines: {node: '>= 0.6'}
- neo-async@2.6.2:
- resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
-
- netmask@2.0.2:
- resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==}
- engines: {node: '>= 0.4.0'}
-
- new-github-release-url@2.0.0:
- resolution: {integrity: sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ neostandard@0.12.2:
+ resolution: {integrity: sha512-VZU8EZpSaNadp3rKEwBhVD1Kw8jE3AftQLkCyOaM7bWemL1LwsYRsBnAmXy2LjG9zO8t66qJdqB7ccwwORyrAg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ hasBin: true
+ peerDependencies:
+ eslint: ^9.0.0
next-tick@1.1.0:
resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
no-case@2.3.2:
resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==}
- node-abi@3.62.0:
- resolution: {integrity: sha512-CPMcGa+y33xuL1E0TcNIu4YyaZCxnnvkVaEXrsosR3FxN+fV8xvb7Mzpb7IgKler10qeMkE6+Dp8qJhpzdq35g==}
+ node-abi@3.75.0:
+ resolution: {integrity: sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==}
engines: {node: '>=10'}
- node-addon-api@7.1.0:
- resolution: {integrity: sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==}
- engines: {node: ^16 || ^18 || >= 20}
-
- node-domexception@1.0.0:
- resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
- engines: {node: '>=10.5.0'}
+ node-addon-api@7.1.1:
+ resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
node-fetch@2.6.13:
resolution: {integrity: sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==}
encoding:
optional: true
- node-fetch@2.7.0:
- resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
- engines: {node: 4.x || >=6.0.0}
- peerDependencies:
- encoding: ^0.1.0
- peerDependenciesMeta:
- encoding:
- optional: true
-
- node-fetch@3.3.2:
- resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
- node-gyp-build@4.8.1:
- resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==}
+ node-gyp-build@4.8.4:
+ resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==}
hasBin: true
node-gyp@8.4.1:
engines: {node: '>= 10.12.0'}
hasBin: true
- node-releases@2.0.14:
- resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
+ node-releases@2.0.19:
+ resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==}
nopt@5.0.0:
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
- normalize-url@8.0.1:
- resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==}
+ normalize-url@8.0.2:
+ resolution: {integrity: sha512-Ee/R3SyN4BuynXcnTaekmaVdbDAEiNrHqjQIA37mHU8G9pf7aaAD4ZX3XjBLo6rsdcxA/gtkcNYZLt30ACgynw==}
engines: {node: '>=14.16'}
npm-run-path@4.0.1:
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
engines: {node: '>=8'}
- npm-run-path@5.3.0:
- resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
npmlog@6.0.2:
resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==}
engines: {node: '>=0.10.0'}
- nwsapi@2.2.10:
- resolution: {integrity: sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==}
+ nwsapi@2.2.20:
+ resolution: {integrity: sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==}
oauth-sign@0.9.0:
resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==}
+ object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
object-hash@3.0.0:
resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
engines: {node: '>= 6'}
- object-inspect@1.13.1:
- resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==}
+ object-inspect@1.13.4:
+ resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
+ engines: {node: '>= 0.4'}
object-keys@1.1.1:
resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
engines: {node: '>= 0.4'}
- object.assign@4.1.5:
- resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==}
+ object.assign@4.1.7:
+ resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==}
engines: {node: '>= 0.4'}
- object.fromentries@2.0.8:
- resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==}
+ object.entries@1.1.9:
+ resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==}
engines: {node: '>= 0.4'}
- object.groupby@1.0.3:
- resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==}
+ object.fromentries@2.0.8:
+ resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==}
engines: {node: '>= 0.4'}
- object.values@1.2.0:
- resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==}
+ object.values@1.2.1:
+ resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
engines: {node: '>= 0.4'}
- obliterator@2.0.4:
- resolution: {integrity: sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==}
+ obliterator@2.0.5:
+ resolution: {integrity: sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==}
on-finished@2.4.1:
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
engines: {node: '>=6'}
- onetime@6.0.0:
- resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
- engines: {node: '>=12'}
-
- open@10.1.0:
- resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==}
+ onetime@7.0.0:
+ resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==}
engines: {node: '>=18'}
open@7.4.2:
resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==}
engines: {node: '>=10'}
- ora@8.0.1:
- resolution: {integrity: sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==}
- engines: {node: '>=18'}
-
os-browserify@0.3.0:
resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==}
resolution: {integrity: sha512-xl9MAoU97MH1Xt5K9ERft2YfCAoaO6msy1OBA0ozxEC0x0TmIoE6K3QvgJMMZA9yKGLmHXNY/YZoDbiGDj4zYw==}
engines: {node: '>=10'}
- os-name@5.1.0:
- resolution: {integrity: sha512-YEIoAnM6zFmzw3PQ201gCVCIWbXNyKObGlVvpAVvraAeOHnlYVKFssbA/riRX5R40WA6kKrZ7Dr7dWzO3nKSeQ==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
os-tmpdir@1.0.2:
resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==}
engines: {node: '>=0.10.0'}
+ own-keys@1.0.1:
+ resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
+ engines: {node: '>= 0.4'}
+
p-cancelable@3.0.0:
resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==}
engines: {node: '>=12.20'}
resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- p-limit@5.0.0:
- resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==}
- engines: {node: '>=18'}
-
p-locate@3.0.0:
resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==}
engines: {node: '>=6'}
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'}
- pac-proxy-agent@7.0.1:
- resolution: {integrity: sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==}
- engines: {node: '>= 14'}
-
- pac-resolver@7.0.1:
- resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==}
- engines: {node: '>= 14'}
+ package-json-from-dist@1.0.1:
+ resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
package-json@6.5.0:
resolution: {integrity: sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==}
engines: {node: '>=8'}
- package-json@8.1.1:
- resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==}
- engines: {node: '>=14.16'}
-
pako@1.0.11:
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'}
+ parent-module@2.0.0:
+ resolution: {integrity: sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==}
+ engines: {node: '>=8'}
+
parent-require@1.0.0:
resolution: {integrity: sha512-2MXDNZC4aXdkkap+rBBMv0lUsfJqvX5/2FiYYnfCnorZt3Pk06/IOR5KeaoghgS2w07MLWgjbsnyaq6PdHn2LQ==}
engines: {node: '>= 0.4.0'}
resolution: {integrity: sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==}
engines: {node: '>= 0.10'}
- parse-github-url@1.0.2:
- resolution: {integrity: sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==}
- engines: {node: '>=0.10.0'}
- hasBin: true
+ parse-imports-exports@0.2.4:
+ resolution: {integrity: sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==}
parse-json@5.2.0:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
- parse-path@7.0.0:
- resolution: {integrity: sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==}
+ parse-statements@1.0.11:
+ resolution: {integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==}
- parse-url@8.1.0:
- resolution: {integrity: sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==}
-
- parse5@7.1.2:
- resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==}
+ parse5@7.3.0:
+ resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
parseurl@1.3.3:
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
- path-key@4.0.0:
- resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
- engines: {node: '>=12'}
-
path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
engines: {node: '>=16 || 14 >=14.18'}
+ path-scurry@2.0.0:
+ resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==}
+ engines: {node: 20 || >=22}
+
path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
- path-type@5.0.0:
- resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==}
- engines: {node: '>=12'}
-
- pathe@1.1.2:
- resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
+ pathe@2.0.3:
+ resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
- pathval@1.1.1:
- resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==}
+ pathval@2.0.1:
+ resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==}
+ engines: {node: '>= 14.16'}
- pbkdf2@3.1.2:
- resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==}
+ pbkdf2@3.1.3:
+ resolution: {integrity: sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==}
engines: {node: '>=0.12'}
+ peowly@1.3.2:
+ resolution: {integrity: sha512-BYIrwr8JCXY49jUZscgw311w9oGEKo7ux/s+BxrhKTQbiQ0iYNdZNJ5LgagaeercQdFHwnR7Z5IxxFWVQ+BasQ==}
+ engines: {node: '>=18.6.0'}
+
performance-now@2.1.0:
resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==}
pg-connection-string@2.6.2:
resolution: {integrity: sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==}
- picocolors@1.0.1:
- resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==}
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
picomatch@2.3.1:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'}
+ picomatch@4.0.2:
+ resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
+ engines: {node: '>=12'}
+
pidtree@0.6.0:
resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==}
engines: {node: '>=0.10'}
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
engines: {node: '>=0.10.0'}
- pkg-types@1.1.1:
- resolution: {integrity: sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==}
-
pkg-up@3.1.0:
resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==}
engines: {node: '>=8'}
- poolifier@4.0.10:
- resolution: {integrity: sha512-PSitQC7KbzqnPrHLOLl0nebqDbGtEPN1fNVZgAdYPK7jmswAiDaW9z4VDr1fW45mkPio654bEg77QvsScUG+WQ==}
- engines: {node: '>=18.0.0', pnpm: '>=9.0.0'}
+ poolifier@5.0.2:
+ resolution: {integrity: sha512-Y+81llBJ/c0ky5ndwZGoVyF+QX+fTVbDXXcHDpVArGTjQbnz4jCfQwRjPhxdREydSu7QAR7GeKLQmLhhMUpVug==}
+ engines: {node: '>=20.11.0', pnpm: '>=9.0.0'}
- possible-typed-array-names@1.0.0:
- resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==}
+ possible-typed-array-names@1.1.0:
+ resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
engines: {node: '>= 0.4'}
postcss-import@13.0.0:
peerDependencies:
postcss: ^8.0.0
- postcss-selector-parser@6.0.16:
- resolution: {integrity: sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==}
+ postcss-selector-parser@6.1.2:
+ resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
engines: {node: '>=4'}
postcss-value-parser@4.2.0:
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
- postcss@8.4.38:
- resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==}
+ postcss@8.5.6:
+ resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
- prebuild-install@7.1.2:
- resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==}
+ prebuild-install@7.1.3:
+ resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==}
engines: {node: '>=10'}
hasBin: true
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
- prettier-linter-helpers@1.0.0:
- resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==}
- engines: {node: '>=6.0.0'}
-
- prettier@3.2.5:
- resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==}
+ prettier@3.6.2:
+ resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==}
engines: {node: '>=14'}
hasBin: true
resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==}
engines: {node: '>=6'}
- pretty-format@29.7.0:
- resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==}
- engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
-
pretty-hrtime@1.0.3:
resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==}
engines: {node: '>= 0.8'}
resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==}
engines: {node: '>=10'}
- promise.allsettled@1.0.7:
- resolution: {integrity: sha512-hezvKvQQmsFkOdrZfYxUxkyxl8mgFQeT259Ajj9PXdbg9VzBCWrItOev72JyWxkCD5VSSqAeHmlN3tWx4DlmsA==}
- engines: {node: '>= 0.4'}
+ prop-types@15.8.1:
+ resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
proto-list@1.2.4:
resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==}
resolution: {integrity: sha512-hNp56d5uuREVde7UqP+dmBkwzxrhJwYU5nL/mdivyFfkRZdgAgojkyBeU3jKo7ZHrjdSx6Q1CwUmYJI6INt20g==}
hasBin: true
- protocols@2.0.1:
- resolution: {integrity: sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==}
-
- proxy-agent@6.4.0:
- resolution: {integrity: sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==}
- engines: {node: '>= 14'}
-
- proxy-from-env@1.1.0:
- resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
-
- psl@1.9.0:
- resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==}
+ psl@1.15.0:
+ resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==}
public-encrypt@4.0.3:
resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==}
- pump@3.0.0:
- resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
+ pump@3.0.3:
+ resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==}
pumpify@2.0.1:
resolution: {integrity: sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==}
resolution: {integrity: sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==}
engines: {node: '>=8'}
- pupa@3.1.0:
- resolution: {integrity: sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==}
- engines: {node: '>=12.20'}
-
- qs@6.12.1:
- resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==}
+ qs@6.14.0:
+ resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==}
engines: {node: '>=0.6'}
qs@6.5.3:
resolution: {integrity: sha512-kKr2uQ2AokadPjvTyKJQad9xELbZwYzWlNfI3Uz2j/ib5u6H9lDP7fUUR//rMycd0gv4Z5P1qXMfXR8YpIxrjQ==}
hasBin: true
- rambda@9.2.0:
- resolution: {integrity: sha512-RjM8TBNPR+iSvWLqbBpFveDfEf2RPRKHuwBHjQdXsYFDwn3MIvgmJiqVVC1CIQKnOwzeDQd44zqDFgSKQ7RT1Q==}
-
randombytes@2.1.0:
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
hasBin: true
- react-is@18.3.1:
- resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
+ react-is@16.13.1:
+ resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
read-cache@1.0.0:
resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
- rechoir@0.6.2:
- resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==}
- engines: {node: '>= 0.10'}
-
rechoir@0.8.0:
resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==}
engines: {node: '>= 10.13.0'}
reflect-metadata@0.2.2:
resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==}
- regexp.prototype.flags@1.5.2:
- resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==}
+ reflect.getprototypeof@1.0.10:
+ resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
+ engines: {node: '>= 0.4'}
+
+ regexp.prototype.flags@1.5.4:
+ resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
engines: {node: '>= 0.4'}
registry-auth-token@4.2.2:
resolution: {integrity: sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==}
engines: {node: '>=6.0.0'}
- registry-auth-token@5.0.2:
- resolution: {integrity: sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==}
- engines: {node: '>=14'}
-
registry-url@5.1.0:
resolution: {integrity: sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==}
engines: {node: '>=8'}
- registry-url@6.0.1:
- resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==}
- engines: {node: '>=12'}
-
reinterval@1.1.0:
resolution: {integrity: sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==}
- release-it@17.3.0:
- resolution: {integrity: sha512-7t9a2WEwqQKCdteshZUrO/3RX60plS5CzYAFr5+4Zj8qvRx1pFOFVglJSz4BeFAEd2yejpPxfI60+qRUzLEDZw==}
- engines: {node: ^18.18.0 || ^20.8.0 || ^22.0.0}
- hasBin: true
+ repeat-string@1.6.1:
+ resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==}
+ engines: {node: '>=0.10'}
request@2.88.2:
resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==}
resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
- resolve@1.19.0:
- resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==}
+ resolve@1.22.10:
+ resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==}
+ engines: {node: '>= 0.4'}
+ hasBin: true
- resolve@1.22.8:
- resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
+ resolve@2.0.0-next.5:
+ resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==}
hasBin: true
responselike@3.0.0:
resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==}
engines: {node: '>=8'}
- restore-cursor@4.0.0:
- resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ restore-cursor@5.1.0:
+ resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==}
+ engines: {node: '>=18'}
retimer@3.0.0:
resolution: {integrity: sha512-WKE0j11Pa0ZJI5YIk0nflGI7SQsfl2ljihVy7ogh7DeQSeYAUi0ubZ/yEueGtDfUPk6GH5LRw1hBdLq4IwUBWA==}
resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==}
engines: {node: '>= 4'}
- retry@0.13.1:
- resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
- engines: {node: '>= 4'}
-
- reusify@1.0.4:
- resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+ reusify@1.1.0:
+ resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
- rfdc@1.3.1:
- resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==}
+ rfdc@1.4.1:
+ resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
rimraf@3.0.2:
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+ deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true
- rimraf@5.0.7:
- resolution: {integrity: sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==}
- engines: {node: '>=14.18'}
+ rimraf@6.0.1:
+ resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==}
+ engines: {node: 20 || >=22}
hasBin: true
+ ripemd160@2.0.1:
+ resolution: {integrity: sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==}
+
ripemd160@2.0.2:
resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==}
- rollup@4.17.2:
- resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==}
+ rollup@4.44.1:
+ resolution: {integrity: sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
- rrweb-cssom@0.6.0:
- resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==}
-
- run-applescript@7.0.0:
- resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==}
- engines: {node: '>=18'}
+ rrweb-cssom@0.8.0:
+ resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==}
run-async@2.4.1:
resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==}
engines: {node: '>=0.12.0'}
- run-async@3.0.0:
- resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==}
- engines: {node: '>=0.12.0'}
-
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==}
engines: {npm: '>=2.0.0'}
- rxjs@7.8.1:
- resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
-
- safe-array-concat@1.1.2:
- resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==}
+ safe-array-concat@1.1.3:
+ resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
engines: {node: '>=0.4'}
safe-buffer@5.1.2:
safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
- safe-regex-test@1.0.3:
- resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==}
+ safe-push-apply@1.0.0:
+ resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
+ engines: {node: '>= 0.4'}
+
+ safe-regex-test@1.1.0:
+ resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
engines: {node: '>= 0.4'}
- safe-stable-stringify@2.4.3:
- resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==}
+ safe-stable-stringify@2.5.0:
+ resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
engines: {node: '>=10'}
safer-buffer@2.1.2:
resolution: {integrity: sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==}
engines: {node: '>=8'}
- semver-diff@4.0.0:
- resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==}
- engines: {node: '>=12'}
-
- semver@7.6.2:
- resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==}
+ semver@7.7.2:
+ resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==}
engines: {node: '>=10'}
hasBin: true
- send@0.18.0:
- resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==}
- engines: {node: '>= 0.8.0'}
+ send@1.2.0:
+ resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==}
+ engines: {node: '>= 18'}
- serve-static@1.15.0:
- resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==}
- engines: {node: '>= 0.8.0'}
+ serve-static@2.2.0:
+ resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==}
+ engines: {node: '>= 18'}
set-blocking@2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==}
engines: {node: '>= 0.4'}
+ set-proto@1.0.0:
+ resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
+ engines: {node: '>= 0.4'}
+
setprototypeof@1.2.0:
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
- sha.js@2.4.11:
- resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==}
+ sha.js@2.4.12:
+ resolution: {integrity: sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==}
+ engines: {node: '>= 0.10'}
hasBin: true
shallow-copy@0.0.1:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'}
- shell-quote@1.8.1:
- resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==}
-
- shelljs@0.8.5:
- resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==}
- engines: {node: '>=4'}
- hasBin: true
+ shell-quote@1.8.3:
+ resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==}
+ engines: {node: '>= 0.4'}
showdown@1.9.1:
resolution: {integrity: sha512-9cGuS382HcvExtf5AHk7Cb4pAeQQ+h0eTr33V1mu+crYWV4KvWAw6el92bDrqGEk5d46Ai/fhbEUwqJ/mTCNEA==}
hasBin: true
- side-channel@1.0.6:
- resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==}
+ side-channel-list@1.0.0:
+ resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-map@1.0.1:
+ resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-weakmap@1.0.2:
+ resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
+ engines: {node: '>= 0.4'}
+
+ side-channel@1.1.0:
+ resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
engines: {node: '>= 0.4'}
siginfo@2.0.0:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
- slash@5.1.0:
- resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==}
- engines: {node: '>=14.16'}
-
slice-ansi@5.0.0:
resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
engines: {node: '>=12'}
resolution: {integrity: sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==}
engines: {node: '>= 10'}
- socks-proxy-agent@8.0.3:
- resolution: {integrity: sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==}
- engines: {node: '>= 14'}
-
- socks@2.8.3:
- resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==}
+ socks@2.8.5:
+ resolution: {integrity: sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==}
engines: {node: '>= 10.0.0', npm: '>= 3.0.0'}
sonic-boom@1.4.1:
resolution: {integrity: sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==}
- source-map-js@1.2.0:
- resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
source-map-support@0.5.21:
spdx-expression-parse@4.0.0:
resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==}
- spdx-license-ids@3.0.17:
- resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==}
+ spdx-license-ids@3.0.21:
+ resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==}
split2@4.2.0:
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
resolution: {integrity: sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==}
engines: {node: '>= 8'}
+ stable-hash-x@0.2.0:
+ resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==}
+ engines: {node: '>=12.0.0'}
+
+ stable-hash@0.0.5:
+ resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
+
stack-trace@0.0.10:
resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==}
- stack-utils@2.0.6:
- resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
- engines: {node: '>=10'}
-
stackback@0.0.2:
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
engines: {node: '>= 0.8'}
- std-env@3.7.0:
- resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==}
+ statuses@2.0.2:
+ resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
+ engines: {node: '>= 0.8'}
- stdin-discarder@0.2.2:
- resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==}
- engines: {node: '>=18'}
+ std-env@3.9.0:
+ resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==}
- stop-iteration-iterator@1.0.0:
- resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==}
+ stop-iteration-iterator@1.1.0:
+ resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
engines: {node: '>= 0.4'}
stream-browserify@3.0.0:
resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
engines: {node: '>=12'}
- string-width@7.1.0:
- resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==}
+ string-width@7.2.0:
+ resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
engines: {node: '>=18'}
- string.prototype.trim@1.2.9:
- resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==}
+ string.prototype.matchall@4.0.12:
+ resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==}
+ engines: {node: '>= 0.4'}
+
+ string.prototype.repeat@1.0.0:
+ resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==}
+
+ string.prototype.trim@1.2.10:
+ resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==}
engines: {node: '>= 0.4'}
- string.prototype.trimend@1.0.8:
- resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==}
+ string.prototype.trimend@1.0.9:
+ resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==}
+ engines: {node: '>= 0.4'}
string.prototype.trimstart@1.0.8:
resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
engines: {node: '>=6'}
- strip-final-newline@3.0.0:
- resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
- engines: {node: '>=12'}
-
strip-json-comments@2.0.1:
resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
engines: {node: '>=0.10.0'}
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
- strip-literal@2.1.0:
- resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==}
+ strip-literal@3.0.0:
+ resolution: {integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==}
subarg@1.0.0:
resolution: {integrity: sha512-RIrIdRY0X1xojthNcVtgT9sjpOGagEUKpZdgBUi054OEPFo282yg+zE+t1Rj3+RqKq2xStL7uUHhY+AjbC4BXg==}
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
- svg-tags@1.0.0:
- resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==}
-
symbol-tree@3.2.4:
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
- synckit@0.8.8:
- resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==}
+ synckit@0.11.8:
+ resolution: {integrity: sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==}
engines: {node: ^14.18.0 || >=16.0.0}
syntax-error@1.4.0:
tachyons@4.12.0:
resolution: {integrity: sha512-2nA2IrYFy3raCM9fxJ2KODRGHVSZNTW3BR0YnlGsLUf1DA3pk3YfWZ/DdfbnZK6zLZS+jUenlUGJsKcA5fUiZg==}
- tapable@2.2.1:
- resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
+ tapable@2.2.2:
+ resolution: {integrity: sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==}
engines: {node: '>=6'}
- tar-fs@2.1.1:
- resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==}
+ tar-fs@2.1.3:
+ resolution: {integrity: sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==}
tar-stream@2.2.0:
resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
engines: {node: '>=10'}
- tar@7.1.0:
- resolution: {integrity: sha512-ENhg4W6BmjYxl8GTaE7/h99f0aXiSWv4kikRZ9n2/JRxypZniE84ILZqimAhxxX7Zb8Px6pFdheW3EeHfhnXQQ==}
+ tar@7.4.3:
+ resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==}
engines: {node: '>=18'}
tarn@3.0.2:
engines: {node: '>=6.0.0'}
hasBin: true
- test-exclude@6.0.0:
- resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==}
- engines: {node: '>=8'}
+ test-exclude@7.0.1:
+ resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==}
+ engines: {node: '>=18'}
text-extensions@2.4.0:
resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==}
text-hex@1.0.0:
resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==}
- text-table@0.2.0:
- resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
-
through2@2.0.5:
resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==}
resolution: {integrity: sha512-wMctrWD2HZZLuIlchlkE2dfXJh7J2KDI9Dwl+2abPYg0mswQHfOAyQW3jJg1pY5VfttSINZuKcXoB3FGypVklA==}
engines: {node: '>=8'}
- tinybench@2.8.0:
- resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==}
+ tinybench@2.9.0:
+ resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
+
+ tinyexec@0.3.2:
+ resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
+
+ tinyexec@1.0.1:
+ resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==}
+
+ tinyglobby@0.2.14:
+ resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==}
+ engines: {node: '>=12.0.0'}
+
+ tinypool@1.1.1:
+ resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
+ engines: {node: ^18.0.0 || >=20.0.0}
- tinypool@0.8.4:
- resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==}
+ tinyrainbow@2.0.0:
+ resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==}
engines: {node: '>=14.0.0'}
- tinyspy@2.2.1:
- resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==}
+ tinyspy@4.0.3:
+ resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==}
engines: {node: '>=14.0.0'}
tmp@0.0.33:
resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==}
engines: {node: '>=0.6.0'}
- to-fast-properties@2.0.0:
- resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
- engines: {node: '>=4'}
+ to-buffer@1.2.1:
+ resolution: {integrity: sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==}
+ engines: {node: '>= 0.4'}
to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
tr46@0.0.3:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
- tr46@4.1.1:
- resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==}
- engines: {node: '>=14'}
-
- tr46@5.0.0:
- resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==}
+ tr46@5.1.1:
+ resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==}
engines: {node: '>=18'}
transform-ast@2.4.4:
resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==}
engines: {node: '>= 14.0.0'}
- ts-api-utils@1.3.0:
- resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==}
- engines: {node: '>=16'}
+ ts-api-utils@2.1.0:
+ resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==}
+ engines: {node: '>=18.12'}
peerDependencies:
- typescript: '>=4.2.0'
+ typescript: '>=4.8.4'
- ts-morph@22.0.0:
- resolution: {integrity: sha512-M9MqFGZREyeb5fTl6gNHKZLqBQA0TjA1lea+CR48R8EBTDuWrNqW6ccC5QvjNR4s6wDumD3LTCjOFSp9iwlzaw==}
+ ts-declaration-location@1.0.7:
+ resolution: {integrity: sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==}
+ peerDependencies:
+ typescript: '>=4.0.0'
+
+ ts-morph@26.0.0:
+ resolution: {integrity: sha512-ztMO++owQnz8c/gIENcM9XfCEzgoGphTv+nKpYNM1bgsdOVC/jRZuEBf6N+mLLDNg68Kl+GgUZfOySaRiG1/Ug==}
ts-node@10.9.2:
resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
'@swc/wasm':
optional: true
- tsconfig-paths@3.15.0:
- resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
-
tsconfig-paths@4.2.0:
resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==}
engines: {node: '>=6'}
tslib@1.14.1:
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
- tslib@2.6.2:
- resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
- tsx@4.10.5:
- resolution: {integrity: sha512-twDSbf7Gtea4I2copqovUiNTEDrT8XNFXsuHpfGbdpW/z9ZW4fTghzzhAG0WfrCuJmJiOEY1nLIjq4u3oujRWQ==}
+ tsx@4.20.3:
+ resolution: {integrity: sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==}
engines: {node: '>=18.0.0'}
hasBin: true
type-component@0.0.1:
resolution: {integrity: sha512-mDZRBQS2yZkwRQKfjJvQ8UIYJeBNNWCq+HBNstl9N5s9jZ4dkVYXEGkVPsSCEh5Ld4JM1kmrZTzjnrqSAIQ7dw==}
- type-detect@4.0.8:
- resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
- engines: {node: '>=4'}
-
type-fest@0.20.2:
resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
engines: {node: '>=10'}
- type-fest@0.21.3:
- resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
- engines: {node: '>=10'}
-
- type-fest@1.4.0:
- resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==}
- engines: {node: '>=10'}
-
- type-fest@2.19.0:
- resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
- engines: {node: '>=12.20'}
-
- type@2.7.2:
- resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==}
+ type@2.7.3:
+ resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==}
- typed-array-buffer@1.0.2:
- resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==}
+ typed-array-buffer@1.0.3:
+ resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
engines: {node: '>= 0.4'}
- typed-array-byte-length@1.0.1:
- resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==}
+ typed-array-byte-length@1.0.3:
+ resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==}
engines: {node: '>= 0.4'}
- typed-array-byte-offset@1.0.2:
- resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==}
+ typed-array-byte-offset@1.0.4:
+ resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==}
engines: {node: '>= 0.4'}
- typed-array-length@1.0.6:
- resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==}
+ typed-array-length@1.0.7:
+ resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==}
engines: {node: '>= 0.4'}
typedarray-pool@1.2.0:
typedarray@0.0.6:
resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==}
- typescript@5.4.5:
- resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==}
- engines: {node: '>=14.17'}
- hasBin: true
-
- ufo@1.5.3:
- resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==}
+ typescript-eslint@8.35.1:
+ resolution: {integrity: sha512-xslJjFzhOmHYQzSB/QTeASAHbjmxOGEP6Coh93TXmUBFQoJ1VU35UHIDmG06Jd6taf3wqqC1ntBnCMeymy5Ovw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <5.9.0'
- uglify-js@3.17.4:
- resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==}
- engines: {node: '>=0.8.0'}
+ typescript@5.8.3:
+ resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==}
+ engines: {node: '>=14.17'}
hasBin: true
umd@3.0.3:
resolution: {integrity: sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==}
hasBin: true
- unbox-primitive@1.0.2:
- resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
+ unbox-primitive@1.1.0:
+ resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
+ engines: {node: '>= 0.4'}
undeclared-identifiers@1.1.3:
resolution: {integrity: sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==}
hasBin: true
- undici-types@5.26.5:
- resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+ undici-types@6.21.0:
+ resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
+
+ undici-types@7.8.0:
+ resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==}
unicorn-magic@0.1.0:
resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==}
resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==}
engines: {node: '>=8'}
- unique-string@3.0.0:
- resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==}
- engines: {node: '>=12'}
-
- universal-user-agent@6.0.1:
- resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==}
-
universalify@0.2.0:
resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
engines: {node: '>= 4.0.0'}
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
engines: {node: '>= 10.0.0'}
- unpipe@1.0.0:
- resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
- engines: {node: '>= 0.8'}
+ unrs-resolver@1.10.1:
+ resolution: {integrity: sha512-EFrL7Hw4kmhZdwWO3dwwFJo6hO3FXuQ6Bg8BK/faHZ9m1YxqBS31BNSTxklIQkxK/4LlV8zTYnPsIRLBzTzjCA==}
- update-browserslist-db@1.0.16:
- resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==}
+ update-browserslist-db@1.1.3:
+ resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==}
hasBin: true
peerDependencies:
browserslist: '>= 4.21.0'
resolution: {integrity: sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==}
engines: {node: '>=10'}
- update-notifier@7.0.0:
- resolution: {integrity: sha512-Hv25Bh+eAbOLlsjJreVPOs4vd51rrtCrmhyOJtbpAojro34jS4KQaEp4/EvlHJX7jSO42VvEFpkastVyXyIsdQ==}
- engines: {node: '>=18'}
-
upper-case@1.1.3:
resolution: {integrity: sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==}
uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
- url-join@5.0.0:
- resolution: {integrity: sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
url-parse@1.5.10:
resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
- url@0.11.3:
- resolution: {integrity: sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==}
+ url@0.11.4:
+ resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==}
+ engines: {node: '>= 0.4'}
- utf-8-validate@6.0.4:
- resolution: {integrity: sha512-xu9GQDeFp+eZ6LnCywXN/zBancWvOpUMzgjLPSjy4BRHSmTelvn2E0DG0o1sTiw5hkCKBHo8rwSKncfRfv2EEQ==}
+ utf-8-validate@6.0.5:
+ resolution: {integrity: sha512-EYZR+OpIXp9Y1eG1iueg8KRsY8TuT8VNgnanZ0uA3STqhHQTLwbl+WX76/9X5OY12yQubymBpaBSmMPkSTQcKA==}
engines: {node: '>=6.14.2'}
util-deprecate@1.0.2:
v8-compile-cache-lib@3.0.1:
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
- v8-to-istanbul@9.2.0:
- resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==}
+ v8-to-istanbul@9.3.0:
+ resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==}
engines: {node: '>=10.12.0'}
varint@5.0.0:
resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==}
engines: {'0': node >=0.6.0}
- vite-node@1.6.0:
- resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==}
- engines: {node: ^18.0.0 || >=20.0.0}
+ vite-node@3.2.4:
+ resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
- vite@5.2.11:
- resolution: {integrity: sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==}
- engines: {node: ^18.0.0 || >=20.0.0}
+ vite@7.0.2:
+ resolution: {integrity: sha512-hxdyZDY1CM6SNpKI4w4lcUc3Mtkd9ej4ECWVHSMrOdSinVc2zYOAppHeGc/hzmRo3pxM5blMzkuWHOJA/3NiFw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
peerDependencies:
- '@types/node': ^18.0.0 || >=20.0.0
- less: '*'
+ '@types/node': ^20.19.0 || >=22.12.0
+ jiti: '>=1.21.0'
+ less: ^4.0.0
lightningcss: ^1.21.0
- sass: '*'
- stylus: '*'
- sugarss: '*'
- terser: ^5.4.0
+ sass: ^1.70.0
+ sass-embedded: ^1.70.0
+ stylus: '>=0.54.8'
+ sugarss: ^5.0.0
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
peerDependenciesMeta:
'@types/node':
optional: true
+ jiti:
+ optional: true
less:
optional: true
lightningcss:
optional: true
sass:
optional: true
+ sass-embedded:
+ optional: true
stylus:
optional: true
sugarss:
optional: true
terser:
optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
- vitest@1.6.0:
- resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==}
- engines: {node: ^18.0.0 || >=20.0.0}
+ vitest@3.2.4:
+ resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
peerDependencies:
'@edge-runtime/vm': '*'
- '@types/node': ^18.0.0 || >=20.0.0
- '@vitest/browser': 1.6.0
- '@vitest/ui': 1.6.0
+ '@types/debug': ^4.1.12
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ '@vitest/browser': 3.2.4
+ '@vitest/ui': 3.2.4
happy-dom: '*'
jsdom: '*'
peerDependenciesMeta:
'@edge-runtime/vm':
optional: true
+ '@types/debug':
+ optional: true
'@types/node':
optional: true
'@vitest/browser':
vm-browserify@1.1.2:
resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==}
- vue-component-type-helpers@2.0.19:
- resolution: {integrity: sha512-cN3f1aTxxKo4lzNeQAkVopswuImUrb5Iurll9Gaw5cqpnbTAxtEMM1mgi6ou4X79OCyqYv1U1mzBHJkzmiK82w==}
+ vscode-languageserver-textdocument@1.0.12:
+ resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==}
+
+ vscode-uri@3.1.0:
+ resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}
+
+ vue-component-type-helpers@2.2.12:
+ resolution: {integrity: sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==}
- vue-eslint-parser@9.4.2:
- resolution: {integrity: sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==}
- engines: {node: ^14.17.0 || >=16.0.0}
+ vue-eslint-parser@10.2.0:
+ resolution: {integrity: sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- eslint: '>=6.0.0'
+ eslint: ^8.57.0 || ^9.0.0
- vue-router@4.3.2:
- resolution: {integrity: sha512-hKQJ1vDAZ5LVkKEnHhmm1f9pMiWIBNGF5AwU67PdH7TyXCj/a4hTccuUuYCAMgJK6rO/NVYtQIEN3yL8CECa7Q==}
+ vue-router@4.5.1:
+ resolution: {integrity: sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==}
peerDependencies:
vue: ^3.2.0
- vue-toast-notification@3.1.2:
- resolution: {integrity: sha512-oNRL/W9aaHoeScp+iTIW7k09vM16/+8aptp2maa+7qTB43JuxmAgKdXKFYtf+uvSNOYYq2BIWgLCeJ61pwom/A==}
+ vue-toast-notification@3.1.3:
+ resolution: {integrity: sha512-XNyWqwLIGBFfX5G9sK+clq3N3IPlhDjzNdbZaXkEElcotPlWs0wWZailk1vqhdtLYT/93Y4FHAVuzyatLmPZRA==}
engines: {node: '>=12.15.0'}
peerDependencies:
vue: ^3.0
- vue@3.4.27:
- resolution: {integrity: sha512-8s/56uK6r01r1icG/aEOHqyMVxd1bkYcSe9j8HcKtr/xTOFWvnzIVTehNW+5Yt89f+DLBe4A569pnZLS5HzAMA==}
+ vue@3.5.17:
+ resolution: {integrity: sha512-LbHV3xPN9BeljML+Xctq4lbz2lVHCR6DtbpTf5XIO6gugpXUN49j2QQPcMj086r9+AkJ0FfUT8xjulKKBkkr9g==}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
wcwidth@1.0.1:
resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
- web-streams-polyfill@3.3.3:
- resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
- engines: {node: '>= 8'}
-
webfontloader@1.6.28:
resolution: {integrity: sha512-Egb0oFEga6f+nSgasH3E0M405Pzn6y3/9tOVanv/DLfa1YBIgcv90L18YyWnvXkRbIM17v5Kv6IT2N6g1x5tvQ==}
resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==}
engines: {node: '>=18'}
- whatwg-url@13.0.0:
- resolution: {integrity: sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==}
- engines: {node: '>=16'}
-
- whatwg-url@14.0.0:
- resolution: {integrity: sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==}
+ whatwg-url@14.2.0:
+ resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==}
engines: {node: '>=18'}
whatwg-url@5.0.0:
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
- which-boxed-primitive@1.0.2:
- resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
+ which-boxed-primitive@1.1.1:
+ resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
+ engines: {node: '>= 0.4'}
+
+ which-builtin-type@1.2.1:
+ resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==}
+ engines: {node: '>= 0.4'}
+
+ which-collection@1.0.2:
+ resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==}
+ engines: {node: '>= 0.4'}
which-module@2.0.1:
resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
- which-typed-array@1.1.15:
- resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==}
+ which-typed-array@1.1.19:
+ resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==}
engines: {node: '>= 0.4'}
which@2.0.2:
engines: {node: '>= 8'}
hasBin: true
- why-is-node-running@2.2.2:
- resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==}
+ why-is-node-running@2.3.0:
+ resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
engines: {node: '>=8'}
hasBin: true
resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==}
engines: {node: '>=8'}
- widest-line@4.0.1:
- resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==}
- engines: {node: '>=12'}
-
- wildcard-match@5.1.3:
- resolution: {integrity: sha512-a95hPUk+BNzSGLntNXYxsjz2Hooi5oL7xOfJR6CKwSsSALh7vUNuTlzsrZowtYy38JNduYFRVhFv19ocqNOZlg==}
-
windows-release@4.0.0:
resolution: {integrity: sha512-OxmV4wzDKB1x7AZaZgXMVsdJ1qER1ed83ZrTYd5Bwq2HfJVg3DJS8nqlAG4sMoJ7mu8cuRmLEYyU13BKwctRAg==}
engines: {node: '>=10'}
- windows-release@5.1.1:
- resolution: {integrity: sha512-NMD00arvqcq2nwqc5Q6KtrSRHK+fVD31erE5FEMahAw5PmVCgD7MUXodq3pdZSUkqA9Cda2iWx6s1XYwiJWRmw==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
winston-daily-rotate-file@5.0.0:
resolution: {integrity: sha512-JDjiXXkM5qvwY06733vf09I2wnMXpZEhxEVOSPenZMii+g7pcDcTBt2MRugnoi8BwVSuCT2jfRXBUy+n1Zz/Yw==}
engines: {node: '>=8'}
peerDependencies:
winston: ^3
- winston-transport@4.7.0:
- resolution: {integrity: sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==}
+ winston-transport@4.9.0:
+ resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==}
engines: {node: '>= 12.0.0'}
- winston@3.13.0:
- resolution: {integrity: sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==}
+ winston@3.17.0:
+ resolution: {integrity: sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==}
engines: {node: '>= 12.0.0'}
word-wrap@1.2.5:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
- wordwrap@1.0.0:
- resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==}
-
wrap-ansi@5.1.0:
resolution: {integrity: sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==}
engines: {node: '>=6'}
- wrap-ansi@6.2.0:
- resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
- engines: {node: '>=8'}
-
wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
write-file-atomic@3.0.3:
resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==}
- ws@8.17.0:
- resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==}
+ ws@8.18.3:
+ resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==}
engines: {node: '>=10.0.0'}
peerDependencies:
bufferutil: ^4.0.1
resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
engines: {node: '>=18'}
- yaml@2.3.4:
- resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==}
- engines: {node: '>= 14'}
+ yaml@2.8.0:
+ resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==}
+ engines: {node: '>= 14.6'}
+ hasBin: true
yargs-parser@15.0.3:
resolution: {integrity: sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==}
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
- yocto-queue@1.0.0:
- resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
+ yocto-queue@1.2.1:
+ resolution: {integrity: sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==}
engines: {node: '>=12.20'}
snapshots:
- 0x@5.7.0:
+ 0x@5.8.0:
dependencies:
- ajv: 8.13.0
- browserify: 17.0.0
+ ajv: 8.17.1
+ browserify: 17.0.1
concat-stream: 2.0.0
d3-fg: 6.14.0
debounce: 1.2.1
- debug: 4.3.4
- end-of-stream: 1.4.4
+ debug: 4.4.1
+ end-of-stream: 1.4.5
env-string: 1.0.1
escape-string-regexp: 4.0.0
execspawn: 1.0.1
jsonstream2: 3.0.0
make-dir: 3.1.0
minimist: 1.2.8
- morphdom: 2.7.2
+ morphdom: 2.7.5
nanohtml: 1.10.0
on-net-listen: 1.1.2
opn: 5.5.0
- pump: 3.0.0
+ pump: 3.0.3
pumpify: 2.0.1
- semver: 7.6.2
+ semver: 7.7.2
single-line-log: 1.1.2
split2: 4.2.0
tachyons: 4.12.0
'@ampproject/remapping@2.3.0':
dependencies:
- '@jridgewell/gen-mapping': 0.3.5
- '@jridgewell/trace-mapping': 0.3.25
+ '@jridgewell/gen-mapping': 0.3.12
+ '@jridgewell/trace-mapping': 0.3.29
+
+ '@asamuzakjp/css-color@3.2.0':
+ dependencies:
+ '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-color-parser': 3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-tokenizer': 3.0.4
+ lru-cache: 10.4.3
'@assemblyscript/loader@0.19.23': {}
- '@babel/code-frame@7.24.2':
+ '@babel/code-frame@7.27.1':
dependencies:
- '@babel/highlight': 7.24.5
- picocolors: 1.0.1
+ '@babel/helper-validator-identifier': 7.27.1
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
- '@babel/compat-data@7.24.4': {}
+ '@babel/compat-data@7.28.0': {}
- '@babel/core@7.24.5':
+ '@babel/core@7.28.0':
dependencies:
'@ampproject/remapping': 2.3.0
- '@babel/code-frame': 7.24.2
- '@babel/generator': 7.24.5
- '@babel/helper-compilation-targets': 7.23.6
- '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5)
- '@babel/helpers': 7.24.5
- '@babel/parser': 7.24.5
- '@babel/template': 7.24.0
- '@babel/traverse': 7.24.5
- '@babel/types': 7.24.5
+ '@babel/code-frame': 7.27.1
+ '@babel/generator': 7.28.0
+ '@babel/helper-compilation-targets': 7.27.2
+ '@babel/helper-module-transforms': 7.27.3(@babel/core@7.28.0)
+ '@babel/helpers': 7.27.6
+ '@babel/parser': 7.28.0
+ '@babel/template': 7.27.2
+ '@babel/traverse': 7.28.0
+ '@babel/types': 7.28.0
convert-source-map: 2.0.0
- debug: 4.3.4
+ debug: 4.4.1
gensync: 1.0.0-beta.2
json5: 2.2.3
- semver: 7.6.2
+ semver: 7.7.2
transitivePeerDependencies:
- supports-color
- '@babel/generator@7.24.5':
+ '@babel/generator@7.28.0':
dependencies:
- '@babel/types': 7.24.5
- '@jridgewell/gen-mapping': 0.3.5
- '@jridgewell/trace-mapping': 0.3.25
- jsesc: 2.5.2
+ '@babel/parser': 7.28.0
+ '@babel/types': 7.28.0
+ '@jridgewell/gen-mapping': 0.3.12
+ '@jridgewell/trace-mapping': 0.3.29
+ jsesc: 3.1.0
- '@babel/helper-annotate-as-pure@7.22.5':
+ '@babel/helper-annotate-as-pure@7.27.3':
dependencies:
- '@babel/types': 7.24.5
+ '@babel/types': 7.28.0
- '@babel/helper-compilation-targets@7.23.6':
+ '@babel/helper-compilation-targets@7.27.2':
dependencies:
- '@babel/compat-data': 7.24.4
- '@babel/helper-validator-option': 7.23.5
- browserslist: 4.23.0
+ '@babel/compat-data': 7.28.0
+ '@babel/helper-validator-option': 7.27.1
+ browserslist: 4.25.1
lru-cache: 5.1.1
- semver: 7.6.2
-
- '@babel/helper-create-class-features-plugin@7.24.5(@babel/core@7.24.5)':
- dependencies:
- '@babel/core': 7.24.5
- '@babel/helper-annotate-as-pure': 7.22.5
- '@babel/helper-environment-visitor': 7.22.20
- '@babel/helper-function-name': 7.23.0
- '@babel/helper-member-expression-to-functions': 7.24.5
- '@babel/helper-optimise-call-expression': 7.22.5
- '@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.5)
- '@babel/helper-skip-transparent-expression-wrappers': 7.22.5
- '@babel/helper-split-export-declaration': 7.24.5
- semver: 7.6.2
-
- '@babel/helper-environment-visitor@7.22.20': {}
-
- '@babel/helper-function-name@7.23.0':
- dependencies:
- '@babel/template': 7.24.0
- '@babel/types': 7.24.5
-
- '@babel/helper-hoist-variables@7.22.5':
- dependencies:
- '@babel/types': 7.24.5
-
- '@babel/helper-member-expression-to-functions@7.24.5':
- dependencies:
- '@babel/types': 7.24.5
+ semver: 7.7.2
+
+ '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.28.0)':
+ dependencies:
+ '@babel/core': 7.28.0
+ '@babel/helper-annotate-as-pure': 7.27.3
+ '@babel/helper-member-expression-to-functions': 7.27.1
+ '@babel/helper-optimise-call-expression': 7.27.1
+ '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.0)
+ '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
+ '@babel/traverse': 7.28.0
+ semver: 7.7.2
+ transitivePeerDependencies:
+ - supports-color
- '@babel/helper-module-imports@7.22.15':
- dependencies:
- '@babel/types': 7.24.5
+ '@babel/helper-globals@7.28.0': {}
- '@babel/helper-module-imports@7.24.3':
+ '@babel/helper-member-expression-to-functions@7.27.1':
dependencies:
- '@babel/types': 7.24.5
+ '@babel/traverse': 7.28.0
+ '@babel/types': 7.28.0
+ transitivePeerDependencies:
+ - supports-color
- '@babel/helper-module-transforms@7.24.5(@babel/core@7.24.5)':
+ '@babel/helper-module-imports@7.27.1':
dependencies:
- '@babel/core': 7.24.5
- '@babel/helper-environment-visitor': 7.22.20
- '@babel/helper-module-imports': 7.24.3
- '@babel/helper-simple-access': 7.24.5
- '@babel/helper-split-export-declaration': 7.24.5
- '@babel/helper-validator-identifier': 7.24.5
+ '@babel/traverse': 7.28.0
+ '@babel/types': 7.28.0
+ transitivePeerDependencies:
+ - supports-color
- '@babel/helper-optimise-call-expression@7.22.5':
+ '@babel/helper-module-transforms@7.27.3(@babel/core@7.28.0)':
dependencies:
- '@babel/types': 7.24.5
-
- '@babel/helper-plugin-utils@7.24.5': {}
+ '@babel/core': 7.28.0
+ '@babel/helper-module-imports': 7.27.1
+ '@babel/helper-validator-identifier': 7.27.1
+ '@babel/traverse': 7.28.0
+ transitivePeerDependencies:
+ - supports-color
- '@babel/helper-replace-supers@7.24.1(@babel/core@7.24.5)':
+ '@babel/helper-optimise-call-expression@7.27.1':
dependencies:
- '@babel/core': 7.24.5
- '@babel/helper-environment-visitor': 7.22.20
- '@babel/helper-member-expression-to-functions': 7.24.5
- '@babel/helper-optimise-call-expression': 7.22.5
+ '@babel/types': 7.28.0
- '@babel/helper-simple-access@7.24.5':
- dependencies:
- '@babel/types': 7.24.5
+ '@babel/helper-plugin-utils@7.27.1': {}
- '@babel/helper-skip-transparent-expression-wrappers@7.22.5':
+ '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.0)':
dependencies:
- '@babel/types': 7.24.5
+ '@babel/core': 7.28.0
+ '@babel/helper-member-expression-to-functions': 7.27.1
+ '@babel/helper-optimise-call-expression': 7.27.1
+ '@babel/traverse': 7.28.0
+ transitivePeerDependencies:
+ - supports-color
- '@babel/helper-split-export-declaration@7.24.5':
+ '@babel/helper-skip-transparent-expression-wrappers@7.27.1':
dependencies:
- '@babel/types': 7.24.5
-
- '@babel/helper-string-parser@7.24.1': {}
+ '@babel/traverse': 7.28.0
+ '@babel/types': 7.28.0
+ transitivePeerDependencies:
+ - supports-color
- '@babel/helper-validator-identifier@7.24.5': {}
+ '@babel/helper-string-parser@7.27.1': {}
- '@babel/helper-validator-option@7.23.5': {}
+ '@babel/helper-validator-identifier@7.27.1': {}
- '@babel/helpers@7.24.5':
- dependencies:
- '@babel/template': 7.24.0
- '@babel/traverse': 7.24.5
- '@babel/types': 7.24.5
- transitivePeerDependencies:
- - supports-color
+ '@babel/helper-validator-option@7.27.1': {}
- '@babel/highlight@7.24.5':
+ '@babel/helpers@7.27.6':
dependencies:
- '@babel/helper-validator-identifier': 7.24.5
- chalk: 2.4.2
- js-tokens: 4.0.0
- picocolors: 1.0.1
+ '@babel/template': 7.27.2
+ '@babel/types': 7.28.0
- '@babel/parser@7.24.5':
+ '@babel/parser@7.28.0':
dependencies:
- '@babel/types': 7.24.5
+ '@babel/types': 7.28.0
- '@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.5)':
+ '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.0)':
dependencies:
- '@babel/core': 7.24.5
- '@babel/helper-plugin-utils': 7.24.5
+ '@babel/core': 7.28.0
+ '@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.5)':
+ '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.0)':
dependencies:
- '@babel/core': 7.24.5
- '@babel/helper-plugin-utils': 7.24.5
+ '@babel/core': 7.28.0
+ '@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-typescript@7.24.5(@babel/core@7.24.5)':
+ '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.28.0)':
dependencies:
- '@babel/core': 7.24.5
- '@babel/helper-annotate-as-pure': 7.22.5
- '@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5)
- '@babel/helper-plugin-utils': 7.24.5
- '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.5)
+ '@babel/core': 7.28.0
+ '@babel/helper-annotate-as-pure': 7.27.3
+ '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.28.0)
+ '@babel/helper-plugin-utils': 7.27.1
+ '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
+ '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.0)
+ transitivePeerDependencies:
+ - supports-color
- '@babel/template@7.24.0':
+ '@babel/template@7.27.2':
dependencies:
- '@babel/code-frame': 7.24.2
- '@babel/parser': 7.24.5
- '@babel/types': 7.24.5
+ '@babel/code-frame': 7.27.1
+ '@babel/parser': 7.28.0
+ '@babel/types': 7.28.0
- '@babel/traverse@7.24.5':
+ '@babel/traverse@7.28.0':
dependencies:
- '@babel/code-frame': 7.24.2
- '@babel/generator': 7.24.5
- '@babel/helper-environment-visitor': 7.22.20
- '@babel/helper-function-name': 7.23.0
- '@babel/helper-hoist-variables': 7.22.5
- '@babel/helper-split-export-declaration': 7.24.5
- '@babel/parser': 7.24.5
- '@babel/types': 7.24.5
- debug: 4.3.4
- globals: 11.12.0
+ '@babel/code-frame': 7.27.1
+ '@babel/generator': 7.28.0
+ '@babel/helper-globals': 7.28.0
+ '@babel/parser': 7.28.0
+ '@babel/template': 7.27.2
+ '@babel/types': 7.28.0
+ debug: 4.4.1
transitivePeerDependencies:
- supports-color
- '@babel/types@7.24.5':
+ '@babel/types@7.28.0':
dependencies:
- '@babel/helper-string-parser': 7.24.1
- '@babel/helper-validator-identifier': 7.24.5
- to-fast-properties: 2.0.0
+ '@babel/helper-string-parser': 7.27.1
+ '@babel/helper-validator-identifier': 7.27.1
- '@bcoe/v8-coverage@0.2.3': {}
+ '@bcoe/v8-coverage@1.0.2': {}
'@clinic/bubbleprof@10.0.0':
dependencies:
'@clinic/node-trace-log-join': 2.0.0
'@clinic/trace-events-parser': 2.0.0
array-flatten: 3.0.0
- async: 3.2.5
+ async: 3.2.6
d3-axis: 1.0.12
d3-color: 3.1.0
d3-drag: 1.2.5
mkdirp: 1.0.4
on-net-listen: 1.1.2
protocol-buffers: 4.2.0
- pump: 3.0.0
+ pump: 3.0.3
'@clinic/clinic-common@7.1.0':
dependencies:
brfs: 2.0.2
- browserify: 17.0.0
+ browserify: 17.0.1
chalk: 4.1.2
lodash.debounce: 4.0.8
loose-envify: 1.4.0
- postcss: 8.4.38
- postcss-import: 13.0.0(postcss@8.4.38)
+ postcss: 8.5.6
+ postcss-import: 13.0.0(postcss@8.5.6)
stream-template: 0.0.10
webfontloader: 1.6.28
'@clinic/trace-events-parser': 2.0.0
'@tensorflow/tfjs-backend-cpu': 3.21.0(@tensorflow/tfjs-core@3.21.0(encoding@0.1.13))
'@tensorflow/tfjs-core': 3.21.0(encoding@0.1.13)
- async: 3.2.5
+ async: 3.2.6
clipboard-copy: 4.0.1
d3-array: 2.12.1
d3-axis: 1.0.12
d3-selection: 1.4.2
d3-shape: 1.3.7
d3-time-format: 2.3.0
- debug: 4.3.4
+ debug: 4.4.1
distributions: 2.2.0
endpoint: 0.4.5
hidden-markov-model-tf: 4.0.0(@tensorflow/tfjs-core@3.21.0(encoding@0.1.13))
mkdirp: 1.0.4
on-net-listen: 1.1.2
protocol-buffers: 4.2.0
- pump: 3.0.0
+ pump: 3.0.3
pumpify: 2.0.1
- semver: 7.6.2
+ semver: 7.7.2
showdown: 1.9.1
stream-template: 0.0.10
streaming-json-stringify: 3.1.0
'@clinic/flame@13.0.0':
dependencies:
- 0x: 5.7.0
+ 0x: 5.8.0
'@clinic/clinic-common': 7.1.0
copy-to-clipboard: 3.3.3
d3-array: 2.12.1
d3-selection: 1.4.2
flame-gradient: 1.0.0
lodash.debounce: 4.0.8
- pump: 3.0.0
+ pump: 3.0.3
querystringify: 2.2.0
rimraf: 3.0.2
transitivePeerDependencies:
d3-array: 2.12.1
d3-fg: 6.14.0
d3-selection: 1.4.2
- fs-extra: 11.2.0
+ fs-extra: 11.3.0
lodash.debounce: 4.0.8
on-net-listen: 1.1.2
- pump: 3.0.0
+ pump: 3.0.3
querystringify: 2.2.0
sinusoidal-decimal: 1.0.0
dependencies:
'@clinic/trace-events-parser': 2.0.0
multistream: 2.1.1
- pump: 3.0.0
+ pump: 3.0.3
through2: 2.0.5
'@clinic/trace-events-parser@2.0.0':
'@colors/colors@1.6.0': {}
- '@commitlint/cli@19.3.0(@types/node@20.12.12)(typescript@5.4.5)':
+ '@commitlint/cli@19.8.1(@types/node@24.0.10)(typescript@5.8.3)':
dependencies:
- '@commitlint/format': 19.3.0
- '@commitlint/lint': 19.2.2
- '@commitlint/load': 19.2.0(@types/node@20.12.12)(typescript@5.4.5)
- '@commitlint/read': 19.2.1
- '@commitlint/types': 19.0.3
- execa: 8.0.1
+ '@commitlint/format': 19.8.1
+ '@commitlint/lint': 19.8.1
+ '@commitlint/load': 19.8.1(@types/node@24.0.10)(typescript@5.8.3)
+ '@commitlint/read': 19.8.1
+ '@commitlint/types': 19.8.1
+ tinyexec: 1.0.1
yargs: 17.7.2
transitivePeerDependencies:
- '@types/node'
- typescript
- '@commitlint/config-conventional@19.2.2':
+ '@commitlint/config-conventional@19.8.1':
dependencies:
- '@commitlint/types': 19.0.3
+ '@commitlint/types': 19.8.1
conventional-changelog-conventionalcommits: 7.0.2
- '@commitlint/config-validator@19.0.3':
+ '@commitlint/config-validator@19.8.1':
dependencies:
- '@commitlint/types': 19.0.3
- ajv: 8.13.0
+ '@commitlint/types': 19.8.1
+ ajv: 8.17.1
- '@commitlint/ensure@19.0.3':
+ '@commitlint/ensure@19.8.1':
dependencies:
- '@commitlint/types': 19.0.3
+ '@commitlint/types': 19.8.1
lodash.camelcase: 4.3.0
lodash.kebabcase: 4.1.1
lodash.snakecase: 4.1.1
lodash.startcase: 4.4.0
lodash.upperfirst: 4.3.1
- '@commitlint/execute-rule@19.0.0': {}
+ '@commitlint/execute-rule@19.8.1': {}
- '@commitlint/format@19.3.0':
+ '@commitlint/format@19.8.1':
dependencies:
- '@commitlint/types': 19.0.3
- chalk: 5.3.0
+ '@commitlint/types': 19.8.1
+ chalk: 5.4.1
- '@commitlint/is-ignored@19.2.2':
+ '@commitlint/is-ignored@19.8.1':
dependencies:
- '@commitlint/types': 19.0.3
- semver: 7.6.2
+ '@commitlint/types': 19.8.1
+ semver: 7.7.2
- '@commitlint/lint@19.2.2':
+ '@commitlint/lint@19.8.1':
dependencies:
- '@commitlint/is-ignored': 19.2.2
- '@commitlint/parse': 19.0.3
- '@commitlint/rules': 19.0.3
- '@commitlint/types': 19.0.3
+ '@commitlint/is-ignored': 19.8.1
+ '@commitlint/parse': 19.8.1
+ '@commitlint/rules': 19.8.1
+ '@commitlint/types': 19.8.1
- '@commitlint/load@19.2.0(@types/node@20.12.12)(typescript@5.4.5)':
+ '@commitlint/load@19.8.1(@types/node@24.0.10)(typescript@5.8.3)':
dependencies:
- '@commitlint/config-validator': 19.0.3
- '@commitlint/execute-rule': 19.0.0
- '@commitlint/resolve-extends': 19.1.0
- '@commitlint/types': 19.0.3
- chalk: 5.3.0
- cosmiconfig: 9.0.0(typescript@5.4.5)
- cosmiconfig-typescript-loader: 5.0.0(@types/node@20.12.12)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5)
+ '@commitlint/config-validator': 19.8.1
+ '@commitlint/execute-rule': 19.8.1
+ '@commitlint/resolve-extends': 19.8.1
+ '@commitlint/types': 19.8.1
+ chalk: 5.4.1
+ cosmiconfig: 9.0.0(typescript@5.8.3)
+ cosmiconfig-typescript-loader: 6.1.0(@types/node@24.0.10)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3)
lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2
lodash.uniq: 4.5.0
- '@types/node'
- typescript
- '@commitlint/message@19.0.0': {}
+ '@commitlint/message@19.8.1': {}
- '@commitlint/parse@19.0.3':
+ '@commitlint/parse@19.8.1':
dependencies:
- '@commitlint/types': 19.0.3
+ '@commitlint/types': 19.8.1
conventional-changelog-angular: 7.0.0
conventional-commits-parser: 5.0.0
- '@commitlint/read@19.2.1':
+ '@commitlint/read@19.8.1':
dependencies:
- '@commitlint/top-level': 19.0.0
- '@commitlint/types': 19.0.3
- execa: 8.0.1
+ '@commitlint/top-level': 19.8.1
+ '@commitlint/types': 19.8.1
git-raw-commits: 4.0.0
minimist: 1.2.8
+ tinyexec: 1.0.1
- '@commitlint/resolve-extends@19.1.0':
+ '@commitlint/resolve-extends@19.8.1':
dependencies:
- '@commitlint/config-validator': 19.0.3
- '@commitlint/types': 19.0.3
+ '@commitlint/config-validator': 19.8.1
+ '@commitlint/types': 19.8.1
global-directory: 4.0.1
import-meta-resolve: 4.1.0
lodash.mergewith: 4.6.2
resolve-from: 5.0.0
- '@commitlint/rules@19.0.3':
+ '@commitlint/rules@19.8.1':
dependencies:
- '@commitlint/ensure': 19.0.3
- '@commitlint/message': 19.0.0
- '@commitlint/to-lines': 19.0.0
- '@commitlint/types': 19.0.3
- execa: 8.0.1
+ '@commitlint/ensure': 19.8.1
+ '@commitlint/message': 19.8.1
+ '@commitlint/to-lines': 19.8.1
+ '@commitlint/types': 19.8.1
- '@commitlint/to-lines@19.0.0': {}
+ '@commitlint/to-lines@19.8.1': {}
- '@commitlint/top-level@19.0.0':
+ '@commitlint/top-level@19.8.1':
dependencies:
find-up: 7.0.0
- '@commitlint/types@19.0.3':
+ '@commitlint/types@19.8.1':
+ dependencies:
+ '@types/conventional-commits-parser': 5.0.1
+ chalk: 5.4.1
+
+ '@cspell/cspell-bundled-dicts@9.1.2':
+ dependencies:
+ '@cspell/dict-ada': 4.1.0
+ '@cspell/dict-al': 1.1.0
+ '@cspell/dict-aws': 4.0.10
+ '@cspell/dict-bash': 4.2.0
+ '@cspell/dict-companies': 3.2.1
+ '@cspell/dict-cpp': 6.0.8
+ '@cspell/dict-cryptocurrencies': 5.0.4
+ '@cspell/dict-csharp': 4.0.6
+ '@cspell/dict-css': 4.0.17
+ '@cspell/dict-dart': 2.3.0
+ '@cspell/dict-data-science': 2.0.8
+ '@cspell/dict-django': 4.1.4
+ '@cspell/dict-docker': 1.1.14
+ '@cspell/dict-dotnet': 5.0.9
+ '@cspell/dict-elixir': 4.0.7
+ '@cspell/dict-en-common-misspellings': 2.1.2
+ '@cspell/dict-en-gb-mit': 3.1.3
+ '@cspell/dict-en_us': 4.4.13
+ '@cspell/dict-filetypes': 3.0.12
+ '@cspell/dict-flutter': 1.1.0
+ '@cspell/dict-fonts': 4.0.4
+ '@cspell/dict-fsharp': 1.1.0
+ '@cspell/dict-fullstack': 3.2.6
+ '@cspell/dict-gaming-terms': 1.1.1
+ '@cspell/dict-git': 3.0.6
+ '@cspell/dict-golang': 6.0.22
+ '@cspell/dict-google': 1.0.8
+ '@cspell/dict-haskell': 4.0.5
+ '@cspell/dict-html': 4.0.11
+ '@cspell/dict-html-symbol-entities': 4.0.3
+ '@cspell/dict-java': 5.0.11
+ '@cspell/dict-julia': 1.1.0
+ '@cspell/dict-k8s': 1.0.11
+ '@cspell/dict-kotlin': 1.1.0
+ '@cspell/dict-latex': 4.0.3
+ '@cspell/dict-lorem-ipsum': 4.0.4
+ '@cspell/dict-lua': 4.0.7
+ '@cspell/dict-makefile': 1.0.4
+ '@cspell/dict-markdown': 2.0.11(@cspell/dict-css@4.0.17)(@cspell/dict-html-symbol-entities@4.0.3)(@cspell/dict-html@4.0.11)(@cspell/dict-typescript@3.2.2)
+ '@cspell/dict-monkeyc': 1.0.10
+ '@cspell/dict-node': 5.0.7
+ '@cspell/dict-npm': 5.2.9
+ '@cspell/dict-php': 4.0.14
+ '@cspell/dict-powershell': 5.0.14
+ '@cspell/dict-public-licenses': 2.0.13
+ '@cspell/dict-python': 4.2.18
+ '@cspell/dict-r': 2.1.0
+ '@cspell/dict-ruby': 5.0.8
+ '@cspell/dict-rust': 4.0.11
+ '@cspell/dict-scala': 5.0.7
+ '@cspell/dict-shell': 1.1.0
+ '@cspell/dict-software-terms': 5.1.2
+ '@cspell/dict-sql': 2.2.0
+ '@cspell/dict-svelte': 1.0.6
+ '@cspell/dict-swift': 2.0.5
+ '@cspell/dict-terraform': 1.1.1
+ '@cspell/dict-typescript': 3.2.2
+ '@cspell/dict-vue': 3.0.4
+
+ '@cspell/cspell-pipe@9.1.2': {}
+
+ '@cspell/cspell-resolver@9.1.2':
dependencies:
- '@types/conventional-commits-parser': 5.0.0
- chalk: 5.3.0
+ global-directory: 4.0.1
- '@cspotcode/source-map-support@0.8.1':
+ '@cspell/cspell-service-bus@9.1.2': {}
+
+ '@cspell/cspell-types@9.1.2': {}
+
+ '@cspell/dict-ada@4.1.0': {}
+
+ '@cspell/dict-al@1.1.0': {}
+
+ '@cspell/dict-aws@4.0.10': {}
+
+ '@cspell/dict-bash@4.2.0':
dependencies:
- '@jridgewell/trace-mapping': 0.3.9
+ '@cspell/dict-shell': 1.1.0
- '@dabh/diagnostics@2.0.3':
+ '@cspell/dict-companies@3.2.1': {}
+
+ '@cspell/dict-cpp@6.0.8': {}
+
+ '@cspell/dict-cryptocurrencies@5.0.4': {}
+
+ '@cspell/dict-csharp@4.0.6': {}
+
+ '@cspell/dict-css@4.0.17': {}
+
+ '@cspell/dict-dart@2.3.0': {}
+
+ '@cspell/dict-data-science@2.0.8': {}
+
+ '@cspell/dict-django@4.1.4': {}
+
+ '@cspell/dict-docker@1.1.14': {}
+
+ '@cspell/dict-dotnet@5.0.9': {}
+
+ '@cspell/dict-elixir@4.0.7': {}
+
+ '@cspell/dict-en-common-misspellings@2.1.2': {}
+
+ '@cspell/dict-en-gb-mit@3.1.3': {}
+
+ '@cspell/dict-en_us@4.4.13': {}
+
+ '@cspell/dict-filetypes@3.0.12': {}
+
+ '@cspell/dict-flutter@1.1.0': {}
+
+ '@cspell/dict-fonts@4.0.4': {}
+
+ '@cspell/dict-fsharp@1.1.0': {}
+
+ '@cspell/dict-fullstack@3.2.6': {}
+
+ '@cspell/dict-gaming-terms@1.1.1': {}
+
+ '@cspell/dict-git@3.0.6': {}
+
+ '@cspell/dict-golang@6.0.22': {}
+
+ '@cspell/dict-google@1.0.8': {}
+
+ '@cspell/dict-haskell@4.0.5': {}
+
+ '@cspell/dict-html-symbol-entities@4.0.3': {}
+
+ '@cspell/dict-html@4.0.11': {}
+
+ '@cspell/dict-java@5.0.11': {}
+
+ '@cspell/dict-julia@1.1.0': {}
+
+ '@cspell/dict-k8s@1.0.11': {}
+
+ '@cspell/dict-kotlin@1.1.0': {}
+
+ '@cspell/dict-latex@4.0.3': {}
+
+ '@cspell/dict-lorem-ipsum@4.0.4': {}
+
+ '@cspell/dict-lua@4.0.7': {}
+
+ '@cspell/dict-makefile@1.0.4': {}
+
+ '@cspell/dict-markdown@2.0.11(@cspell/dict-css@4.0.17)(@cspell/dict-html-symbol-entities@4.0.3)(@cspell/dict-html@4.0.11)(@cspell/dict-typescript@3.2.2)':
dependencies:
- colorspace: 1.1.4
- enabled: 2.0.0
- kuler: 2.0.0
+ '@cspell/dict-css': 4.0.17
+ '@cspell/dict-html': 4.0.11
+ '@cspell/dict-html-symbol-entities': 4.0.3
+ '@cspell/dict-typescript': 3.2.2
+
+ '@cspell/dict-monkeyc@1.0.10': {}
+
+ '@cspell/dict-node@5.0.7': {}
+
+ '@cspell/dict-npm@5.2.9': {}
+
+ '@cspell/dict-php@4.0.14': {}
+
+ '@cspell/dict-powershell@5.0.14': {}
+
+ '@cspell/dict-public-licenses@2.0.13': {}
- '@es-joy/jsdoccomment@0.43.0':
+ '@cspell/dict-python@4.2.18':
dependencies:
- '@types/eslint': 8.56.10
- '@types/estree': 1.0.5
- '@typescript-eslint/types': 7.10.0
- comment-parser: 1.4.1
- esquery: 1.5.0
- jsdoc-type-pratt-parser: 4.0.0
+ '@cspell/dict-data-science': 2.0.8
- '@esbuild/aix-ppc64@0.20.2':
- optional: true
+ '@cspell/dict-r@2.1.0': {}
- '@esbuild/aix-ppc64@0.21.3':
- optional: true
+ '@cspell/dict-ruby@5.0.8': {}
+
+ '@cspell/dict-rust@4.0.11': {}
+
+ '@cspell/dict-scala@5.0.7': {}
+
+ '@cspell/dict-shell@1.1.0': {}
+
+ '@cspell/dict-software-terms@5.1.2': {}
+
+ '@cspell/dict-sql@2.2.0': {}
+
+ '@cspell/dict-svelte@1.0.6': {}
+
+ '@cspell/dict-swift@2.0.5': {}
+
+ '@cspell/dict-terraform@1.1.1': {}
+
+ '@cspell/dict-typescript@3.2.2': {}
+
+ '@cspell/dict-vue@3.0.4': {}
+
+ '@cspell/dynamic-import@9.1.2':
+ dependencies:
+ '@cspell/url': 9.1.2
+ import-meta-resolve: 4.1.0
- '@esbuild/android-arm64@0.20.2':
- optional: true
+ '@cspell/eslint-plugin@9.1.2(eslint@9.30.1(jiti@2.4.2))':
+ dependencies:
+ '@cspell/cspell-types': 9.1.2
+ '@cspell/url': 9.1.2
+ cspell-lib: 9.1.2
+ eslint: 9.30.1(jiti@2.4.2)
+ synckit: 0.11.8
- '@esbuild/android-arm64@0.21.3':
- optional: true
+ '@cspell/filetypes@9.1.2': {}
- '@esbuild/android-arm@0.20.2':
- optional: true
+ '@cspell/strong-weak-map@9.1.2': {}
- '@esbuild/android-arm@0.21.3':
- optional: true
+ '@cspell/url@9.1.2': {}
- '@esbuild/android-x64@0.20.2':
- optional: true
+ '@cspotcode/source-map-support@0.8.1':
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.9
- '@esbuild/android-x64@0.21.3':
- optional: true
+ '@csstools/color-helpers@5.0.2': {}
- '@esbuild/darwin-arm64@0.20.2':
- optional: true
+ '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
+ dependencies:
+ '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-tokenizer': 3.0.4
- '@esbuild/darwin-arm64@0.21.3':
- optional: true
+ '@csstools/css-color-parser@3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
+ dependencies:
+ '@csstools/color-helpers': 5.0.2
+ '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-tokenizer': 3.0.4
- '@esbuild/darwin-x64@0.20.2':
- optional: true
+ '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)':
+ dependencies:
+ '@csstools/css-tokenizer': 3.0.4
- '@esbuild/darwin-x64@0.21.3':
- optional: true
+ '@csstools/css-tokenizer@3.0.4': {}
- '@esbuild/freebsd-arm64@0.20.2':
- optional: true
+ '@dabh/diagnostics@2.0.3':
+ dependencies:
+ colorspace: 1.1.4
+ enabled: 2.0.0
+ kuler: 2.0.0
- '@esbuild/freebsd-arm64@0.21.3':
+ '@emnapi/core@1.4.3':
+ dependencies:
+ '@emnapi/wasi-threads': 1.0.2
+ tslib: 2.8.1
optional: true
- '@esbuild/freebsd-x64@0.20.2':
+ '@emnapi/runtime@1.4.3':
+ dependencies:
+ tslib: 2.8.1
optional: true
- '@esbuild/freebsd-x64@0.21.3':
+ '@emnapi/wasi-threads@1.0.2':
+ dependencies:
+ tslib: 2.8.1
optional: true
- '@esbuild/linux-arm64@0.20.2':
- optional: true
+ '@es-joy/jsdoccomment@0.52.0':
+ dependencies:
+ '@types/estree': 1.0.8
+ '@typescript-eslint/types': 8.35.1
+ comment-parser: 1.4.1
+ esquery: 1.6.0
+ jsdoc-type-pratt-parser: 4.1.0
- '@esbuild/linux-arm64@0.21.3':
+ '@esbuild/aix-ppc64@0.25.5':
optional: true
- '@esbuild/linux-arm@0.20.2':
+ '@esbuild/android-arm64@0.25.5':
optional: true
- '@esbuild/linux-arm@0.21.3':
+ '@esbuild/android-arm@0.25.5':
optional: true
- '@esbuild/linux-ia32@0.20.2':
+ '@esbuild/android-x64@0.25.5':
optional: true
- '@esbuild/linux-ia32@0.21.3':
+ '@esbuild/darwin-arm64@0.25.5':
optional: true
- '@esbuild/linux-loong64@0.20.2':
+ '@esbuild/darwin-x64@0.25.5':
optional: true
- '@esbuild/linux-loong64@0.21.3':
+ '@esbuild/freebsd-arm64@0.25.5':
optional: true
- '@esbuild/linux-mips64el@0.20.2':
+ '@esbuild/freebsd-x64@0.25.5':
optional: true
- '@esbuild/linux-mips64el@0.21.3':
+ '@esbuild/linux-arm64@0.25.5':
optional: true
- '@esbuild/linux-ppc64@0.20.2':
+ '@esbuild/linux-arm@0.25.5':
optional: true
- '@esbuild/linux-ppc64@0.21.3':
+ '@esbuild/linux-ia32@0.25.5':
optional: true
- '@esbuild/linux-riscv64@0.20.2':
+ '@esbuild/linux-loong64@0.25.5':
optional: true
- '@esbuild/linux-riscv64@0.21.3':
+ '@esbuild/linux-mips64el@0.25.5':
optional: true
- '@esbuild/linux-s390x@0.20.2':
+ '@esbuild/linux-ppc64@0.25.5':
optional: true
- '@esbuild/linux-s390x@0.21.3':
+ '@esbuild/linux-riscv64@0.25.5':
optional: true
- '@esbuild/linux-x64@0.20.2':
+ '@esbuild/linux-s390x@0.25.5':
optional: true
- '@esbuild/linux-x64@0.21.3':
+ '@esbuild/linux-x64@0.25.5':
optional: true
- '@esbuild/netbsd-x64@0.20.2':
+ '@esbuild/netbsd-arm64@0.25.5':
optional: true
- '@esbuild/netbsd-x64@0.21.3':
+ '@esbuild/netbsd-x64@0.25.5':
optional: true
- '@esbuild/openbsd-x64@0.20.2':
+ '@esbuild/openbsd-arm64@0.25.5':
optional: true
- '@esbuild/openbsd-x64@0.21.3':
+ '@esbuild/openbsd-x64@0.25.5':
optional: true
- '@esbuild/sunos-x64@0.20.2':
+ '@esbuild/sunos-x64@0.25.5':
optional: true
- '@esbuild/sunos-x64@0.21.3':
+ '@esbuild/win32-arm64@0.25.5':
optional: true
- '@esbuild/win32-arm64@0.20.2':
+ '@esbuild/win32-ia32@0.25.5':
optional: true
- '@esbuild/win32-arm64@0.21.3':
+ '@esbuild/win32-x64@0.25.5':
optional: true
- '@esbuild/win32-ia32@0.20.2':
- optional: true
+ '@eslint-community/eslint-utils@4.7.0(eslint@9.30.1(jiti@2.4.2))':
+ dependencies:
+ eslint: 9.30.1(jiti@2.4.2)
+ eslint-visitor-keys: 3.4.3
- '@esbuild/win32-ia32@0.21.3':
- optional: true
+ '@eslint-community/regexpp@4.12.1': {}
- '@esbuild/win32-x64@0.20.2':
- optional: true
+ '@eslint/config-array@0.21.0':
+ dependencies:
+ '@eslint/object-schema': 2.1.6
+ debug: 4.4.1
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
- '@esbuild/win32-x64@0.21.3':
- optional: true
+ '@eslint/config-helpers@0.3.0': {}
- '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)':
+ '@eslint/core@0.14.0':
dependencies:
- eslint: 8.57.0
- eslint-visitor-keys: 3.4.3
+ '@types/json-schema': 7.0.15
- '@eslint-community/regexpp@4.10.0': {}
+ '@eslint/core@0.15.1':
+ dependencies:
+ '@types/json-schema': 7.0.15
- '@eslint/eslintrc@2.1.4':
+ '@eslint/eslintrc@3.3.1':
dependencies:
ajv: 6.12.6
- debug: 4.3.4
- espree: 9.6.1
- globals: 13.24.0
- ignore: 5.3.1
- import-fresh: 3.3.0
+ debug: 4.4.1
+ espree: 10.4.0
+ globals: 14.0.0
+ ignore: 5.3.2
+ import-fresh: 3.3.1
js-yaml: 4.1.0
minimatch: 3.1.2
strip-json-comments: 3.1.1
transitivePeerDependencies:
- supports-color
- '@eslint/js@8.57.0': {}
+ '@eslint/js@9.30.1': {}
+
+ '@eslint/object-schema@2.1.6': {}
+
+ '@eslint/plugin-kit@0.3.3':
+ dependencies:
+ '@eslint/core': 0.15.1
+ levn: 0.4.1
'@gar/promisify@1.1.3':
optional: true
- '@humanwhocodes/config-array@0.11.14':
+ '@humanfs/core@0.19.1': {}
+
+ '@humanfs/node@0.16.6':
dependencies:
- '@humanwhocodes/object-schema': 2.0.3
- debug: 4.3.4
- minimatch: 3.1.2
- transitivePeerDependencies:
- - supports-color
+ '@humanfs/core': 0.19.1
+ '@humanwhocodes/retry': 0.3.1
+
+ '@humanwhocodes/gitignore-to-minimatch@1.0.2': {}
'@humanwhocodes/module-importer@1.0.1': {}
- '@humanwhocodes/object-schema@2.0.3': {}
+ '@humanwhocodes/retry@0.3.1': {}
- '@iarna/toml@2.2.5': {}
+ '@humanwhocodes/retry@0.4.3': {}
- '@inquirer/figures@1.0.2': {}
+ '@isaacs/balanced-match@4.0.1': {}
+
+ '@isaacs/brace-expansion@5.0.0':
+ dependencies:
+ '@isaacs/balanced-match': 4.0.1
'@isaacs/cliui@8.0.2':
dependencies:
'@isaacs/fs-minipass@4.0.1':
dependencies:
- minipass: 7.1.1
+ minipass: 7.1.2
'@istanbuljs/schema@0.1.3': {}
'@jercle/yargonaut@1.1.5':
dependencies:
chalk: 4.1.2
- figlet: 1.7.0
+ figlet: 1.8.1
parent-require: 1.0.0
- '@jest/expect-utils@29.7.0':
- dependencies:
- jest-get-type: 29.6.3
-
- '@jest/schemas@29.6.3':
- dependencies:
- '@sinclair/typebox': 0.27.8
-
- '@jest/types@29.6.3':
- dependencies:
- '@jest/schemas': 29.6.3
- '@types/istanbul-lib-coverage': 2.0.6
- '@types/istanbul-reports': 3.0.4
- '@types/node': 20.12.12
- '@types/yargs': 17.0.32
- chalk: 4.1.2
-
- '@jridgewell/gen-mapping@0.3.5':
+ '@jridgewell/gen-mapping@0.3.12':
dependencies:
- '@jridgewell/set-array': 1.2.1
- '@jridgewell/sourcemap-codec': 1.4.15
- '@jridgewell/trace-mapping': 0.3.25
+ '@jridgewell/sourcemap-codec': 1.5.4
+ '@jridgewell/trace-mapping': 0.3.29
'@jridgewell/resolve-uri@3.1.2': {}
- '@jridgewell/set-array@1.2.1': {}
+ '@jridgewell/sourcemap-codec@1.5.4': {}
- '@jridgewell/sourcemap-codec@1.4.15': {}
-
- '@jridgewell/trace-mapping@0.3.25':
+ '@jridgewell/trace-mapping@0.3.29':
dependencies:
'@jridgewell/resolve-uri': 3.1.2
- '@jridgewell/sourcemap-codec': 1.4.15
+ '@jridgewell/sourcemap-codec': 1.5.4
'@jridgewell/trace-mapping@0.3.9':
dependencies:
'@jridgewell/resolve-uri': 3.1.2
- '@jridgewell/sourcemap-codec': 1.4.15
+ '@jridgewell/sourcemap-codec': 1.5.4
- '@ljharb/through@2.3.13':
+ '@jsr/std__assert@1.0.13':
dependencies:
- call-bind: 1.0.7
+ '@jsr/std__internal': 1.0.9
- '@microsoft/tsdoc-config@0.16.2':
+ '@jsr/std__expect@1.0.16':
dependencies:
- '@microsoft/tsdoc': 0.14.2
- ajv: 6.12.6
- jju: 1.4.0
- resolve: 1.19.0
+ '@jsr/std__assert': 1.0.13
+ '@jsr/std__internal': 1.0.9
- '@microsoft/tsdoc@0.14.2': {}
+ '@jsr/std__internal@1.0.9': {}
- '@mikro-orm/cli@6.2.7':
+ '@mikro-orm/cli@6.4.16(mariadb@3.4.2)':
dependencies:
'@jercle/yargonaut': 1.1.5
- '@mikro-orm/core': 6.2.7
- '@mikro-orm/knex': 6.2.7(@mikro-orm/core@6.2.7)(sqlite3@5.1.7)
- fs-extra: 11.2.0
+ '@mikro-orm/core': 6.4.16
+ '@mikro-orm/knex': 6.4.16(@mikro-orm/core@6.4.16)(mariadb@3.4.2)(sqlite3@5.1.7)
+ fs-extra: 11.3.0
tsconfig-paths: 4.2.0
yargs: 17.7.2
transitivePeerDependencies:
- better-sqlite3
+ - libsql
+ - mariadb
- mysql
- mysql2
- pg
- supports-color
- tedious
- '@mikro-orm/core@6.2.7':
+ '@mikro-orm/core@6.4.16':
dependencies:
- dataloader: 2.2.2
- dotenv: 16.4.5
+ dataloader: 2.2.3
+ dotenv: 16.5.0
esprima: 4.0.1
- fs-extra: 11.2.0
+ fs-extra: 11.3.0
globby: 11.1.0
- mikro-orm: 6.2.7
+ mikro-orm: 6.4.16
reflect-metadata: 0.2.2
- '@mikro-orm/knex@6.2.7(@mikro-orm/core@6.2.7)(sqlite3@5.1.7)':
+ '@mikro-orm/knex@6.4.16(@mikro-orm/core@6.4.16)(mariadb@3.4.2)(sqlite3@5.1.7)':
dependencies:
- '@mikro-orm/core': 6.2.7
- fs-extra: 11.2.0
+ '@mikro-orm/core': 6.4.16
+ fs-extra: 11.3.0
knex: 3.1.0(sqlite3@5.1.7)
sqlstring: 2.3.3
+ optionalDependencies:
+ mariadb: 3.4.2
transitivePeerDependencies:
- - better-sqlite3
- mysql
- mysql2
- pg
- supports-color
- tedious
- '@mikro-orm/mariadb@6.2.7(@mikro-orm/core@6.2.7)':
+ '@mikro-orm/mariadb@6.4.16(@mikro-orm/core@6.4.16)':
dependencies:
- '@mikro-orm/core': 6.2.7
- '@mikro-orm/knex': 6.2.7(@mikro-orm/core@6.2.7)(sqlite3@5.1.7)
- mariadb: 3.3.0
+ '@mikro-orm/core': 6.4.16
+ '@mikro-orm/knex': 6.4.16(@mikro-orm/core@6.4.16)(mariadb@3.4.2)(sqlite3@5.1.7)
+ mariadb: 3.4.2
transitivePeerDependencies:
- better-sqlite3
+ - libsql
- mysql
- mysql2
- pg
- supports-color
- tedious
- '@mikro-orm/reflection@6.2.7(@mikro-orm/core@6.2.7)':
+ '@mikro-orm/reflection@6.4.16(@mikro-orm/core@6.4.16)':
dependencies:
- '@mikro-orm/core': 6.2.7
+ '@mikro-orm/core': 6.4.16
globby: 11.1.0
- ts-morph: 22.0.0
+ ts-morph: 26.0.0
- '@mikro-orm/sqlite@6.2.7(@mikro-orm/core@6.2.7)':
+ '@mikro-orm/sqlite@6.4.16(@mikro-orm/core@6.4.16)(mariadb@3.4.2)':
dependencies:
- '@mikro-orm/core': 6.2.7
- '@mikro-orm/knex': 6.2.7(@mikro-orm/core@6.2.7)(sqlite3@5.1.7)
- fs-extra: 11.2.0
+ '@mikro-orm/core': 6.4.16
+ '@mikro-orm/knex': 6.4.16(@mikro-orm/core@6.4.16)(mariadb@3.4.2)(sqlite3@5.1.7)
+ fs-extra: 11.3.0
sqlite3: 5.1.7
sqlstring-sqlite: 0.1.1
transitivePeerDependencies:
- better-sqlite3
- bluebird
+ - libsql
+ - mariadb
- mysql
- mysql2
- pg
- supports-color
- tedious
- '@mongodb-js/saslprep@1.1.7':
+ '@mongodb-js/saslprep@1.3.0':
dependencies:
sparse-bitfield: 3.0.3
+ '@napi-rs/wasm-runtime@0.2.11':
+ dependencies:
+ '@emnapi/core': 1.4.3
+ '@emnapi/runtime': 1.4.3
+ '@tybys/wasm-util': 0.9.0
+ optional: true
+
'@nearform/heap-profiler@2.0.0':
dependencies:
abort-controller: 3.0.0
'@nodelib/fs.walk@1.2.8':
dependencies:
'@nodelib/fs.scandir': 2.1.5
- fastq: 1.17.1
+ fastq: 1.19.1
+
+ '@nolyfill/is-core-module@1.0.39': {}
'@npmcli/fs@1.1.1':
dependencies:
'@gar/promisify': 1.1.3
- semver: 7.6.2
+ semver: 7.7.2
optional: true
'@npmcli/move-file@1.1.2':
rimraf: 3.0.2
optional: true
- '@octokit/auth-token@4.0.0': {}
-
- '@octokit/core@5.2.0':
- dependencies:
- '@octokit/auth-token': 4.0.0
- '@octokit/graphql': 7.1.0
- '@octokit/request': 8.4.0
- '@octokit/request-error': 5.1.0
- '@octokit/types': 13.5.0
- before-after-hook: 2.2.3
- universal-user-agent: 6.0.1
-
- '@octokit/endpoint@9.0.5':
- dependencies:
- '@octokit/types': 13.5.0
- universal-user-agent: 6.0.1
-
- '@octokit/graphql@7.1.0':
- dependencies:
- '@octokit/request': 8.4.0
- '@octokit/types': 13.5.0
- universal-user-agent: 6.0.1
-
- '@octokit/openapi-types@22.2.0': {}
-
- '@octokit/plugin-paginate-rest@11.3.1(@octokit/core@5.2.0)':
- dependencies:
- '@octokit/core': 5.2.0
- '@octokit/types': 13.5.0
-
- '@octokit/plugin-request-log@4.0.1(@octokit/core@5.2.0)':
- dependencies:
- '@octokit/core': 5.2.0
-
- '@octokit/plugin-rest-endpoint-methods@13.2.2(@octokit/core@5.2.0)':
- dependencies:
- '@octokit/core': 5.2.0
- '@octokit/types': 13.5.0
-
- '@octokit/request-error@5.1.0':
- dependencies:
- '@octokit/types': 13.5.0
- deprecation: 2.3.1
- once: 1.4.0
-
- '@octokit/request@8.4.0':
- dependencies:
- '@octokit/endpoint': 9.0.5
- '@octokit/request-error': 5.1.0
- '@octokit/types': 13.5.0
- universal-user-agent: 6.0.1
-
- '@octokit/rest@20.1.1':
- dependencies:
- '@octokit/core': 5.2.0
- '@octokit/plugin-paginate-rest': 11.3.1(@octokit/core@5.2.0)
- '@octokit/plugin-request-log': 4.0.1(@octokit/core@5.2.0)
- '@octokit/plugin-rest-endpoint-methods': 13.2.2(@octokit/core@5.2.0)
-
- '@octokit/types@13.5.0':
- dependencies:
- '@octokit/openapi-types': 22.2.0
-
'@one-ini/wasm@0.1.1': {}
'@pkgjs/parseargs@0.11.0':
optional: true
- '@pkgr/core@0.1.1': {}
+ '@pkgr/core@0.2.7': {}
- '@pnpm/config.env-replace@1.1.0': {}
+ '@rolldown/pluginutils@1.0.0-beta.19': {}
- '@pnpm/network.ca-file@1.0.2':
- dependencies:
- graceful-fs: 4.2.10
+ '@rolldown/pluginutils@1.0.0-beta.23': {}
- '@pnpm/npm-conf@2.2.2':
- dependencies:
- '@pnpm/config.env-replace': 1.1.0
- '@pnpm/network.ca-file': 1.0.2
- config-chain: 1.1.13
+ '@rollup/rollup-android-arm-eabi@4.44.1':
+ optional: true
- '@release-it/bumper@6.0.1(release-it@17.3.0(typescript@5.4.5))':
- dependencies:
- '@iarna/toml': 2.2.5
- detect-indent: 7.0.1
- fast-glob: 3.3.2
- ini: 4.1.2
- js-yaml: 4.1.0
- lodash-es: 4.17.21
- release-it: 17.3.0(typescript@5.4.5)
- semver: 7.6.2
+ '@rollup/rollup-android-arm64@4.44.1':
+ optional: true
- '@rollup/rollup-android-arm-eabi@4.17.2':
+ '@rollup/rollup-darwin-arm64@4.44.1':
optional: true
- '@rollup/rollup-android-arm64@4.17.2':
+ '@rollup/rollup-darwin-x64@4.44.1':
optional: true
- '@rollup/rollup-darwin-arm64@4.17.2':
+ '@rollup/rollup-freebsd-arm64@4.44.1':
optional: true
- '@rollup/rollup-darwin-x64@4.17.2':
+ '@rollup/rollup-freebsd-x64@4.44.1':
optional: true
- '@rollup/rollup-linux-arm-gnueabihf@4.17.2':
+ '@rollup/rollup-linux-arm-gnueabihf@4.44.1':
optional: true
- '@rollup/rollup-linux-arm-musleabihf@4.17.2':
+ '@rollup/rollup-linux-arm-musleabihf@4.44.1':
optional: true
- '@rollup/rollup-linux-arm64-gnu@4.17.2':
+ '@rollup/rollup-linux-arm64-gnu@4.44.1':
optional: true
- '@rollup/rollup-linux-arm64-musl@4.17.2':
+ '@rollup/rollup-linux-arm64-musl@4.44.1':
optional: true
- '@rollup/rollup-linux-powerpc64le-gnu@4.17.2':
+ '@rollup/rollup-linux-loongarch64-gnu@4.44.1':
optional: true
- '@rollup/rollup-linux-riscv64-gnu@4.17.2':
+ '@rollup/rollup-linux-powerpc64le-gnu@4.44.1':
optional: true
- '@rollup/rollup-linux-s390x-gnu@4.17.2':
+ '@rollup/rollup-linux-riscv64-gnu@4.44.1':
optional: true
- '@rollup/rollup-linux-x64-gnu@4.17.2':
+ '@rollup/rollup-linux-riscv64-musl@4.44.1':
optional: true
- '@rollup/rollup-linux-x64-musl@4.17.2':
+ '@rollup/rollup-linux-s390x-gnu@4.44.1':
optional: true
- '@rollup/rollup-win32-arm64-msvc@4.17.2':
+ '@rollup/rollup-linux-x64-gnu@4.44.1':
optional: true
- '@rollup/rollup-win32-ia32-msvc@4.17.2':
+ '@rollup/rollup-linux-x64-musl@4.44.1':
optional: true
- '@rollup/rollup-win32-x64-msvc@4.17.2':
+ '@rollup/rollup-win32-arm64-msvc@4.44.1':
optional: true
- '@rushstack/eslint-patch@1.10.3': {}
+ '@rollup/rollup-win32-ia32-msvc@4.44.1':
+ optional: true
- '@sinclair/typebox@0.27.8': {}
+ '@rollup/rollup-win32-x64-msvc@4.44.1':
+ optional: true
'@sindresorhus/is@5.6.0': {}
- '@sindresorhus/merge-streams@2.3.0': {}
+ '@stylistic/eslint-plugin@2.11.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)':
+ dependencies:
+ '@typescript-eslint/utils': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
+ eslint: 9.30.1(jiti@2.4.2)
+ eslint-visitor-keys: 4.2.1
+ espree: 10.4.0
+ estraverse: 5.3.0
+ picomatch: 4.0.2
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
'@szmarczak/http-timer@5.0.1':
dependencies:
'@tootallnate/once@1.1.2':
optional: true
- '@tootallnate/quickjs-emscripten@0.23.0': {}
-
- '@ts-morph/common@0.23.0':
+ '@ts-morph/common@0.27.0':
dependencies:
- fast-glob: 3.3.2
- minimatch: 9.0.4
- mkdirp: 3.0.1
+ fast-glob: 3.3.3
+ minimatch: 10.0.3
path-browserify: 1.0.1
'@tsconfig/node10@1.0.11': {}
'@tsconfig/node16@1.0.4': {}
- '@tsconfig/node20@20.1.4': {}
+ '@tsconfig/node22@22.0.2': {}
+
+ '@tybys/wasm-util@0.9.0':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
- '@types/conventional-commits-parser@5.0.0':
+ '@types/chai@5.2.2':
dependencies:
- '@types/node': 20.12.12
+ '@types/deep-eql': 4.0.2
- '@types/eslint@8.56.10':
+ '@types/conventional-commits-parser@5.0.1':
dependencies:
- '@types/estree': 1.0.5
- '@types/json-schema': 7.0.15
+ '@types/node': 24.0.10
+
+ '@types/deep-eql@4.0.2': {}
- '@types/estree@1.0.5': {}
+ '@types/estree@1.0.8': {}
- '@types/geojson@7946.0.14': {}
+ '@types/geojson@7946.0.16': {}
'@types/http-cache-semantics@4.0.4': {}
'@types/istanbul-lib-coverage@2.0.6': {}
- '@types/istanbul-lib-report@3.0.3':
- dependencies:
- '@types/istanbul-lib-coverage': 2.0.6
-
- '@types/istanbul-reports@3.0.4':
- dependencies:
- '@types/istanbul-lib-report': 3.0.3
-
- '@types/jsdom@21.1.6':
+ '@types/jsdom@21.1.7':
dependencies:
- '@types/node': 20.12.12
+ '@types/node': 24.0.10
'@types/tough-cookie': 4.0.5
- parse5: 7.1.2
+ parse5: 7.3.0
'@types/json-schema@7.0.15': {}
- '@types/json5@0.0.29': {}
-
'@types/long@4.0.2': {}
- '@types/node@20.12.12':
+ '@types/node@22.16.0':
+ dependencies:
+ undici-types: 6.21.0
+
+ '@types/node@24.0.10':
dependencies:
- undici-types: 5.26.5
+ undici-types: 7.8.0
'@types/offscreencanvas@2019.3.0': {}
'@types/seedrandom@2.4.34': {}
- '@types/semver@7.5.8': {}
-
- '@types/stack-utils@2.0.3': {}
+ '@types/semver@7.7.0': {}
'@types/tough-cookie@4.0.5': {}
dependencies:
'@types/webidl-conversions': 7.0.3
- '@types/ws@8.5.10':
- dependencies:
- '@types/node': 20.12.12
-
- '@types/yargs-parser@21.0.3': {}
-
- '@types/yargs@17.0.32':
+ '@types/ws@8.18.1':
dependencies:
- '@types/yargs-parser': 21.0.3
+ '@types/node': 24.0.10
- '@typescript-eslint/eslint-plugin@7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)':
+ '@typescript-eslint/eslint-plugin@8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
- '@eslint-community/regexpp': 4.10.0
- '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.4.5)
- '@typescript-eslint/scope-manager': 7.10.0
- '@typescript-eslint/type-utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5)
- '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5)
- '@typescript-eslint/visitor-keys': 7.10.0
- eslint: 8.57.0
+ '@eslint-community/regexpp': 4.12.1
+ '@typescript-eslint/parser': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
+ '@typescript-eslint/scope-manager': 8.35.1
+ '@typescript-eslint/type-utils': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
+ '@typescript-eslint/utils': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
+ '@typescript-eslint/visitor-keys': 8.35.1
+ eslint: 9.30.1(jiti@2.4.2)
graphemer: 1.4.0
- ignore: 5.3.1
+ ignore: 7.0.5
natural-compare: 1.4.0
- ts-api-utils: 1.3.0(typescript@5.4.5)
- optionalDependencies:
- typescript: 5.4.5
+ ts-api-utils: 2.1.0(typescript@5.8.3)
+ typescript: 5.8.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5)':
+ '@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
- '@typescript-eslint/scope-manager': 7.10.0
- '@typescript-eslint/types': 7.10.0
- '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5)
- '@typescript-eslint/visitor-keys': 7.10.0
- debug: 4.3.4
- eslint: 8.57.0
- optionalDependencies:
- typescript: 5.4.5
+ '@typescript-eslint/scope-manager': 8.35.1
+ '@typescript-eslint/types': 8.35.1
+ '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.8.3)
+ '@typescript-eslint/visitor-keys': 8.35.1
+ debug: 4.4.1
+ eslint: 9.30.1(jiti@2.4.2)
+ typescript: 5.8.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/scope-manager@7.10.0':
+ '@typescript-eslint/project-service@8.35.1(typescript@5.8.3)':
dependencies:
- '@typescript-eslint/types': 7.10.0
- '@typescript-eslint/visitor-keys': 7.10.0
+ '@typescript-eslint/tsconfig-utils': 8.35.1(typescript@5.8.3)
+ '@typescript-eslint/types': 8.35.1
+ debug: 4.4.1
+ typescript: 5.8.3
+ transitivePeerDependencies:
+ - supports-color
- '@typescript-eslint/type-utils@7.10.0(eslint@8.57.0)(typescript@5.4.5)':
+ '@typescript-eslint/scope-manager@8.35.1':
dependencies:
- '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5)
- '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5)
- debug: 4.3.4
- eslint: 8.57.0
- ts-api-utils: 1.3.0(typescript@5.4.5)
- optionalDependencies:
- typescript: 5.4.5
+ '@typescript-eslint/types': 8.35.1
+ '@typescript-eslint/visitor-keys': 8.35.1
+
+ '@typescript-eslint/tsconfig-utils@8.35.1(typescript@5.8.3)':
+ dependencies:
+ typescript: 5.8.3
+
+ '@typescript-eslint/type-utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)':
+ dependencies:
+ '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.8.3)
+ '@typescript-eslint/utils': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
+ debug: 4.4.1
+ eslint: 9.30.1(jiti@2.4.2)
+ ts-api-utils: 2.1.0(typescript@5.8.3)
+ typescript: 5.8.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/types@7.10.0': {}
+ '@typescript-eslint/types@8.35.1': {}
- '@typescript-eslint/typescript-estree@7.10.0(typescript@5.4.5)':
+ '@typescript-eslint/typescript-estree@8.35.1(typescript@5.8.3)':
dependencies:
- '@typescript-eslint/types': 7.10.0
- '@typescript-eslint/visitor-keys': 7.10.0
- debug: 4.3.4
- globby: 11.1.0
+ '@typescript-eslint/project-service': 8.35.1(typescript@5.8.3)
+ '@typescript-eslint/tsconfig-utils': 8.35.1(typescript@5.8.3)
+ '@typescript-eslint/types': 8.35.1
+ '@typescript-eslint/visitor-keys': 8.35.1
+ debug: 4.4.1
+ fast-glob: 3.3.3
is-glob: 4.0.3
- minimatch: 9.0.4
- semver: 7.6.2
- ts-api-utils: 1.3.0(typescript@5.4.5)
- optionalDependencies:
- typescript: 5.4.5
+ minimatch: 9.0.5
+ semver: 7.7.2
+ ts-api-utils: 2.1.0(typescript@5.8.3)
+ typescript: 5.8.3
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@7.10.0(eslint@8.57.0)(typescript@5.4.5)':
+ '@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
- '@typescript-eslint/scope-manager': 7.10.0
- '@typescript-eslint/types': 7.10.0
- '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5)
- eslint: 8.57.0
+ '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1(jiti@2.4.2))
+ '@typescript-eslint/scope-manager': 8.35.1
+ '@typescript-eslint/types': 8.35.1
+ '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.8.3)
+ eslint: 9.30.1(jiti@2.4.2)
+ typescript: 5.8.3
transitivePeerDependencies:
- supports-color
- - typescript
- '@typescript-eslint/visitor-keys@7.10.0':
+ '@typescript-eslint/visitor-keys@8.35.1':
dependencies:
- '@typescript-eslint/types': 7.10.0
- eslint-visitor-keys: 3.4.3
+ '@typescript-eslint/types': 8.35.1
+ eslint-visitor-keys: 4.2.1
+
+ '@unrs/resolver-binding-android-arm-eabi@1.10.1':
+ optional: true
+
+ '@unrs/resolver-binding-android-arm64@1.10.1':
+ optional: true
+
+ '@unrs/resolver-binding-darwin-arm64@1.10.1':
+ optional: true
+
+ '@unrs/resolver-binding-darwin-x64@1.10.1':
+ optional: true
+
+ '@unrs/resolver-binding-freebsd-x64@1.10.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-arm-gnueabihf@1.10.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-arm-musleabihf@1.10.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-arm64-gnu@1.10.1':
+ optional: true
- '@ungap/structured-clone@1.2.0': {}
+ '@unrs/resolver-binding-linux-arm64-musl@1.10.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-ppc64-gnu@1.10.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-riscv64-gnu@1.10.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-riscv64-musl@1.10.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-s390x-gnu@1.10.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-x64-gnu@1.10.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-x64-musl@1.10.1':
+ optional: true
+
+ '@unrs/resolver-binding-wasm32-wasi@1.10.1':
+ dependencies:
+ '@napi-rs/wasm-runtime': 0.2.11
+ optional: true
- '@vitejs/plugin-vue-jsx@3.1.0(vite@5.2.11(@types/node@20.12.12))(vue@3.4.27(typescript@5.4.5))':
+ '@unrs/resolver-binding-win32-arm64-msvc@1.10.1':
+ optional: true
+
+ '@unrs/resolver-binding-win32-ia32-msvc@1.10.1':
+ optional: true
+
+ '@unrs/resolver-binding-win32-x64-msvc@1.10.1':
+ optional: true
+
+ '@vitejs/plugin-vue-jsx@5.0.1(vite@7.0.2(@types/node@24.0.10)(jiti@2.4.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))':
dependencies:
- '@babel/core': 7.24.5
- '@babel/plugin-transform-typescript': 7.24.5(@babel/core@7.24.5)
- '@vue/babel-plugin-jsx': 1.2.2(@babel/core@7.24.5)
- vite: 5.2.11(@types/node@20.12.12)
- vue: 3.4.27(typescript@5.4.5)
+ '@babel/core': 7.28.0
+ '@babel/plugin-transform-typescript': 7.28.0(@babel/core@7.28.0)
+ '@rolldown/pluginutils': 1.0.0-beta.23
+ '@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.28.0)
+ vite: 7.0.2(@types/node@24.0.10)(jiti@2.4.2)(tsx@4.20.3)(yaml@2.8.0)
+ vue: 3.5.17(typescript@5.8.3)
transitivePeerDependencies:
- supports-color
- '@vitejs/plugin-vue@5.0.4(vite@5.2.11(@types/node@20.12.12))(vue@3.4.27(typescript@5.4.5))':
+ '@vitejs/plugin-vue@6.0.0(vite@7.0.2(@types/node@24.0.10)(jiti@2.4.2)(tsx@4.20.3)(yaml@2.8.0))(vue@3.5.17(typescript@5.8.3))':
dependencies:
- vite: 5.2.11(@types/node@20.12.12)
- vue: 3.4.27(typescript@5.4.5)
+ '@rolldown/pluginutils': 1.0.0-beta.19
+ vite: 7.0.2(@types/node@24.0.10)(jiti@2.4.2)(tsx@4.20.3)(yaml@2.8.0)
+ vue: 3.5.17(typescript@5.8.3)
- '@vitest/coverage-v8@1.6.0(vitest@1.6.0(@types/node@20.12.12)(jsdom@24.0.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)))':
+ '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/node@24.0.10)(jiti@2.4.2)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(tsx@4.20.3)(yaml@2.8.0))':
dependencies:
'@ampproject/remapping': 2.3.0
- '@bcoe/v8-coverage': 0.2.3
- debug: 4.3.4
+ '@bcoe/v8-coverage': 1.0.2
+ ast-v8-to-istanbul: 0.3.3
+ debug: 4.4.1
istanbul-lib-coverage: 3.2.2
istanbul-lib-report: 3.0.1
- istanbul-lib-source-maps: 5.0.4
+ istanbul-lib-source-maps: 5.0.6
istanbul-reports: 3.1.7
- magic-string: 0.30.10
- magicast: 0.3.4
- picocolors: 1.0.1
- std-env: 3.7.0
- strip-literal: 2.1.0
- test-exclude: 6.0.0
- vitest: 1.6.0(@types/node@20.12.12)(jsdom@24.0.0(bufferutil@4.0.8)(utf-8-validate@6.0.4))
+ magic-string: 0.30.17
+ magicast: 0.3.5
+ std-env: 3.9.0
+ test-exclude: 7.0.1
+ tinyrainbow: 2.0.0
+ vitest: 3.2.4(@types/node@24.0.10)(jiti@2.4.2)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(tsx@4.20.3)(yaml@2.8.0)
transitivePeerDependencies:
- supports-color
- '@vitest/expect@1.6.0':
+ '@vitest/expect@3.2.4':
+ dependencies:
+ '@types/chai': 5.2.2
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
+ chai: 5.2.0
+ tinyrainbow: 2.0.0
+
+ '@vitest/mocker@3.2.4(vite@7.0.2(@types/node@24.0.10)(jiti@2.4.2)(tsx@4.20.3)(yaml@2.8.0))':
dependencies:
- '@vitest/spy': 1.6.0
- '@vitest/utils': 1.6.0
- chai: 4.4.1
+ '@vitest/spy': 3.2.4
+ estree-walker: 3.0.3
+ magic-string: 0.30.17
+ optionalDependencies:
+ vite: 7.0.2(@types/node@24.0.10)(jiti@2.4.2)(tsx@4.20.3)(yaml@2.8.0)
- '@vitest/runner@1.6.0':
+ '@vitest/pretty-format@3.2.4':
dependencies:
- '@vitest/utils': 1.6.0
- p-limit: 5.0.0
- pathe: 1.1.2
+ tinyrainbow: 2.0.0
- '@vitest/snapshot@1.6.0':
+ '@vitest/runner@3.2.4':
dependencies:
- magic-string: 0.30.10
- pathe: 1.1.2
- pretty-format: 29.7.0
+ '@vitest/utils': 3.2.4
+ pathe: 2.0.3
+ strip-literal: 3.0.0
- '@vitest/spy@1.6.0':
+ '@vitest/snapshot@3.2.4':
dependencies:
- tinyspy: 2.2.1
+ '@vitest/pretty-format': 3.2.4
+ magic-string: 0.30.17
+ pathe: 2.0.3
- '@vitest/utils@1.6.0':
+ '@vitest/spy@3.2.4':
dependencies:
- diff-sequences: 29.6.3
- estree-walker: 3.0.3
- loupe: 2.3.7
- pretty-format: 29.7.0
+ tinyspy: 4.0.3
- '@vue/babel-helper-vue-transform-on@1.2.2': {}
+ '@vitest/utils@3.2.4':
+ dependencies:
+ '@vitest/pretty-format': 3.2.4
+ loupe: 3.1.4
+ tinyrainbow: 2.0.0
+
+ '@vue/babel-helper-vue-transform-on@1.4.0': {}
- '@vue/babel-plugin-jsx@1.2.2(@babel/core@7.24.5)':
+ '@vue/babel-plugin-jsx@1.4.0(@babel/core@7.28.0)':
dependencies:
- '@babel/helper-module-imports': 7.22.15
- '@babel/helper-plugin-utils': 7.24.5
- '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5)
- '@babel/template': 7.24.0
- '@babel/traverse': 7.24.5
- '@babel/types': 7.24.5
- '@vue/babel-helper-vue-transform-on': 1.2.2
- '@vue/babel-plugin-resolve-type': 1.2.2(@babel/core@7.24.5)
- camelcase: 6.3.0
- html-tags: 3.3.1
- svg-tags: 1.0.0
+ '@babel/helper-module-imports': 7.27.1
+ '@babel/helper-plugin-utils': 7.27.1
+ '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0)
+ '@babel/template': 7.27.2
+ '@babel/traverse': 7.28.0
+ '@babel/types': 7.28.0
+ '@vue/babel-helper-vue-transform-on': 1.4.0
+ '@vue/babel-plugin-resolve-type': 1.4.0(@babel/core@7.28.0)
+ '@vue/shared': 3.5.17
optionalDependencies:
- '@babel/core': 7.24.5
+ '@babel/core': 7.28.0
transitivePeerDependencies:
- supports-color
- '@vue/babel-plugin-resolve-type@1.2.2(@babel/core@7.24.5)':
+ '@vue/babel-plugin-resolve-type@1.4.0(@babel/core@7.28.0)':
dependencies:
- '@babel/code-frame': 7.24.2
- '@babel/core': 7.24.5
- '@babel/helper-module-imports': 7.22.15
- '@babel/helper-plugin-utils': 7.24.5
- '@babel/parser': 7.24.5
- '@vue/compiler-sfc': 3.4.27
+ '@babel/code-frame': 7.27.1
+ '@babel/core': 7.28.0
+ '@babel/helper-module-imports': 7.27.1
+ '@babel/helper-plugin-utils': 7.27.1
+ '@babel/parser': 7.28.0
+ '@vue/compiler-sfc': 3.5.17
+ transitivePeerDependencies:
+ - supports-color
- '@vue/compiler-core@3.4.27':
+ '@vue/compiler-core@3.5.17':
dependencies:
- '@babel/parser': 7.24.5
- '@vue/shared': 3.4.27
+ '@babel/parser': 7.28.0
+ '@vue/shared': 3.5.17
entities: 4.5.0
estree-walker: 2.0.2
- source-map-js: 1.2.0
+ source-map-js: 1.2.1
- '@vue/compiler-dom@3.4.27':
+ '@vue/compiler-dom@3.5.17':
dependencies:
- '@vue/compiler-core': 3.4.27
- '@vue/shared': 3.4.27
+ '@vue/compiler-core': 3.5.17
+ '@vue/shared': 3.5.17
- '@vue/compiler-sfc@3.4.27':
+ '@vue/compiler-sfc@3.5.17':
dependencies:
- '@babel/parser': 7.24.5
- '@vue/compiler-core': 3.4.27
- '@vue/compiler-dom': 3.4.27
- '@vue/compiler-ssr': 3.4.27
- '@vue/shared': 3.4.27
+ '@babel/parser': 7.28.0
+ '@vue/compiler-core': 3.5.17
+ '@vue/compiler-dom': 3.5.17
+ '@vue/compiler-ssr': 3.5.17
+ '@vue/shared': 3.5.17
estree-walker: 2.0.2
- magic-string: 0.30.10
- postcss: 8.4.38
- source-map-js: 1.2.0
-
- '@vue/compiler-ssr@3.4.27':
- dependencies:
- '@vue/compiler-dom': 3.4.27
- '@vue/shared': 3.4.27
-
- '@vue/devtools-api@6.6.1': {}
+ magic-string: 0.30.17
+ postcss: 8.5.6
+ source-map-js: 1.2.1
- '@vue/eslint-config-prettier@9.0.0(@types/eslint@8.56.10)(eslint@8.57.0)(prettier@3.2.5)':
+ '@vue/compiler-ssr@3.5.17':
dependencies:
- eslint: 8.57.0
- eslint-config-prettier: 9.1.0(eslint@8.57.0)
- eslint-plugin-prettier: 5.1.3(@types/eslint@8.56.10)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5)
- prettier: 3.2.5
- transitivePeerDependencies:
- - '@types/eslint'
+ '@vue/compiler-dom': 3.5.17
+ '@vue/shared': 3.5.17
- '@vue/eslint-config-typescript@13.0.0(eslint-plugin-vue@9.26.0(eslint@8.57.0))(eslint@8.57.0)(typescript@5.4.5)':
- dependencies:
- '@typescript-eslint/eslint-plugin': 7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)
- '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.4.5)
- eslint: 8.57.0
- eslint-plugin-vue: 9.26.0(eslint@8.57.0)
- vue-eslint-parser: 9.4.2(eslint@8.57.0)
- optionalDependencies:
- typescript: 5.4.5
- transitivePeerDependencies:
- - supports-color
+ '@vue/devtools-api@6.6.4': {}
- '@vue/reactivity@3.4.27':
+ '@vue/reactivity@3.5.17':
dependencies:
- '@vue/shared': 3.4.27
+ '@vue/shared': 3.5.17
- '@vue/runtime-core@3.4.27':
+ '@vue/runtime-core@3.5.17':
dependencies:
- '@vue/reactivity': 3.4.27
- '@vue/shared': 3.4.27
+ '@vue/reactivity': 3.5.17
+ '@vue/shared': 3.5.17
- '@vue/runtime-dom@3.4.27':
+ '@vue/runtime-dom@3.5.17':
dependencies:
- '@vue/runtime-core': 3.4.27
- '@vue/shared': 3.4.27
+ '@vue/reactivity': 3.5.17
+ '@vue/runtime-core': 3.5.17
+ '@vue/shared': 3.5.17
csstype: 3.1.3
- '@vue/server-renderer@3.4.27(vue@3.4.27(typescript@5.4.5))':
+ '@vue/server-renderer@3.5.17(vue@3.5.17(typescript@5.8.3))':
dependencies:
- '@vue/compiler-ssr': 3.4.27
- '@vue/shared': 3.4.27
- vue: 3.4.27(typescript@5.4.5)
+ '@vue/compiler-ssr': 3.5.17
+ '@vue/shared': 3.5.17
+ vue: 3.5.17(typescript@5.8.3)
- '@vue/shared@3.4.27': {}
+ '@vue/shared@3.5.17': {}
'@vue/test-utils@2.4.6':
dependencies:
- js-beautify: 1.15.1
- vue-component-type-helpers: 2.0.19
+ js-beautify: 1.15.4
+ vue-component-type-helpers: 2.2.12
- '@vue/tsconfig@0.5.1': {}
+ '@vue/tsconfig@0.7.0(typescript@5.8.3)(vue@3.5.17(typescript@5.8.3))':
+ optionalDependencies:
+ typescript: 5.8.3
+ vue: 3.5.17(typescript@5.8.3)
'@webgpu/types@0.1.16': {}
dependencies:
event-target-shim: 5.0.1
- acorn-jsx@5.3.2(acorn@8.11.3):
+ acorn-jsx@5.3.2(acorn@8.15.0):
dependencies:
- acorn: 8.11.3
+ acorn: 8.15.0
acorn-node@1.8.2:
dependencies:
acorn-walk@7.2.0: {}
- acorn-walk@8.3.2: {}
+ acorn-walk@8.3.4:
+ dependencies:
+ acorn: 8.15.0
acorn@7.4.1: {}
- acorn@8.11.3: {}
+ acorn@8.15.0: {}
agent-base@6.0.2:
dependencies:
- debug: 4.3.4
+ debug: 4.4.1
transitivePeerDependencies:
- supports-color
optional: true
- agent-base@7.1.1:
- dependencies:
- debug: 4.3.4
- transitivePeerDependencies:
- - supports-color
+ agent-base@7.1.3: {}
- agentkeepalive@4.5.0:
+ agentkeepalive@4.6.0:
dependencies:
humanize-ms: 1.2.1
optional: true
clean-stack: 2.2.0
indent-string: 4.0.0
- ajv-formats@2.1.1(ajv@8.13.0):
+ ajv-formats@2.1.1(ajv@8.17.1):
optionalDependencies:
- ajv: 8.13.0
+ ajv: 8.17.1
- ajv-formats@3.0.1(ajv@8.13.0):
+ ajv-formats@3.0.1(ajv@8.17.1):
optionalDependencies:
- ajv: 8.13.0
+ ajv: 8.17.1
ajv@6.12.6:
dependencies:
json-schema-traverse: 0.4.1
uri-js: 4.4.1
- ajv@8.13.0:
+ ajv@8.17.1:
dependencies:
fast-deep-equal: 3.1.3
+ fast-uri: 3.0.6
json-schema-traverse: 1.0.0
require-from-string: 2.0.2
- uri-js: 4.4.1
ansi-align@3.0.1:
dependencies:
ansi-escapes@3.2.0: {}
- ansi-escapes@4.3.2:
+ ansi-escapes@7.0.0:
dependencies:
- type-fest: 0.21.3
-
- ansi-escapes@6.2.1: {}
+ environment: 1.1.0
ansi-regex@2.1.1: {}
ansi-regex@5.0.1: {}
- ansi-regex@6.0.1: {}
+ ansi-regex@6.1.0: {}
ansi-styles@2.2.1: {}
dependencies:
color-convert: 2.0.1
- ansi-styles@5.2.0: {}
-
ansi-styles@6.2.1: {}
any-shell-escape@0.1.1: {}
argparse@2.0.1: {}
- array-buffer-byte-length@1.0.1:
+ array-buffer-byte-length@1.0.2:
dependencies:
- call-bind: 1.0.7
- is-array-buffer: 3.0.4
+ call-bound: 1.0.4
+ is-array-buffer: 3.0.5
array-flatten@3.0.0: {}
array-ify@1.0.0: {}
- array-includes@3.1.8:
+ array-includes@3.1.9:
dependencies:
- call-bind: 1.0.7
+ call-bind: 1.0.8
+ call-bound: 1.0.4
define-properties: 1.2.1
- es-abstract: 1.23.3
- es-object-atoms: 1.0.0
- get-intrinsic: 1.2.4
- is-string: 1.0.7
+ es-abstract: 1.24.0
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ is-string: 1.1.1
+ math-intrinsics: 1.1.0
+
+ array-timsort@1.0.3: {}
array-union@2.1.0: {}
- array.prototype.findlastindex@1.2.5:
+ array.prototype.findlast@1.2.5:
dependencies:
- call-bind: 1.0.7
+ call-bind: 1.0.8
define-properties: 1.2.1
- es-abstract: 1.23.3
+ es-abstract: 1.24.0
es-errors: 1.3.0
- es-object-atoms: 1.0.0
- es-shim-unscopables: 1.0.2
+ es-object-atoms: 1.1.1
+ es-shim-unscopables: 1.1.0
- array.prototype.flat@1.3.2:
+ array.prototype.flat@1.3.3:
dependencies:
- call-bind: 1.0.7
+ call-bind: 1.0.8
define-properties: 1.2.1
- es-abstract: 1.23.3
- es-shim-unscopables: 1.0.2
+ es-abstract: 1.24.0
+ es-shim-unscopables: 1.1.0
- array.prototype.flatmap@1.3.2:
+ array.prototype.flatmap@1.3.3:
dependencies:
- call-bind: 1.0.7
+ call-bind: 1.0.8
define-properties: 1.2.1
- es-abstract: 1.23.3
- es-shim-unscopables: 1.0.2
+ es-abstract: 1.24.0
+ es-shim-unscopables: 1.1.0
- array.prototype.map@1.0.7:
+ array.prototype.tosorted@1.1.4:
dependencies:
- call-bind: 1.0.7
+ call-bind: 1.0.8
define-properties: 1.2.1
- es-abstract: 1.23.3
- es-array-method-boxes-properly: 1.0.0
- es-object-atoms: 1.0.0
- is-string: 1.0.7
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ es-shim-unscopables: 1.1.0
- arraybuffer.prototype.slice@1.0.3:
+ arraybuffer.prototype.slice@1.0.4:
dependencies:
- array-buffer-byte-length: 1.0.1
- call-bind: 1.0.7
+ array-buffer-byte-length: 1.0.2
+ call-bind: 1.0.8
define-properties: 1.2.1
- es-abstract: 1.23.3
+ es-abstract: 1.24.0
es-errors: 1.3.0
- get-intrinsic: 1.2.4
- is-array-buffer: 3.0.4
- is-shared-array-buffer: 1.0.3
+ get-intrinsic: 1.3.0
+ is-array-buffer: 3.0.5
asn1.js@4.10.1:
dependencies:
- bn.js: 4.12.0
+ bn.js: 4.12.2
inherits: 2.0.4
minimalistic-assert: 1.0.1
assert@1.5.1:
dependencies:
- object.assign: 4.1.5
+ object.assign: 4.1.7
util: 0.10.4
- assertion-error@1.1.0: {}
+ assertion-error@2.0.1: {}
- ast-types@0.13.4:
+ ast-v8-to-istanbul@0.3.3:
dependencies:
- tslib: 2.6.2
+ '@jridgewell/trace-mapping': 0.3.29
+ estree-walker: 3.0.3
+ js-tokens: 9.0.1
- async-retry@1.3.3:
- dependencies:
- retry: 0.13.1
+ async-function@1.0.0: {}
async@2.6.4:
dependencies:
lodash: 4.17.21
- async@3.2.5: {}
+ async@3.2.6: {}
asynckit@0.4.0: {}
atomically@1.7.0: {}
- auto-changelog@2.4.0(encoding@0.1.13):
- dependencies:
- commander: 7.2.0
- handlebars: 4.7.8
- node-fetch: 2.7.0(encoding@0.1.13)
- parse-github-url: 1.0.2
- semver: 7.6.2
- transitivePeerDependencies:
- - encoding
-
autocannon@7.15.0:
dependencies:
chalk: 4.1.2
cli-table3: 0.6.5
color-support: 1.1.3
cross-argv: 2.0.0
- form-data: 4.0.0
+ form-data: 4.0.3
has-async-hooks: 1.0.0
- hdr-histogram-js: 3.0.0
+ hdr-histogram-js: 3.0.1
hdr-histogram-percentiles-obj: 3.0.0
- http-parser-js: 0.5.8
- hyperid: 3.2.0
+ http-parser-js: 0.5.10
+ hyperid: 3.3.0
lodash.chunk: 4.2.0
lodash.clonedeep: 4.5.0
lodash.flatten: 4.4.0
progress: 2.0.3
reinterval: 1.1.0
retimer: 3.0.0
- semver: 7.6.2
+ semver: 7.7.2
subarg: 1.0.0
timestring: 6.0.0
available-typed-arrays@1.0.7:
dependencies:
- possible-typed-array-names: 1.0.0
+ possible-typed-array-names: 1.1.0
aws-sign2@0.7.0: {}
- aws4@1.13.0: {}
+ aws4@1.13.2: {}
- b4a@1.6.6: {}
+ b4a@1.6.7: {}
balanced-match@1.0.2: {}
dependencies:
tweetnacl: 0.14.5
- before-after-hook@2.2.3: {}
-
binary-extensions@2.3.0: {}
bindings@1.5.0:
inherits: 2.0.4
readable-stream: 3.6.2
- bn.js@4.12.0: {}
+ bn.js@4.12.2: {}
- bn.js@5.2.1: {}
+ bn.js@5.2.2: {}
boolbase@1.0.0: {}
widest-line: 3.1.0
wrap-ansi: 7.0.0
- boxen@7.1.1:
- dependencies:
- ansi-align: 3.0.1
- camelcase: 7.0.1
- chalk: 5.3.0
- cli-boxes: 3.0.0
- string-width: 5.1.2
- type-fest: 2.19.0
- widest-line: 4.0.1
- wrap-ansi: 8.1.0
-
- brace-expansion@1.1.11:
+ brace-expansion@1.1.12:
dependencies:
balanced-match: 1.0.2
concat-map: 0.0.1
- brace-expansion@2.0.1:
+ brace-expansion@2.0.2:
dependencies:
balanced-match: 1.0.2
brfs@2.0.2:
dependencies:
quote-stream: 1.0.2
- resolve: 1.22.8
+ resolve: 1.22.10
static-module: 3.0.4
through2: 2.0.5
browser-resolve@2.0.0:
dependencies:
- resolve: 1.22.8
+ resolve: 1.22.10
browserify-aes@1.2.0:
dependencies:
buffer-xor: 1.0.3
- cipher-base: 1.0.4
+ cipher-base: 1.0.6
create-hash: 1.2.0
evp_bytestokey: 1.0.3
inherits: 2.0.4
browserify-des@1.0.2:
dependencies:
- cipher-base: 1.0.4
+ cipher-base: 1.0.6
des.js: 1.1.0
inherits: 2.0.4
safe-buffer: 5.2.1
- browserify-rsa@4.1.0:
+ browserify-rsa@4.1.1:
dependencies:
- bn.js: 5.2.1
+ bn.js: 5.2.2
randombytes: 2.1.0
+ safe-buffer: 5.2.1
browserify-sign@4.2.3:
dependencies:
- bn.js: 5.2.1
- browserify-rsa: 4.1.0
+ bn.js: 5.2.2
+ browserify-rsa: 4.1.1
create-hash: 1.2.0
create-hmac: 1.1.7
- elliptic: 6.5.5
- hash-base: 3.0.4
+ elliptic: 6.6.1
+ hash-base: 3.0.5
inherits: 2.0.4
parse-asn1: 5.1.7
readable-stream: 2.3.8
dependencies:
pako: 1.0.11
- browserify@17.0.0:
+ browserify@17.0.1:
dependencies:
JSONStream: 1.3.5
assert: 1.5.1
concat-stream: 1.6.2
console-browserify: 1.2.0
constants-browserify: 1.0.0
- crypto-browserify: 3.12.0
+ crypto-browserify: 3.12.1
defined: 1.0.1
deps-sort: 2.0.1
domain-browser: 1.2.0
duplexer2: 0.1.4
events: 3.3.0
glob: 7.2.3
- has: 1.0.4
+ hasown: 2.0.2
htmlescape: 1.1.1
https-browserify: 1.0.0
inherits: 2.0.4
querystring-es3: 0.2.1
read-only-stream: 2.0.0
readable-stream: 2.3.8
- resolve: 1.22.8
+ resolve: 1.22.10
shasum-object: 1.0.0
- shell-quote: 1.8.1
+ shell-quote: 1.8.3
stream-browserify: 3.0.0
stream-http: 3.2.0
string_decoder: 1.3.0
through2: 2.0.5
timers-browserify: 1.4.2
tty-browserify: 0.0.1
- url: 0.11.3
+ url: 0.11.4
util: 0.12.5
vm-browserify: 1.1.2
xtend: 4.0.2
- browserslist@4.23.0:
+ browserslist@4.25.1:
dependencies:
- caniuse-lite: 1.0.30001620
- electron-to-chromium: 1.4.776
- node-releases: 2.0.14
- update-browserslist-db: 1.0.16(browserslist@4.23.0)
+ caniuse-lite: 1.0.30001726
+ electron-to-chromium: 1.5.179
+ node-releases: 2.0.19
+ update-browserslist-db: 1.1.3(browserslist@4.25.1)
- bson@6.7.0: {}
+ bson@6.10.4: {}
buffer-equal@0.0.1: {}
base64-js: 1.5.1
ieee754: 1.2.1
- bufferutil@4.0.8:
+ bufferutil@4.0.9:
dependencies:
- node-gyp-build: 4.8.1
+ node-gyp-build: 4.8.4
optional: true
- builtin-modules@3.3.0: {}
-
builtin-status-codes@3.0.0: {}
- bundle-name@4.1.0:
- dependencies:
- run-applescript: 7.0.0
-
- c8@9.1.0:
+ c8@10.1.3:
dependencies:
- '@bcoe/v8-coverage': 0.2.3
+ '@bcoe/v8-coverage': 1.0.2
'@istanbuljs/schema': 0.1.3
find-up: 5.0.0
- foreground-child: 3.1.1
+ foreground-child: 3.3.1
istanbul-lib-coverage: 3.2.2
istanbul-lib-report: 3.0.1
istanbul-reports: 3.1.7
- test-exclude: 6.0.0
- v8-to-istanbul: 9.2.0
+ test-exclude: 7.0.1
+ v8-to-istanbul: 9.3.0
yargs: 17.7.2
yargs-parser: 21.1.1
dependencies:
'@types/http-cache-semantics': 4.0.4
get-stream: 6.0.1
- http-cache-semantics: 4.1.1
+ http-cache-semantics: 4.2.0
keyv: 4.5.4
mimic-response: 4.0.0
- normalize-url: 8.0.1
+ normalize-url: 8.0.2
responselike: 3.0.0
cached-path-relative@1.1.0: {}
- call-bind@1.0.7:
+ call-bind-apply-helpers@1.0.2:
dependencies:
- es-define-property: 1.0.0
es-errors: 1.3.0
function-bind: 1.1.2
- get-intrinsic: 1.2.4
+
+ call-bind@1.0.8:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-define-property: 1.0.1
+ get-intrinsic: 1.3.0
set-function-length: 1.2.2
+ call-bound@1.0.4:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ get-intrinsic: 1.3.0
+
callsites@3.1.0: {}
camel-case@3.0.0:
camelcase@6.3.0: {}
- camelcase@7.0.1: {}
-
- caniuse-lite@1.0.30001620: {}
+ caniuse-lite@1.0.30001726: {}
caseless@0.12.0: {}
cephes@2.0.0: {}
- chai@4.4.1:
+ chai@5.2.0:
dependencies:
- assertion-error: 1.1.0
- check-error: 1.0.3
- deep-eql: 4.1.3
- get-func-name: 2.0.2
- loupe: 2.3.7
- pathval: 1.1.1
- type-detect: 4.0.8
+ assertion-error: 2.0.1
+ check-error: 2.1.1
+ deep-eql: 5.0.2
+ loupe: 3.1.4
+ pathval: 2.0.1
chalk@1.1.3:
dependencies:
ansi-styles: 4.3.0
supports-color: 7.2.0
- chalk@5.3.0: {}
+ chalk@5.4.1: {}
char-spinner@1.0.1: {}
chardet@0.7.0: {}
- check-error@1.0.3:
- dependencies:
- get-func-name: 2.0.2
+ check-error@2.1.1: {}
chokidar@3.6.0:
dependencies:
ci-info@2.0.0: {}
- ci-info@3.9.0: {}
-
- cipher-base@1.0.4:
+ cipher-base@1.0.6:
dependencies:
inherits: 2.0.4
safe-buffer: 5.2.1
clean-stack@2.2.0: {}
- cli-boxes@2.2.1: {}
+ clear-module@4.1.2:
+ dependencies:
+ parent-module: 2.0.0
+ resolve-from: 5.0.0
- cli-boxes@3.0.0: {}
+ cli-boxes@2.2.1: {}
cli-cursor@2.1.0:
dependencies:
dependencies:
restore-cursor: 3.1.0
- cli-cursor@4.0.0:
+ cli-cursor@5.0.0:
dependencies:
- restore-cursor: 4.0.0
+ restore-cursor: 5.1.0
cli-spinners@2.9.2: {}
cli-truncate@4.0.0:
dependencies:
slice-ansi: 5.0.0
- string-width: 7.1.0
+ string-width: 7.2.0
cli-width@2.2.1: {}
- cli-width@4.1.0: {}
-
clinic@13.0.0(encoding@0.1.13):
dependencies:
'@clinic/bubbleprof': 10.0.0
'@clinic/flame': 13.0.0
'@clinic/heap-profiler': 5.0.0
any-shell-escape: 0.1.1
- async: 3.2.5
+ async: 3.2.6
autocannon: 7.15.0
commist: 1.1.0
cross-argv: 1.0.0
clone@1.0.4: {}
- code-block-writer@13.0.1: {}
+ code-block-writer@13.0.3: {}
code-point-at@1.1.0: {}
commander@10.0.1: {}
- commander@11.1.0: {}
+ commander@14.0.0: {}
commander@2.20.3: {}
- commander@7.2.0: {}
+ comment-json@4.2.5:
+ dependencies:
+ array-timsort: 1.0.3
+ core-util-is: 1.0.3
+ esprima: 4.0.1
+ has-own-prop: 2.0.0
+ repeat-string: 1.6.1
comment-parser@1.4.1: {}
conf@10.2.0:
dependencies:
- ajv: 8.13.0
- ajv-formats: 2.1.1(ajv@8.13.0)
+ ajv: 8.17.1
+ ajv-formats: 2.1.1(ajv@8.17.1)
atomically: 1.7.0
debounce-fn: 4.0.0
dot-prop: 6.0.1
json-schema-typed: 7.0.3
onetime: 5.1.2
pkg-up: 3.1.0
- semver: 7.6.2
-
- confbox@0.1.7: {}
+ semver: 7.7.2
config-chain@1.1.13:
dependencies:
write-file-atomic: 3.0.3
xdg-basedir: 4.0.0
- configstore@6.0.0:
- dependencies:
- dot-prop: 6.0.1
- graceful-fs: 4.2.11
- unique-string: 3.0.0
- write-file-atomic: 3.0.3
- xdg-basedir: 5.1.0
-
console-browserify@1.2.0: {}
console-control-strings@1.1.0:
core-util-is@1.0.3: {}
- cosmiconfig-typescript-loader@5.0.0(@types/node@20.12.12)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5):
+ cosmiconfig-typescript-loader@6.1.0(@types/node@24.0.10)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3):
dependencies:
- '@types/node': 20.12.12
- cosmiconfig: 9.0.0(typescript@5.4.5)
- jiti: 1.21.0
- typescript: 5.4.5
+ '@types/node': 24.0.10
+ cosmiconfig: 9.0.0(typescript@5.8.3)
+ jiti: 2.4.2
+ typescript: 5.8.3
- cosmiconfig@9.0.0(typescript@5.4.5):
+ cosmiconfig@9.0.0(typescript@5.8.3):
dependencies:
env-paths: 2.2.1
- import-fresh: 3.3.0
+ import-fresh: 3.3.1
js-yaml: 4.1.0
parse-json: 5.2.0
optionalDependencies:
- typescript: 5.4.5
+ typescript: 5.8.3
create-ecdh@4.0.4:
dependencies:
- bn.js: 4.12.0
- elliptic: 6.5.5
+ bn.js: 4.12.2
+ elliptic: 6.6.1
+
+ create-hash@1.1.3:
+ dependencies:
+ cipher-base: 1.0.6
+ inherits: 2.0.4
+ ripemd160: 2.0.2
+ sha.js: 2.4.12
create-hash@1.2.0:
dependencies:
- cipher-base: 1.0.4
+ cipher-base: 1.0.6
inherits: 2.0.4
md5.js: 1.3.5
ripemd160: 2.0.2
- sha.js: 2.4.11
+ sha.js: 2.4.12
create-hmac@1.1.7:
dependencies:
- cipher-base: 1.0.4
+ cipher-base: 1.0.6
create-hash: 1.2.0
inherits: 2.0.4
ripemd160: 2.0.2
safe-buffer: 5.2.1
- sha.js: 2.4.11
+ sha.js: 2.4.12
create-require@1.1.1: {}
cross-env@7.0.3:
dependencies:
- cross-spawn: 7.0.3
+ cross-spawn: 7.0.6
- cross-spawn@7.0.3:
+ cross-spawn@7.0.6:
dependencies:
path-key: 3.1.1
shebang-command: 2.0.0
which: 2.0.2
- crypto-browserify@3.12.0:
+ crypto-browserify@3.12.1:
dependencies:
browserify-cipher: 1.0.1
browserify-sign: 4.2.3
create-hash: 1.2.0
create-hmac: 1.1.7
diffie-hellman: 5.0.3
+ hash-base: 3.0.5
inherits: 2.0.4
- pbkdf2: 3.1.2
+ pbkdf2: 3.1.3
public-encrypt: 4.0.3
randombytes: 2.1.0
randomfill: 1.0.4
crypto-random-string@2.0.0: {}
- crypto-random-string@4.0.0:
+ cspell-config-lib@9.1.2:
+ dependencies:
+ '@cspell/cspell-types': 9.1.2
+ comment-json: 4.2.5
+ yaml: 2.8.0
+
+ cspell-dictionary@9.1.2:
+ dependencies:
+ '@cspell/cspell-pipe': 9.1.2
+ '@cspell/cspell-types': 9.1.2
+ cspell-trie-lib: 9.1.2
+ fast-equals: 5.2.2
+
+ cspell-glob@9.1.2:
+ dependencies:
+ '@cspell/url': 9.1.2
+ picomatch: 4.0.2
+
+ cspell-grammar@9.1.2:
+ dependencies:
+ '@cspell/cspell-pipe': 9.1.2
+ '@cspell/cspell-types': 9.1.2
+
+ cspell-io@9.1.2:
+ dependencies:
+ '@cspell/cspell-service-bus': 9.1.2
+ '@cspell/url': 9.1.2
+
+ cspell-lib@9.1.2:
+ dependencies:
+ '@cspell/cspell-bundled-dicts': 9.1.2
+ '@cspell/cspell-pipe': 9.1.2
+ '@cspell/cspell-resolver': 9.1.2
+ '@cspell/cspell-types': 9.1.2
+ '@cspell/dynamic-import': 9.1.2
+ '@cspell/filetypes': 9.1.2
+ '@cspell/strong-weak-map': 9.1.2
+ '@cspell/url': 9.1.2
+ clear-module: 4.1.2
+ comment-json: 4.2.5
+ cspell-config-lib: 9.1.2
+ cspell-dictionary: 9.1.2
+ cspell-glob: 9.1.2
+ cspell-grammar: 9.1.2
+ cspell-io: 9.1.2
+ cspell-trie-lib: 9.1.2
+ env-paths: 3.0.0
+ fast-equals: 5.2.2
+ gensequence: 7.0.0
+ import-fresh: 3.3.1
+ resolve-from: 5.0.0
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+ xdg-basedir: 5.1.0
+
+ cspell-trie-lib@9.1.2:
dependencies:
- type-fest: 1.4.0
+ '@cspell/cspell-pipe': 9.1.2
+ '@cspell/cspell-types': 9.1.2
+ gensequence: 7.0.0
cssesc@3.0.0: {}
- cssstyle@4.0.1:
+ cssstyle@4.6.0:
dependencies:
- rrweb-cssom: 0.6.0
+ '@asamuzakjp/css-color': 3.2.0
+ rrweb-cssom: 0.8.0
csstype@3.1.3: {}
d@1.0.2:
dependencies:
es5-ext: 0.10.64
- type: 2.7.2
+ type: 2.7.3
dargs@7.0.0: {}
dependencies:
assert-plus: 1.0.0
- data-uri-to-buffer@4.0.1: {}
-
- data-uri-to-buffer@6.0.2: {}
-
data-urls@5.0.0:
dependencies:
whatwg-mimetype: 4.0.0
- whatwg-url: 14.0.0
+ whatwg-url: 14.2.0
- data-view-buffer@1.0.1:
+ data-view-buffer@1.0.2:
dependencies:
- call-bind: 1.0.7
+ call-bound: 1.0.4
es-errors: 1.3.0
- is-data-view: 1.0.1
+ is-data-view: 1.0.2
- data-view-byte-length@1.0.1:
+ data-view-byte-length@1.0.2:
dependencies:
- call-bind: 1.0.7
+ call-bound: 1.0.4
es-errors: 1.3.0
- is-data-view: 1.0.1
+ is-data-view: 1.0.2
- data-view-byte-offset@1.0.0:
+ data-view-byte-offset@1.0.1:
dependencies:
- call-bind: 1.0.7
+ call-bound: 1.0.4
es-errors: 1.3.0
- is-data-view: 1.0.1
+ is-data-view: 1.0.2
- dataloader@2.2.2: {}
+ dataloader@2.2.3: {}
- date-fns@3.6.0: {}
+ date-fns@4.1.0: {}
debounce-fn@4.0.0:
dependencies:
debounce@1.2.1: {}
- debug@2.6.9:
- dependencies:
- ms: 2.0.0
-
debug@3.2.7:
dependencies:
ms: 2.1.3
+ optional: true
debug@4.3.4:
dependencies:
ms: 2.1.2
+ debug@4.4.1:
+ dependencies:
+ ms: 2.1.3
+
decamelize@1.2.0: {}
- decimal.js@10.4.3: {}
+ decimal.js@10.5.0: {}
decompress-response@6.0.0:
dependencies:
mimic-response: 3.1.0
- deep-eql@4.1.3:
- dependencies:
- type-detect: 4.0.8
+ deep-eql@5.0.2: {}
deep-extend@0.6.0: {}
deep-is@0.1.4: {}
- default-browser-id@5.0.0: {}
-
- default-browser@5.2.1:
- dependencies:
- bundle-name: 4.1.0
- default-browser-id: 5.0.0
-
defaults@1.0.4:
dependencies:
clone: 1.0.4
define-data-property@1.1.4:
dependencies:
- es-define-property: 1.0.0
+ es-define-property: 1.0.1
es-errors: 1.3.0
- gopd: 1.0.1
-
- define-lazy-prop@3.0.0: {}
+ gopd: 1.2.0
define-properties@1.2.1:
dependencies:
defined@1.0.1: {}
- degenerator@5.0.1:
- dependencies:
- ast-types: 0.13.4
- escodegen: 2.1.0
- esprima: 4.0.1
-
del@6.1.1:
dependencies:
globby: 11.1.0
depd@2.0.0: {}
- deprecation@2.3.1: {}
-
deps-sort@2.0.1:
dependencies:
JSONStream: 1.3.5
inherits: 2.0.4
minimalistic-assert: 1.0.1
- destroy@1.2.0: {}
-
- detect-indent@7.0.1: {}
-
- detect-libc@2.0.3: {}
+ detect-libc@2.0.4: {}
detective@5.2.1:
dependencies:
defined: 1.0.1
minimist: 1.2.8
- diff-sequences@29.6.3: {}
-
diff@4.0.2: {}
diffie-hellman@5.0.3:
dependencies:
- bn.js: 4.12.0
+ bn.js: 4.12.2
miller-rabin: 4.0.1
randombytes: 2.1.0
dependencies:
esutils: 2.0.3
- doctrine@3.0.0:
- dependencies:
- esutils: 2.0.3
-
domain-browser@1.2.0: {}
dot-prop@5.3.0:
dependencies:
is-obj: 2.0.0
- dotenv@16.4.5: {}
+ dotenv@16.5.0: {}
+
+ dunder-proto@1.0.1:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-errors: 1.3.0
+ gopd: 1.2.0
dup@1.0.0: {}
duplexify@4.1.3:
dependencies:
- end-of-stream: 1.4.4
+ end-of-stream: 1.4.5
inherits: 2.0.4
readable-stream: 3.6.2
stream-shift: 1.0.3
'@one-ini/wasm': 0.1.1
commander: 10.0.1
minimatch: 9.0.1
- semver: 7.6.2
+ semver: 7.7.2
ee-first@1.1.1: {}
- electron-to-chromium@1.4.776: {}
+ electron-to-chromium@1.5.179: {}
- elliptic@6.5.5:
+ elliptic@6.6.1:
dependencies:
- bn.js: 4.12.0
+ bn.js: 4.12.2
brorand: 1.1.0
hash.js: 1.1.7
hmac-drbg: 1.0.1
minimalistic-assert: 1.0.1
minimalistic-crypto-utils: 1.0.1
- emoji-regex@10.3.0: {}
+ emoji-regex@10.4.0: {}
emoji-regex@7.0.3: {}
enabled@2.0.0: {}
- encodeurl@1.0.2: {}
+ encodeurl@2.0.0: {}
encoding@0.1.13:
dependencies:
iconv-lite: 0.6.3
optional: true
- end-of-stream@1.4.4:
+ end-of-stream@1.4.5:
dependencies:
once: 1.4.0
dependencies:
inherits: 2.0.4
- enhanced-resolve@5.16.1:
+ enhanced-resolve@5.18.2:
dependencies:
graceful-fs: 4.2.11
- tapable: 2.2.1
+ tapable: 2.2.2
entities@4.5.0: {}
+ entities@6.0.1: {}
+
env-paths@2.2.1: {}
+ env-paths@3.0.0: {}
+
env-string@1.0.1: {}
+ environment@1.1.0: {}
+
err-code@2.0.3:
optional: true
dependencies:
is-arrayish: 0.2.1
- es-abstract@1.23.3:
+ es-abstract@1.24.0:
dependencies:
- array-buffer-byte-length: 1.0.1
- arraybuffer.prototype.slice: 1.0.3
+ array-buffer-byte-length: 1.0.2
+ arraybuffer.prototype.slice: 1.0.4
available-typed-arrays: 1.0.7
- call-bind: 1.0.7
- data-view-buffer: 1.0.1
- data-view-byte-length: 1.0.1
- data-view-byte-offset: 1.0.0
- es-define-property: 1.0.0
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ data-view-buffer: 1.0.2
+ data-view-byte-length: 1.0.2
+ data-view-byte-offset: 1.0.1
+ es-define-property: 1.0.1
es-errors: 1.3.0
- es-object-atoms: 1.0.0
- es-set-tostringtag: 2.0.3
- es-to-primitive: 1.2.1
- function.prototype.name: 1.1.6
- get-intrinsic: 1.2.4
- get-symbol-description: 1.0.2
+ es-object-atoms: 1.1.1
+ es-set-tostringtag: 2.1.0
+ es-to-primitive: 1.3.0
+ function.prototype.name: 1.1.8
+ get-intrinsic: 1.3.0
+ get-proto: 1.0.1
+ get-symbol-description: 1.1.0
globalthis: 1.0.4
- gopd: 1.0.1
+ gopd: 1.2.0
has-property-descriptors: 1.0.2
- has-proto: 1.0.3
- has-symbols: 1.0.3
+ has-proto: 1.2.0
+ has-symbols: 1.1.0
hasown: 2.0.2
- internal-slot: 1.0.7
- is-array-buffer: 3.0.4
+ internal-slot: 1.1.0
+ is-array-buffer: 3.0.5
is-callable: 1.2.7
- is-data-view: 1.0.1
+ is-data-view: 1.0.2
is-negative-zero: 2.0.3
- is-regex: 1.1.4
- is-shared-array-buffer: 1.0.3
- is-string: 1.0.7
- is-typed-array: 1.1.13
- is-weakref: 1.0.2
- object-inspect: 1.13.1
+ is-regex: 1.2.1
+ is-set: 2.0.3
+ is-shared-array-buffer: 1.0.4
+ is-string: 1.1.1
+ is-typed-array: 1.1.15
+ is-weakref: 1.1.1
+ math-intrinsics: 1.1.0
+ object-inspect: 1.13.4
object-keys: 1.1.1
- object.assign: 4.1.5
- regexp.prototype.flags: 1.5.2
- safe-array-concat: 1.1.2
- safe-regex-test: 1.0.3
- string.prototype.trim: 1.2.9
- string.prototype.trimend: 1.0.8
+ object.assign: 4.1.7
+ own-keys: 1.0.1
+ regexp.prototype.flags: 1.5.4
+ safe-array-concat: 1.1.3
+ safe-push-apply: 1.0.0
+ safe-regex-test: 1.1.0
+ set-proto: 1.0.0
+ stop-iteration-iterator: 1.1.0
+ string.prototype.trim: 1.2.10
+ string.prototype.trimend: 1.0.9
string.prototype.trimstart: 1.0.8
- typed-array-buffer: 1.0.2
- typed-array-byte-length: 1.0.1
- typed-array-byte-offset: 1.0.2
- typed-array-length: 1.0.6
- unbox-primitive: 1.0.2
- which-typed-array: 1.1.15
+ typed-array-buffer: 1.0.3
+ typed-array-byte-length: 1.0.3
+ typed-array-byte-offset: 1.0.4
+ typed-array-length: 1.0.7
+ unbox-primitive: 1.1.0
+ which-typed-array: 1.1.19
- es-array-method-boxes-properly@1.0.0: {}
-
- es-define-property@1.0.0:
- dependencies:
- get-intrinsic: 1.2.4
+ es-define-property@1.0.1: {}
es-errors@1.3.0: {}
- es-get-iterator@1.1.3:
+ es-iterator-helpers@1.2.1:
dependencies:
- call-bind: 1.0.7
- get-intrinsic: 1.2.4
- has-symbols: 1.0.3
- is-arguments: 1.1.1
- is-map: 2.0.3
- is-set: 2.0.3
- is-string: 1.0.7
- isarray: 2.0.5
- stop-iteration-iterator: 1.0.0
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ es-set-tostringtag: 2.1.0
+ function-bind: 1.1.2
+ get-intrinsic: 1.3.0
+ globalthis: 1.0.4
+ gopd: 1.2.0
+ has-property-descriptors: 1.0.2
+ has-proto: 1.2.0
+ has-symbols: 1.1.0
+ internal-slot: 1.1.0
+ iterator.prototype: 1.1.5
+ safe-array-concat: 1.1.3
- es-object-atoms@1.0.0:
+ es-module-lexer@1.7.0: {}
+
+ es-object-atoms@1.1.1:
dependencies:
es-errors: 1.3.0
- es-set-tostringtag@2.0.3:
+ es-set-tostringtag@2.1.0:
dependencies:
- get-intrinsic: 1.2.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
has-tostringtag: 1.0.2
hasown: 2.0.2
- es-shim-unscopables@1.0.2:
+ es-shim-unscopables@1.1.0:
dependencies:
hasown: 2.0.2
- es-to-primitive@1.2.1:
+ es-to-primitive@1.3.0:
dependencies:
is-callable: 1.2.7
- is-date-object: 1.0.5
- is-symbol: 1.0.4
+ is-date-object: 1.1.0
+ is-symbol: 1.1.1
es5-ext@0.10.64:
dependencies:
es6-iterator: 2.0.3
es6-symbol: 3.1.4
event-emitter: 0.3.5
- type: 2.7.2
+ type: 2.7.3
es6-symbol@3.1.4:
dependencies:
d: 1.0.2
ext: 1.7.0
- esbuild-plugin-clean@1.0.1(esbuild@0.21.3):
+ esbuild-plugin-clean@1.0.1(esbuild@0.25.5):
dependencies:
chalk: 4.1.2
del: 6.1.1
- esbuild: 0.21.3
+ esbuild: 0.25.5
- esbuild-plugin-copy@2.1.1(esbuild@0.21.3):
+ esbuild-plugin-copy@2.1.1(esbuild@0.25.5):
dependencies:
chalk: 4.1.2
chokidar: 3.6.0
- esbuild: 0.21.3
+ esbuild: 0.25.5
fs-extra: 10.1.0
globby: 11.1.0
- esbuild@0.20.2:
+ esbuild@0.25.5:
optionalDependencies:
- '@esbuild/aix-ppc64': 0.20.2
- '@esbuild/android-arm': 0.20.2
- '@esbuild/android-arm64': 0.20.2
- '@esbuild/android-x64': 0.20.2
- '@esbuild/darwin-arm64': 0.20.2
- '@esbuild/darwin-x64': 0.20.2
- '@esbuild/freebsd-arm64': 0.20.2
- '@esbuild/freebsd-x64': 0.20.2
- '@esbuild/linux-arm': 0.20.2
- '@esbuild/linux-arm64': 0.20.2
- '@esbuild/linux-ia32': 0.20.2
- '@esbuild/linux-loong64': 0.20.2
- '@esbuild/linux-mips64el': 0.20.2
- '@esbuild/linux-ppc64': 0.20.2
- '@esbuild/linux-riscv64': 0.20.2
- '@esbuild/linux-s390x': 0.20.2
- '@esbuild/linux-x64': 0.20.2
- '@esbuild/netbsd-x64': 0.20.2
- '@esbuild/openbsd-x64': 0.20.2
- '@esbuild/sunos-x64': 0.20.2
- '@esbuild/win32-arm64': 0.20.2
- '@esbuild/win32-ia32': 0.20.2
- '@esbuild/win32-x64': 0.20.2
-
- esbuild@0.21.3:
- optionalDependencies:
- '@esbuild/aix-ppc64': 0.21.3
- '@esbuild/android-arm': 0.21.3
- '@esbuild/android-arm64': 0.21.3
- '@esbuild/android-x64': 0.21.3
- '@esbuild/darwin-arm64': 0.21.3
- '@esbuild/darwin-x64': 0.21.3
- '@esbuild/freebsd-arm64': 0.21.3
- '@esbuild/freebsd-x64': 0.21.3
- '@esbuild/linux-arm': 0.21.3
- '@esbuild/linux-arm64': 0.21.3
- '@esbuild/linux-ia32': 0.21.3
- '@esbuild/linux-loong64': 0.21.3
- '@esbuild/linux-mips64el': 0.21.3
- '@esbuild/linux-ppc64': 0.21.3
- '@esbuild/linux-riscv64': 0.21.3
- '@esbuild/linux-s390x': 0.21.3
- '@esbuild/linux-x64': 0.21.3
- '@esbuild/netbsd-x64': 0.21.3
- '@esbuild/openbsd-x64': 0.21.3
- '@esbuild/sunos-x64': 0.21.3
- '@esbuild/win32-arm64': 0.21.3
- '@esbuild/win32-ia32': 0.21.3
- '@esbuild/win32-x64': 0.21.3
-
- escalade@3.1.2: {}
+ '@esbuild/aix-ppc64': 0.25.5
+ '@esbuild/android-arm': 0.25.5
+ '@esbuild/android-arm64': 0.25.5
+ '@esbuild/android-x64': 0.25.5
+ '@esbuild/darwin-arm64': 0.25.5
+ '@esbuild/darwin-x64': 0.25.5
+ '@esbuild/freebsd-arm64': 0.25.5
+ '@esbuild/freebsd-x64': 0.25.5
+ '@esbuild/linux-arm': 0.25.5
+ '@esbuild/linux-arm64': 0.25.5
+ '@esbuild/linux-ia32': 0.25.5
+ '@esbuild/linux-loong64': 0.25.5
+ '@esbuild/linux-mips64el': 0.25.5
+ '@esbuild/linux-ppc64': 0.25.5
+ '@esbuild/linux-riscv64': 0.25.5
+ '@esbuild/linux-s390x': 0.25.5
+ '@esbuild/linux-x64': 0.25.5
+ '@esbuild/netbsd-arm64': 0.25.5
+ '@esbuild/netbsd-x64': 0.25.5
+ '@esbuild/openbsd-arm64': 0.25.5
+ '@esbuild/openbsd-x64': 0.25.5
+ '@esbuild/sunos-x64': 0.25.5
+ '@esbuild/win32-arm64': 0.25.5
+ '@esbuild/win32-ia32': 0.25.5
+ '@esbuild/win32-x64': 0.25.5
+
+ escalade@3.2.0: {}
escape-goat@2.1.1: {}
- escape-goat@4.0.0: {}
-
escape-html@1.0.3: {}
escape-string-regexp@1.0.5: {}
- escape-string-regexp@2.0.0: {}
-
escape-string-regexp@4.0.0: {}
escodegen@1.14.3:
optionalDependencies:
source-map: 0.6.1
- eslint-compat-utils@0.5.0(eslint@8.57.0):
- dependencies:
- eslint: 8.57.0
- semver: 7.6.2
-
- eslint-config-love@47.0.0(@typescript-eslint/eslint-plugin@7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint-plugin-n@17.7.0(eslint@8.57.0))(eslint-plugin-promise@6.1.1(eslint@8.57.0))(eslint@8.57.0)(typescript@5.4.5):
- dependencies:
- '@typescript-eslint/eslint-plugin': 7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)
- '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.4.5)
- eslint: 8.57.0
- eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
- eslint-plugin-n: 17.7.0(eslint@8.57.0)
- eslint-plugin-promise: 6.1.1(eslint@8.57.0)
- typescript: 5.4.5
- transitivePeerDependencies:
- - supports-color
-
- eslint-config-prettier@9.1.0(eslint@8.57.0):
+ eslint-compat-utils@0.5.1(eslint@9.30.1(jiti@2.4.2)):
dependencies:
- eslint: 8.57.0
+ eslint: 9.30.1(jiti@2.4.2)
+ semver: 7.7.2
- eslint-config-standard@17.1.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0))(eslint-plugin-n@17.7.0(eslint@8.57.0))(eslint-plugin-promise@6.1.1(eslint@8.57.0))(eslint@8.57.0):
+ eslint-import-context@0.1.9(unrs-resolver@1.10.1):
dependencies:
- eslint: 8.57.0
- eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
- eslint-plugin-n: 17.7.0(eslint@8.57.0)
- eslint-plugin-promise: 6.1.1(eslint@8.57.0)
-
- eslint-define-config@2.1.0: {}
+ get-tsconfig: 4.10.1
+ stable-hash-x: 0.2.0
+ optionalDependencies:
+ unrs-resolver: 1.10.1
eslint-import-resolver-node@0.3.9:
dependencies:
debug: 3.2.7
- is-core-module: 2.13.1
- resolve: 1.22.8
- transitivePeerDependencies:
- - supports-color
-
- eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0):
- dependencies:
- debug: 4.3.4
- enhanced-resolve: 5.16.1
- eslint: 8.57.0
- eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0)
- eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
- fast-glob: 3.3.2
- get-tsconfig: 4.7.5
- is-core-module: 2.13.1
- is-glob: 4.0.3
+ is-core-module: 2.16.1
+ resolve: 1.22.10
transitivePeerDependencies:
- - '@typescript-eslint/parser'
- - eslint-import-resolver-node
- - eslint-import-resolver-webpack
- supports-color
+ optional: true
- eslint-module-utils@2.8.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0):
+ eslint-import-resolver-typescript@3.10.1(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)))(eslint@9.30.1(jiti@2.4.2)):
dependencies:
- debug: 3.2.7
+ '@nolyfill/is-core-module': 1.0.39
+ debug: 4.4.1
+ eslint: 9.30.1(jiti@2.4.2)
+ get-tsconfig: 4.10.1
+ is-bun-module: 2.0.0
+ stable-hash: 0.0.5
+ tinyglobby: 0.2.14
+ unrs-resolver: 1.10.1
optionalDependencies:
- '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.4.5)
- eslint: 8.57.0
- eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0)
+ eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2))
transitivePeerDependencies:
- supports-color
- eslint-plugin-es-x@7.6.0(eslint@8.57.0):
+ eslint-plugin-es-x@7.8.0(eslint@9.30.1(jiti@2.4.2)):
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
- '@eslint-community/regexpp': 4.10.0
- eslint: 8.57.0
- eslint-compat-utils: 0.5.0(eslint@8.57.0)
+ '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1(jiti@2.4.2))
+ '@eslint-community/regexpp': 4.12.1
+ eslint: 9.30.1(jiti@2.4.2)
+ eslint-compat-utils: 0.5.1(eslint@9.30.1(jiti@2.4.2))
- eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0):
+ eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)):
dependencies:
- array-includes: 3.1.8
- array.prototype.findlastindex: 1.2.5
- array.prototype.flat: 1.3.2
- array.prototype.flatmap: 1.3.2
- debug: 3.2.7
- doctrine: 2.1.0
- eslint: 8.57.0
- eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0)
- hasown: 2.0.2
- is-core-module: 2.13.1
+ '@typescript-eslint/types': 8.35.1
+ comment-parser: 1.4.1
+ debug: 4.4.1
+ eslint: 9.30.1(jiti@2.4.2)
+ eslint-import-context: 0.1.9(unrs-resolver@1.10.1)
is-glob: 4.0.3
- minimatch: 3.1.2
- object.fromentries: 2.0.8
- object.groupby: 1.0.3
- object.values: 1.2.0
- semver: 7.6.2
- tsconfig-paths: 3.15.0
+ minimatch: 10.0.3
+ semver: 7.7.2
+ stable-hash-x: 0.2.0
+ unrs-resolver: 1.10.1
optionalDependencies:
- '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.4.5)
+ '@typescript-eslint/utils': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
+ eslint-import-resolver-node: 0.3.9
transitivePeerDependencies:
- - eslint-import-resolver-typescript
- - eslint-import-resolver-webpack
- supports-color
- eslint-plugin-jsdoc@48.2.5(eslint@8.57.0):
+ eslint-plugin-jsdoc@51.3.3(eslint@9.30.1(jiti@2.4.2)):
dependencies:
- '@es-joy/jsdoccomment': 0.43.0
+ '@es-joy/jsdoccomment': 0.52.0
are-docs-informative: 0.0.2
comment-parser: 1.4.1
- debug: 4.3.4
+ debug: 4.4.1
escape-string-regexp: 4.0.0
- eslint: 8.57.0
- esquery: 1.5.0
- is-builtin-module: 3.2.1
- semver: 7.6.2
+ eslint: 9.30.1(jiti@2.4.2)
+ espree: 10.4.0
+ esquery: 1.6.0
+ parse-imports-exports: 0.2.4
+ semver: 7.7.2
spdx-expression-parse: 4.0.0
transitivePeerDependencies:
- supports-color
- eslint-plugin-n@17.7.0(eslint@8.57.0):
- dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
- enhanced-resolve: 5.16.1
- eslint: 8.57.0
- eslint-plugin-es-x: 7.6.0(eslint@8.57.0)
- get-tsconfig: 4.7.5
- globals: 15.3.0
- ignore: 5.3.1
- minimatch: 9.0.4
- semver: 7.6.2
-
- eslint-plugin-prettier@5.1.3(@types/eslint@8.56.10)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5):
- dependencies:
- eslint: 8.57.0
- prettier: 3.2.5
- prettier-linter-helpers: 1.0.0
- synckit: 0.8.8
- optionalDependencies:
- '@types/eslint': 8.56.10
- eslint-config-prettier: 9.1.0(eslint@8.57.0)
+ eslint-plugin-n@17.21.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3):
+ dependencies:
+ '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1(jiti@2.4.2))
+ enhanced-resolve: 5.18.2
+ eslint: 9.30.1(jiti@2.4.2)
+ eslint-plugin-es-x: 7.8.0(eslint@9.30.1(jiti@2.4.2))
+ get-tsconfig: 4.10.1
+ globals: 15.15.0
+ ignore: 5.3.2
+ minimatch: 9.0.5
+ semver: 7.7.2
+ ts-declaration-location: 1.0.7(typescript@5.8.3)
+ transitivePeerDependencies:
+ - typescript
- eslint-plugin-promise@6.1.1(eslint@8.57.0):
+ eslint-plugin-perfectionist@4.15.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3):
dependencies:
- eslint: 8.57.0
+ '@typescript-eslint/types': 8.35.1
+ '@typescript-eslint/utils': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
+ eslint: 9.30.1(jiti@2.4.2)
+ natural-orderby: 5.0.0
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
- eslint-plugin-simple-import-sort@12.1.0(eslint@8.57.0):
+ eslint-plugin-promise@7.2.1(eslint@9.30.1(jiti@2.4.2)):
dependencies:
- eslint: 8.57.0
+ '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1(jiti@2.4.2))
+ eslint: 9.30.1(jiti@2.4.2)
- eslint-plugin-tsdoc@0.2.17:
+ eslint-plugin-react@7.37.5(eslint@9.30.1(jiti@2.4.2)):
dependencies:
- '@microsoft/tsdoc': 0.14.2
- '@microsoft/tsdoc-config': 0.16.2
+ array-includes: 3.1.9
+ array.prototype.findlast: 1.2.5
+ array.prototype.flatmap: 1.3.3
+ array.prototype.tosorted: 1.1.4
+ doctrine: 2.1.0
+ es-iterator-helpers: 1.2.1
+ eslint: 9.30.1(jiti@2.4.2)
+ estraverse: 5.3.0
+ hasown: 2.0.2
+ jsx-ast-utils: 3.3.5
+ minimatch: 3.1.2
+ object.entries: 1.1.9
+ object.fromentries: 2.0.8
+ object.values: 1.2.1
+ prop-types: 15.8.1
+ resolve: 2.0.0-next.5
+ semver: 7.7.2
+ string.prototype.matchall: 4.0.12
+ string.prototype.repeat: 1.0.0
- eslint-plugin-vue@9.26.0(eslint@8.57.0):
+ eslint-plugin-vue@10.3.0(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.1(jiti@2.4.2))(vue-eslint-parser@10.2.0(eslint@9.30.1(jiti@2.4.2))):
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
- eslint: 8.57.0
- globals: 13.24.0
+ '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1(jiti@2.4.2))
+ eslint: 9.30.1(jiti@2.4.2)
natural-compare: 1.4.0
nth-check: 2.1.1
- postcss-selector-parser: 6.0.16
- semver: 7.6.2
- vue-eslint-parser: 9.4.2(eslint@8.57.0)
+ postcss-selector-parser: 6.1.2
+ semver: 7.7.2
+ vue-eslint-parser: 10.2.0(eslint@9.30.1(jiti@2.4.2))
xml-name-validator: 4.0.0
- transitivePeerDependencies:
- - supports-color
+ optionalDependencies:
+ '@typescript-eslint/parser': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
- eslint-scope@7.2.2:
+ eslint-scope@8.4.0:
dependencies:
esrecurse: 4.3.0
estraverse: 5.3.0
eslint-visitor-keys@3.4.3: {}
- eslint@8.57.0:
+ eslint-visitor-keys@4.2.1: {}
+
+ eslint@9.30.1(jiti@2.4.2):
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
- '@eslint-community/regexpp': 4.10.0
- '@eslint/eslintrc': 2.1.4
- '@eslint/js': 8.57.0
- '@humanwhocodes/config-array': 0.11.14
+ '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1(jiti@2.4.2))
+ '@eslint-community/regexpp': 4.12.1
+ '@eslint/config-array': 0.21.0
+ '@eslint/config-helpers': 0.3.0
+ '@eslint/core': 0.14.0
+ '@eslint/eslintrc': 3.3.1
+ '@eslint/js': 9.30.1
+ '@eslint/plugin-kit': 0.3.3
+ '@humanfs/node': 0.16.6
'@humanwhocodes/module-importer': 1.0.1
- '@nodelib/fs.walk': 1.2.8
- '@ungap/structured-clone': 1.2.0
+ '@humanwhocodes/retry': 0.4.3
+ '@types/estree': 1.0.8
+ '@types/json-schema': 7.0.15
ajv: 6.12.6
chalk: 4.1.2
- cross-spawn: 7.0.3
- debug: 4.3.4
- doctrine: 3.0.0
+ cross-spawn: 7.0.6
+ debug: 4.4.1
escape-string-regexp: 4.0.0
- eslint-scope: 7.2.2
- eslint-visitor-keys: 3.4.3
- espree: 9.6.1
- esquery: 1.5.0
+ eslint-scope: 8.4.0
+ eslint-visitor-keys: 4.2.1
+ espree: 10.4.0
+ esquery: 1.6.0
esutils: 2.0.3
fast-deep-equal: 3.1.3
- file-entry-cache: 6.0.1
+ file-entry-cache: 8.0.0
find-up: 5.0.0
glob-parent: 6.0.2
- globals: 13.24.0
- graphemer: 1.4.0
- ignore: 5.3.1
+ ignore: 5.3.2
imurmurhash: 0.1.4
is-glob: 4.0.3
- is-path-inside: 3.0.3
- js-yaml: 4.1.0
json-stable-stringify-without-jsonify: 1.0.1
- levn: 0.4.1
lodash.merge: 4.6.2
minimatch: 3.1.2
natural-compare: 1.4.0
optionator: 0.9.4
- strip-ansi: 6.0.1
- text-table: 0.2.0
+ optionalDependencies:
+ jiti: 2.4.2
transitivePeerDependencies:
- supports-color
d: 1.0.2
es5-ext: 0.10.64
event-emitter: 0.3.5
- type: 2.7.2
+ type: 2.7.3
- espree@9.6.1:
+ espree@10.4.0:
dependencies:
- acorn: 8.11.3
- acorn-jsx: 5.3.2(acorn@8.11.3)
- eslint-visitor-keys: 3.4.3
+ acorn: 8.15.0
+ acorn-jsx: 5.3.2(acorn@8.15.0)
+ eslint-visitor-keys: 4.2.1
esprima@4.0.1: {}
- esquery@1.5.0:
+ esquery@1.6.0:
dependencies:
estraverse: 5.3.0
estree-walker@3.0.3:
dependencies:
- '@types/estree': 1.0.5
+ '@types/estree': 1.0.8
esutils@2.0.3: {}
execa@4.1.0:
dependencies:
- cross-spawn: 7.0.3
+ cross-spawn: 7.0.6
get-stream: 5.2.0
human-signals: 1.1.1
is-stream: 2.0.1
signal-exit: 3.0.7
strip-final-newline: 2.0.0
- execa@5.1.1:
- dependencies:
- cross-spawn: 7.0.3
- get-stream: 6.0.1
- human-signals: 2.1.0
- is-stream: 2.0.1
- merge-stream: 2.0.0
- npm-run-path: 4.0.1
- onetime: 5.1.2
- signal-exit: 3.0.7
- strip-final-newline: 2.0.0
-
- execa@8.0.1:
- dependencies:
- cross-spawn: 7.0.3
- get-stream: 8.0.1
- human-signals: 5.0.0
- is-stream: 3.0.0
- merge-stream: 2.0.0
- npm-run-path: 5.3.0
- onetime: 6.0.0
- signal-exit: 4.1.0
- strip-final-newline: 3.0.0
-
execspawn@1.0.1:
dependencies:
util-extend: 1.0.3
expand-template@2.0.3: {}
- expect@29.7.0:
- dependencies:
- '@jest/expect-utils': 29.7.0
- jest-get-type: 29.6.3
- jest-matcher-utils: 29.7.0
- jest-message-util: 29.7.0
- jest-util: 29.7.0
+ expect-type@1.2.1: {}
ext@1.7.0:
dependencies:
- type: 2.7.2
+ type: 2.7.3
extend@3.0.2: {}
fast-deep-equal@3.1.3: {}
- fast-diff@1.3.0: {}
+ fast-equals@5.2.2: {}
- fast-glob@3.3.2:
+ fast-glob@3.3.3:
dependencies:
'@nodelib/fs.stat': 2.0.5
'@nodelib/fs.walk': 1.2.8
glob-parent: 5.1.2
merge2: 1.4.1
- micromatch: 4.0.5
+ micromatch: 4.0.8
fast-json-stable-stringify@2.1.0: {}
fast-safe-stringify@2.1.1: {}
- fastq@1.17.1:
+ fast-uri@3.0.6: {}
+
+ fastq@1.19.1:
dependencies:
- reusify: 1.0.4
+ reusify: 1.1.0
- fecha@4.2.3: {}
+ fdir@6.4.6(picomatch@4.0.2):
+ optionalDependencies:
+ picomatch: 4.0.2
- fetch-blob@3.2.0:
- dependencies:
- node-domexception: 1.0.0
- web-streams-polyfill: 3.3.3
+ fecha@4.2.3: {}
- figlet@1.7.0: {}
+ figlet@1.8.1: {}
figures@2.0.0:
dependencies:
escape-string-regexp: 1.0.5
- file-entry-cache@6.0.1:
+ file-entry-cache@8.0.0:
dependencies:
- flat-cache: 3.2.0
+ flat-cache: 4.0.1
file-stream-rotator@0.6.1:
dependencies:
dependencies:
to-regex-range: 5.0.1
- finalhandler@1.2.0:
+ finalhandler@2.1.0:
dependencies:
- debug: 2.6.9
- encodeurl: 1.0.2
+ debug: 4.4.1
+ encodeurl: 2.0.0
escape-html: 1.0.3
on-finished: 2.4.1
parseurl: 1.3.3
- statuses: 2.0.1
- unpipe: 1.0.0
+ statuses: 2.0.2
transitivePeerDependencies:
- supports-color
dependencies:
sinusoidal-decimal: 1.0.0
- flat-cache@3.2.0:
+ flat-cache@4.0.1:
dependencies:
- flatted: 3.3.1
+ flatted: 3.3.3
keyv: 4.5.4
- rimraf: 3.0.2
flatstr@1.0.12: {}
- flatted@3.3.1: {}
+ flatted@3.3.3: {}
fn.name@1.1.0: {}
- for-each@0.3.3:
+ for-each@0.3.5:
dependencies:
is-callable: 1.2.7
- foreground-child@3.1.1:
+ foreground-child@3.3.1:
dependencies:
- cross-spawn: 7.0.3
+ cross-spawn: 7.0.6
signal-exit: 4.1.0
forever-agent@0.6.1: {}
combined-stream: 1.0.8
mime-types: 2.1.35
- form-data@4.0.0:
+ form-data@4.0.3:
dependencies:
asynckit: 0.4.0
combined-stream: 1.0.8
+ es-set-tostringtag: 2.1.0
+ hasown: 2.0.2
mime-types: 2.1.35
- formdata-polyfill@4.0.10:
- dependencies:
- fetch-blob: 3.2.0
-
- fresh@0.5.2: {}
+ fresh@2.0.0: {}
from2-string@1.1.0:
dependencies:
jsonfile: 6.1.0
universalify: 2.0.1
- fs-extra@11.2.0:
+ fs-extra@11.3.0:
dependencies:
graceful-fs: 4.2.11
jsonfile: 6.1.0
function-bind@1.1.2: {}
- function.prototype.name@1.1.6:
+ function.prototype.name@1.1.8:
dependencies:
- call-bind: 1.0.7
+ call-bind: 1.0.8
+ call-bound: 1.0.4
define-properties: 1.2.1
- es-abstract: 1.23.3
functions-have-names: 1.2.3
+ hasown: 2.0.2
+ is-callable: 1.2.7
functions-have-names@1.2.3: {}
dependencies:
is-property: 1.0.2
+ gensequence@7.0.0: {}
+
gensync@1.0.0-beta.2: {}
get-assigned-identifiers@1.2.0: {}
get-caller-file@2.0.5: {}
- get-east-asian-width@1.2.0: {}
+ get-east-asian-width@1.3.0: {}
- get-func-name@2.0.2: {}
-
- get-intrinsic@1.2.4:
+ get-intrinsic@1.3.0:
dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-define-property: 1.0.1
es-errors: 1.3.0
+ es-object-atoms: 1.1.1
function-bind: 1.1.2
- has-proto: 1.0.3
- has-symbols: 1.0.3
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ has-symbols: 1.1.0
hasown: 2.0.2
+ math-intrinsics: 1.1.0
get-package-type@0.1.0: {}
+ get-proto@1.0.1:
+ dependencies:
+ dunder-proto: 1.0.1
+ es-object-atoms: 1.1.1
+
get-stream@5.2.0:
dependencies:
- pump: 3.0.0
+ pump: 3.0.3
get-stream@6.0.1: {}
- get-stream@8.0.1: {}
-
- get-symbol-description@1.0.2:
+ get-symbol-description@1.1.0:
dependencies:
- call-bind: 1.0.7
+ call-bound: 1.0.4
es-errors: 1.3.0
- get-intrinsic: 1.2.4
+ get-intrinsic: 1.3.0
- get-tsconfig@4.7.5:
+ get-tsconfig@4.10.1:
dependencies:
resolve-pkg-maps: 1.0.0
- get-uri@6.0.3:
- dependencies:
- basic-ftp: 5.0.5
- data-uri-to-buffer: 6.0.2
- debug: 4.3.4
- fs-extra: 11.2.0
- transitivePeerDependencies:
- - supports-color
-
getopts@2.3.0: {}
getpass@0.1.7:
meow: 12.1.1
split2: 4.2.0
- git-up@7.0.0:
- dependencies:
- is-ssh: 1.4.0
- parse-url: 8.1.0
-
- git-url-parse@14.0.0:
- dependencies:
- git-up: 7.0.0
-
github-from-package@0.0.0: {}
glob-parent@5.1.2:
dependencies:
is-glob: 4.0.3
- glob@10.3.15:
+ glob@10.4.5:
dependencies:
- foreground-child: 3.1.1
- jackspeak: 2.3.6
- minimatch: 9.0.4
- minipass: 7.1.1
+ foreground-child: 3.3.1
+ jackspeak: 3.4.3
+ minimatch: 9.0.5
+ minipass: 7.1.2
+ package-json-from-dist: 1.0.1
path-scurry: 1.11.1
+ glob@11.0.3:
+ dependencies:
+ foreground-child: 3.3.1
+ jackspeak: 4.1.1
+ minimatch: 10.0.3
+ minipass: 7.1.2
+ package-json-from-dist: 1.0.1
+ path-scurry: 2.0.0
+
glob@7.2.3:
dependencies:
fs.realpath: 1.0.0
dependencies:
ini: 2.0.0
- globals@11.12.0: {}
-
- globals@13.24.0:
- dependencies:
- type-fest: 0.20.2
+ globals@14.0.0: {}
- globals@15.3.0: {}
+ globals@15.15.0: {}
globalthis@1.0.4:
dependencies:
define-properties: 1.2.1
- gopd: 1.0.1
+ gopd: 1.2.0
globby@11.1.0:
dependencies:
array-union: 2.1.0
dir-glob: 3.0.1
- fast-glob: 3.3.2
- ignore: 5.3.1
+ fast-glob: 3.3.3
+ ignore: 5.3.2
merge2: 1.4.1
slash: 3.0.0
- globby@14.0.1:
- dependencies:
- '@sindresorhus/merge-streams': 2.3.0
- fast-glob: 3.3.2
- ignore: 5.3.1
- path-type: 5.0.0
- slash: 5.1.0
- unicorn-magic: 0.1.0
-
- gopd@1.0.1:
- dependencies:
- get-intrinsic: 1.2.4
+ gopd@1.2.0: {}
got@12.6.1:
dependencies:
p-cancelable: 3.0.0
responselike: 3.0.0
- graceful-fs@4.2.10: {}
-
graceful-fs@4.2.11: {}
graphemer@1.4.0: {}
- handlebars@4.7.8:
- dependencies:
- minimist: 1.2.8
- neo-async: 2.6.2
- source-map: 0.6.1
- wordwrap: 1.0.0
- optionalDependencies:
- uglify-js: 3.17.4
-
har-schema@2.0.0: {}
har-validator@5.1.5:
has-async-hooks@1.0.0: {}
- has-bigints@1.0.2: {}
+ has-bigints@1.1.0: {}
has-flag@3.0.0: {}
has-flag@4.0.0: {}
+ has-own-prop@2.0.0: {}
+
has-property-descriptors@1.0.2:
dependencies:
- es-define-property: 1.0.0
+ es-define-property: 1.0.1
- has-proto@1.0.3: {}
+ has-proto@1.2.0:
+ dependencies:
+ dunder-proto: 1.0.1
- has-symbols@1.0.3: {}
+ has-symbols@1.1.0: {}
has-tostringtag@1.0.2:
dependencies:
- has-symbols: 1.0.3
+ has-symbols: 1.1.0
has-unicode@2.0.1: {}
has@1.0.4: {}
- hash-base@3.0.4:
+ hash-base@2.0.2:
dependencies:
inherits: 2.0.4
- safe-buffer: 5.2.1
- hash-base@3.1.0:
+ hash-base@3.0.5:
dependencies:
inherits: 2.0.4
- readable-stream: 3.6.2
safe-buffer: 5.2.1
hash.js@1.1.7:
dependencies:
function-bind: 1.1.2
- hdr-histogram-js@3.0.0:
+ hdr-histogram-js@3.0.1:
dependencies:
'@assemblyscript/loader': 0.19.23
base64-js: 1.5.1
ndarray-determinant: 1.0.0
ndarray-inv: 0.2.0
seedrandom: 3.0.5
- semver: 7.6.2
+ semver: 7.7.2
hmac-drbg@1.0.1:
dependencies:
html-escaper@2.0.2: {}
- html-tags@3.3.1: {}
-
htmlescape@1.1.1: {}
- http-cache-semantics@4.1.1: {}
+ http-cache-semantics@4.2.0: {}
http-errors@2.0.0:
dependencies:
statuses: 2.0.1
toidentifier: 1.0.1
- http-parser-js@0.5.8: {}
+ http-parser-js@0.5.10: {}
http-proxy-agent@4.0.1:
dependencies:
'@tootallnate/once': 1.1.2
agent-base: 6.0.2
- debug: 4.3.4
+ debug: 4.4.1
transitivePeerDependencies:
- supports-color
optional: true
http-proxy-agent@7.0.2:
dependencies:
- agent-base: 7.1.1
- debug: 4.3.4
+ agent-base: 7.1.3
+ debug: 4.4.1
transitivePeerDependencies:
- supports-color
https-proxy-agent@5.0.1:
dependencies:
agent-base: 6.0.2
- debug: 4.3.4
+ debug: 4.4.1
transitivePeerDependencies:
- supports-color
optional: true
- https-proxy-agent@7.0.4:
+ https-proxy-agent@7.0.6:
dependencies:
- agent-base: 7.1.1
- debug: 4.3.4
+ agent-base: 7.1.3
+ debug: 4.4.1
transitivePeerDependencies:
- supports-color
human-signals@1.1.1: {}
- human-signals@2.1.0: {}
-
- human-signals@5.0.0: {}
-
humanize-ms@1.2.1:
dependencies:
ms: 2.1.3
optional: true
- husky@9.0.11: {}
+ husky@9.1.7: {}
- hyperid@3.2.0:
+ hyperid@3.3.0:
dependencies:
buffer: 5.7.1
uuid: 9.0.1
ieee754@1.2.1: {}
- ignore@5.3.1: {}
+ ignore@5.3.2: {}
+
+ ignore@7.0.5: {}
- import-fresh@3.3.0:
+ import-fresh@3.3.1:
dependencies:
parent-module: 1.0.1
resolve-from: 4.0.0
import-lazy@2.1.0: {}
- import-lazy@4.0.0: {}
-
import-meta-resolve@4.1.0: {}
imurmurhash@0.1.4: {}
ini@4.1.1: {}
- ini@4.1.2: {}
-
inline-source-map@0.6.3:
dependencies:
source-map: 0.5.7
strip-ansi: 5.2.0
through: 2.3.8
- inquirer@9.2.22:
- dependencies:
- '@inquirer/figures': 1.0.2
- '@ljharb/through': 2.3.13
- ansi-escapes: 4.3.2
- chalk: 5.3.0
- cli-cursor: 3.1.0
- cli-width: 4.1.0
- external-editor: 3.1.0
- lodash: 4.17.21
- mute-stream: 1.0.0
- ora: 5.4.1
- run-async: 3.0.0
- rxjs: 7.8.1
- string-width: 4.2.3
- strip-ansi: 6.0.1
- wrap-ansi: 6.2.0
-
insert-module-globals@7.2.1:
dependencies:
JSONStream: 1.3.5
tough-cookie: 4.1.4
uuid: 9.0.1
- internal-slot@1.0.7:
+ internal-slot@1.1.0:
dependencies:
es-errors: 1.3.0
hasown: 2.0.2
- side-channel: 1.0.6
+ side-channel: 1.1.0
internmap@1.0.1: {}
- interpret@1.4.0: {}
-
interpret@2.2.0: {}
iota-array@1.0.0: {}
dependencies:
jsbn: 1.1.0
sprintf-js: 1.1.3
+ optional: true
is-any-array@2.0.1: {}
- is-arguments@1.1.1:
+ is-arguments@1.2.0:
dependencies:
- call-bind: 1.0.7
+ call-bound: 1.0.4
has-tostringtag: 1.0.2
- is-array-buffer@3.0.4:
+ is-array-buffer@3.0.5:
dependencies:
- call-bind: 1.0.7
- get-intrinsic: 1.2.4
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
is-arrayish@0.2.1: {}
is-arrayish@0.3.2: {}
- is-bigint@1.0.4:
+ is-async-function@2.1.1:
dependencies:
- has-bigints: 1.0.2
+ async-function: 1.0.0
+ call-bound: 1.0.4
+ get-proto: 1.0.1
+ has-tostringtag: 1.0.2
+ safe-regex-test: 1.1.0
+
+ is-bigint@1.1.0:
+ dependencies:
+ has-bigints: 1.1.0
is-binary-path@2.1.0:
dependencies:
is-boolean-attribute@0.0.1: {}
- is-boolean-object@1.1.2:
+ is-boolean-object@1.2.2:
dependencies:
- call-bind: 1.0.7
+ call-bound: 1.0.4
has-tostringtag: 1.0.2
is-buffer@1.1.6: {}
is-buffer@2.0.5: {}
- is-builtin-module@3.2.1:
+ is-bun-module@2.0.0:
dependencies:
- builtin-modules: 3.3.0
+ semver: 7.7.2
is-callable@1.2.7: {}
dependencies:
ci-info: 2.0.0
- is-ci@3.0.1:
- dependencies:
- ci-info: 3.9.0
-
- is-core-module@2.13.1:
+ is-core-module@2.16.1:
dependencies:
hasown: 2.0.2
- is-data-view@1.0.1:
+ is-data-view@1.0.2:
dependencies:
- is-typed-array: 1.1.13
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+ is-typed-array: 1.1.15
- is-date-object@1.0.5:
+ is-date-object@1.1.0:
dependencies:
+ call-bound: 1.0.4
has-tostringtag: 1.0.2
is-docker@2.2.1: {}
- is-docker@3.0.0: {}
-
is-extglob@2.1.1: {}
+ is-finalizationregistry@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
+
is-fullwidth-code-point@1.0.0:
dependencies:
number-is-nan: 1.0.1
is-fullwidth-code-point@5.0.0:
dependencies:
- get-east-asian-width: 1.2.0
+ get-east-asian-width: 1.3.0
- is-generator-function@1.0.10:
+ is-generator-function@1.1.0:
dependencies:
+ call-bound: 1.0.4
+ get-proto: 1.0.1
has-tostringtag: 1.0.2
+ safe-regex-test: 1.1.0
is-glob@4.0.3:
dependencies:
is-extglob: 2.1.1
- is-in-ci@0.1.0: {}
-
- is-inside-container@1.0.0:
- dependencies:
- is-docker: 3.0.0
-
is-installed-globally@0.4.0:
dependencies:
global-dirs: 3.0.1
is-interactive@1.0.0: {}
- is-interactive@2.0.0: {}
-
is-lambda@1.0.1:
optional: true
is-npm@5.0.0: {}
- is-npm@6.0.0: {}
-
- is-number-object@1.0.7:
+ is-number-object@1.1.1:
dependencies:
+ call-bound: 1.0.4
has-tostringtag: 1.0.2
is-number@7.0.0: {}
is-property@1.0.2: {}
- is-regex@1.1.4:
+ is-regex@1.2.1:
dependencies:
- call-bind: 1.0.7
+ call-bound: 1.0.4
+ gopd: 1.2.0
has-tostringtag: 1.0.2
+ hasown: 2.0.2
is-set@2.0.3: {}
- is-shared-array-buffer@1.0.3:
- dependencies:
- call-bind: 1.0.7
-
- is-ssh@1.4.0:
+ is-shared-array-buffer@1.0.4:
dependencies:
- protocols: 2.0.1
+ call-bound: 1.0.4
is-stream@2.0.1: {}
- is-stream@3.0.0: {}
-
- is-string@1.0.7:
+ is-string@1.1.1:
dependencies:
+ call-bound: 1.0.4
has-tostringtag: 1.0.2
- is-symbol@1.0.4:
+ is-symbol@1.1.1:
dependencies:
- has-symbols: 1.0.3
+ call-bound: 1.0.4
+ has-symbols: 1.1.0
+ safe-regex-test: 1.1.0
is-text-path@2.0.0:
dependencies:
text-extensions: 2.4.0
- is-typed-array@1.1.13:
+ is-typed-array@1.1.15:
dependencies:
- which-typed-array: 1.1.15
+ which-typed-array: 1.1.19
is-typedarray@1.0.0: {}
is-unicode-supported@0.1.0: {}
- is-unicode-supported@1.3.0: {}
+ is-weakmap@2.0.2: {}
- is-unicode-supported@2.0.0: {}
+ is-weakref@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
- is-weakref@1.0.2:
+ is-weakset@2.0.4:
dependencies:
- call-bind: 1.0.7
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
is-wsl@1.1.0: {}
dependencies:
is-docker: 2.2.1
- is-wsl@3.1.0:
- dependencies:
- is-inside-container: 1.0.0
-
is-yarn-global@0.3.0: {}
isarray@1.0.0: {}
isstream@0.1.2: {}
- issue-parser@7.0.0:
- dependencies:
- lodash.capitalize: 4.2.1
- lodash.escaperegexp: 4.1.2
- lodash.isplainobject: 4.0.6
- lodash.isstring: 4.0.1
- lodash.uniqby: 4.7.0
-
istanbul-lib-coverage@3.2.2: {}
istanbul-lib-report@3.0.1:
make-dir: 4.0.0
supports-color: 7.2.0
- istanbul-lib-source-maps@5.0.4:
+ istanbul-lib-source-maps@5.0.6:
dependencies:
- '@jridgewell/trace-mapping': 0.3.25
- debug: 4.3.4
+ '@jridgewell/trace-mapping': 0.3.29
+ debug: 4.4.1
istanbul-lib-coverage: 3.2.2
transitivePeerDependencies:
- supports-color
html-escaper: 2.0.2
istanbul-lib-report: 3.0.1
- iterate-iterator@1.0.2: {}
-
- iterate-value@1.0.2:
+ iterator.prototype@1.1.5:
dependencies:
- es-get-iterator: 1.1.3
- iterate-iterator: 1.0.2
+ define-data-property: 1.1.4
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ get-proto: 1.0.1
+ has-symbols: 1.1.0
+ set-function-name: 2.0.2
- jackspeak@2.3.6:
+ jackspeak@3.4.3:
dependencies:
'@isaacs/cliui': 8.0.2
optionalDependencies:
'@pkgjs/parseargs': 0.11.0
- jest-diff@29.7.0:
- dependencies:
- chalk: 4.1.2
- diff-sequences: 29.6.3
- jest-get-type: 29.6.3
- pretty-format: 29.7.0
-
- jest-get-type@29.6.3: {}
-
- jest-matcher-utils@29.7.0:
- dependencies:
- chalk: 4.1.2
- jest-diff: 29.7.0
- jest-get-type: 29.6.3
- pretty-format: 29.7.0
-
- jest-message-util@29.7.0:
- dependencies:
- '@babel/code-frame': 7.24.2
- '@jest/types': 29.6.3
- '@types/stack-utils': 2.0.3
- chalk: 4.1.2
- graceful-fs: 4.2.11
- micromatch: 4.0.5
- pretty-format: 29.7.0
- slash: 3.0.0
- stack-utils: 2.0.6
-
- jest-util@29.7.0:
+ jackspeak@4.1.1:
dependencies:
- '@jest/types': 29.6.3
- '@types/node': 20.12.12
- chalk: 4.1.2
- ci-info: 3.9.0
- graceful-fs: 4.2.11
- picomatch: 2.3.1
-
- jiti@1.21.0: {}
+ '@isaacs/cliui': 8.0.2
- jju@1.4.0: {}
+ jiti@2.4.2: {}
- js-beautify@1.15.1:
+ js-beautify@1.15.4:
dependencies:
config-chain: 1.1.13
editorconfig: 1.0.4
- glob: 10.3.15
+ glob: 10.4.5
js-cookie: 3.0.5
nopt: 7.2.1
js-tokens@4.0.0: {}
- js-tokens@9.0.0: {}
+ js-tokens@9.0.1: {}
js-yaml@4.1.0:
dependencies:
jsbn@0.1.1: {}
- jsbn@1.1.0: {}
+ jsbn@1.1.0:
+ optional: true
- jsdoc-type-pratt-parser@4.0.0: {}
+ jsdoc-type-pratt-parser@4.1.0: {}
- jsdom@24.0.0(bufferutil@4.0.8)(utf-8-validate@6.0.4):
+ jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5):
dependencies:
- cssstyle: 4.0.1
+ cssstyle: 4.6.0
data-urls: 5.0.0
- decimal.js: 10.4.3
- form-data: 4.0.0
+ decimal.js: 10.5.0
html-encoding-sniffer: 4.0.0
http-proxy-agent: 7.0.2
- https-proxy-agent: 7.0.4
+ https-proxy-agent: 7.0.6
is-potential-custom-element-name: 1.0.1
- nwsapi: 2.2.10
- parse5: 7.1.2
- rrweb-cssom: 0.6.0
+ nwsapi: 2.2.20
+ parse5: 7.3.0
+ rrweb-cssom: 0.8.0
saxes: 6.0.0
symbol-tree: 3.2.4
tough-cookie: 4.1.4
webidl-conversions: 7.0.0
whatwg-encoding: 3.1.1
whatwg-mimetype: 4.0.0
- whatwg-url: 14.0.0
- ws: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+ whatwg-url: 14.2.0
+ ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)
xml-name-validator: 5.0.0
transitivePeerDependencies:
- bufferutil
- supports-color
- utf-8-validate
- jsesc@2.5.2: {}
+ jsesc@3.1.0: {}
json-buffer@3.0.1: {}
json-stringify-safe@5.0.1: {}
- json5@1.0.2:
- dependencies:
- minimist: 1.2.8
-
json5@2.2.3: {}
jsonfile@6.1.0:
json-schema: 0.4.0
verror: 1.10.0
+ jsx-ast-utils@3.3.5:
+ dependencies:
+ array-includes: 3.1.9
+ array.prototype.flat: 1.3.3
+ object.assign: 4.1.7
+ object.values: 1.2.1
+
keyv@4.5.4:
dependencies:
json-buffer: 3.0.1
colorette: 2.0.19
commander: 10.0.1
debug: 4.3.4
- escalade: 3.1.2
+ escalade: 3.2.0
esm: 3.2.25
get-package-type: 0.1.0
getopts: 2.3.0
dependencies:
package-json: 6.5.0
- latest-version@7.0.0:
- dependencies:
- package-json: 8.1.1
-
leven@2.1.0: {}
levn@0.3.0:
prelude-ls: 1.2.1
type-check: 0.4.0
- lilconfig@3.0.0: {}
+ lilconfig@3.1.3: {}
lines-and-columns@1.2.4: {}
- lint-staged@15.2.2:
+ lint-staged@16.1.2:
dependencies:
- chalk: 5.3.0
- commander: 11.1.0
- debug: 4.3.4
- execa: 8.0.1
- lilconfig: 3.0.0
- listr2: 8.0.1
- micromatch: 4.0.5
+ chalk: 5.4.1
+ commander: 14.0.0
+ debug: 4.4.1
+ lilconfig: 3.1.3
+ listr2: 8.3.3
+ micromatch: 4.0.8
+ nano-spawn: 1.0.2
pidtree: 0.6.0
string-argv: 0.3.2
- yaml: 2.3.4
+ yaml: 2.8.0
transitivePeerDependencies:
- supports-color
- listr2@8.0.1:
+ listr2@8.3.3:
dependencies:
cli-truncate: 4.0.0
colorette: 2.0.20
eventemitter3: 5.0.1
- log-update: 6.0.0
- rfdc: 1.3.1
+ log-update: 6.1.0
+ rfdc: 1.4.1
wrap-ansi: 9.0.0
- local-pkg@0.5.0:
- dependencies:
- mlly: 1.7.0
- pkg-types: 1.1.1
-
locate-path@3.0.0:
dependencies:
p-locate: 3.0.0
dependencies:
p-locate: 6.0.0
- lodash-es@4.17.21: {}
-
lodash.camelcase@4.3.0: {}
- lodash.capitalize@4.2.1: {}
-
lodash.chunk@4.2.0: {}
lodash.clonedeep@4.5.0: {}
lodash.debounce@4.0.8: {}
- lodash.escaperegexp@4.1.2: {}
-
lodash.flatten@4.4.0: {}
lodash.isplainobject@4.0.6: {}
- lodash.isstring@4.0.1: {}
-
lodash.kebabcase@4.1.1: {}
lodash.memoize@3.0.4: {}
lodash.uniq@4.5.0: {}
- lodash.uniqby@4.7.0: {}
-
lodash.upperfirst@4.3.1: {}
lodash@4.17.21: {}
chalk: 4.1.2
is-unicode-supported: 0.1.0
- log-symbols@6.0.0:
- dependencies:
- chalk: 5.3.0
- is-unicode-supported: 1.3.0
-
- log-update@6.0.0:
+ log-update@6.1.0:
dependencies:
- ansi-escapes: 6.2.1
- cli-cursor: 4.0.0
+ ansi-escapes: 7.0.0
+ cli-cursor: 5.0.0
slice-ansi: 7.1.0
strip-ansi: 7.1.0
wrap-ansi: 9.0.0
- logform@2.6.0:
+ logform@2.7.0:
dependencies:
'@colors/colors': 1.6.0
'@types/triple-beam': 1.3.5
fecha: 4.2.3
ms: 2.1.3
- safe-stable-stringify: 2.4.3
+ safe-stable-stringify: 2.5.0
triple-beam: 1.4.1
long@4.0.0: {}
dependencies:
js-tokens: 4.0.0
- loupe@2.3.7:
- dependencies:
- get-func-name: 2.0.2
+ loupe@3.1.4: {}
lower-case@1.1.4: {}
lowercase-keys@3.0.0: {}
- lru-cache@10.2.2: {}
+ lru-cache@10.4.3: {}
+
+ lru-cache@11.1.0: {}
lru-cache@5.1.1:
dependencies:
yallist: 4.0.0
optional: true
- lru-cache@7.18.3: {}
-
macos-release@2.5.1: {}
- macos-release@3.2.0: {}
-
magic-string@0.23.2:
dependencies:
sourcemap-codec: 1.4.8
dependencies:
sourcemap-codec: 1.4.8
- magic-string@0.30.10:
+ magic-string@0.30.17:
dependencies:
- '@jridgewell/sourcemap-codec': 1.4.15
+ '@jridgewell/sourcemap-codec': 1.5.4
- magicast@0.3.4:
+ magicast@0.3.5:
dependencies:
- '@babel/parser': 7.24.5
- '@babel/types': 7.24.5
- source-map-js: 1.2.0
+ '@babel/parser': 7.28.0
+ '@babel/types': 7.28.0
+ source-map-js: 1.2.1
make-dir@3.1.0:
dependencies:
- semver: 7.6.2
+ semver: 7.7.2
make-dir@4.0.0:
dependencies:
- semver: 7.6.2
+ semver: 7.7.2
make-error@1.3.6: {}
make-fetch-happen@9.1.0:
dependencies:
- agentkeepalive: 4.5.0
+ agentkeepalive: 4.6.0
cacache: 15.3.0
- http-cache-semantics: 4.1.1
+ http-cache-semantics: 4.2.0
http-proxy-agent: 4.0.1
https-proxy-agent: 5.0.1
is-lambda: 1.0.1
minipass-fetch: 1.4.1
minipass-flush: 1.0.5
minipass-pipeline: 1.2.4
- negotiator: 0.6.3
+ negotiator: 0.6.4
promise-retry: 2.0.1
socks-proxy-agent: 6.2.1
ssri: 8.0.1
manage-path@2.0.0: {}
- mariadb@3.3.0:
+ mariadb@3.4.2:
dependencies:
- '@types/geojson': 7946.0.14
- '@types/node': 20.12.12
+ '@types/geojson': 7946.0.16
+ '@types/node': 22.16.0
denque: 2.1.0
iconv-lite: 0.6.3
- lru-cache: 10.2.2
+ lru-cache: 10.4.3
+
+ math-intrinsics@1.1.0: {}
md5.js@1.3.5:
dependencies:
- hash-base: 3.1.0
+ hash-base: 3.0.5
inherits: 2.0.4
safe-buffer: 5.2.1
merge2@1.4.1: {}
- micromatch@4.0.5:
+ micromatch@4.0.8:
dependencies:
braces: 3.0.3
picomatch: 2.3.1
- mikro-orm@6.2.7: {}
+ mikro-orm@6.4.16: {}
miller-rabin@4.0.1:
dependencies:
- bn.js: 4.12.0
+ bn.js: 4.12.2
brorand: 1.1.0
mime-db@1.52.0: {}
+ mime-db@1.54.0: {}
+
mime-types@2.1.35:
dependencies:
mime-db: 1.52.0
- mime@1.6.0: {}
+ mime-types@3.0.1:
+ dependencies:
+ mime-db: 1.54.0
mimic-fn@1.2.0: {}
mimic-fn@3.1.0: {}
- mimic-fn@4.0.0: {}
+ mimic-function@5.0.1: {}
mimic-response@3.1.0: {}
minimalistic-crypto-utils@1.0.1: {}
+ minimatch@10.0.3:
+ dependencies:
+ '@isaacs/brace-expansion': 5.0.0
+
minimatch@3.1.2:
dependencies:
- brace-expansion: 1.1.11
+ brace-expansion: 1.1.12
minimatch@9.0.1:
dependencies:
- brace-expansion: 2.0.1
+ brace-expansion: 2.0.2
- minimatch@9.0.4:
+ minimatch@9.0.5:
dependencies:
- brace-expansion: 2.0.1
+ brace-expansion: 2.0.2
minimist@1.2.8: {}
minipass@5.0.0: {}
- minipass@7.1.1: {}
+ minipass@7.1.2: {}
minizlib@2.1.2:
dependencies:
minipass: 3.3.6
yallist: 4.0.0
- minizlib@3.0.1:
+ minizlib@3.0.2:
dependencies:
- minipass: 7.1.1
- rimraf: 5.0.7
+ minipass: 7.1.2
mkdirp-classic@0.5.3: {}
ml-xsadd@2.0.0: {}
- mlly@1.7.0:
+ mnemonist@0.40.3:
dependencies:
- acorn: 8.11.3
- pathe: 1.1.2
- pkg-types: 1.1.1
- ufo: 1.5.3
-
- mnemonist@0.40.0-rc1:
- dependencies:
- obliterator: 2.0.4
+ obliterator: 2.0.5
module-deps@6.2.3:
dependencies:
inherits: 2.0.4
parents: 1.0.1
readable-stream: 2.3.8
- resolve: 1.22.8
+ resolve: 1.22.10
stream-combiner2: 1.1.1
subarg: 1.0.0
through2: 2.0.5
moment@2.30.1: {}
- mongodb-connection-string-url@3.0.1:
+ mongodb-connection-string-url@3.0.2:
dependencies:
'@types/whatwg-url': 11.0.5
- whatwg-url: 13.0.0
+ whatwg-url: 14.2.0
- mongodb@6.6.2(socks@2.8.3):
+ mongodb@6.17.0(socks@2.8.5):
dependencies:
- '@mongodb-js/saslprep': 1.1.7
- bson: 6.7.0
- mongodb-connection-string-url: 3.0.1
+ '@mongodb-js/saslprep': 1.3.0
+ bson: 6.10.4
+ mongodb-connection-string-url: 3.0.2
optionalDependencies:
- socks: 2.8.3
+ socks: 2.8.5
- morphdom@2.7.2: {}
-
- ms@2.0.0: {}
+ morphdom@2.7.5: {}
ms@2.1.2: {}
mute-stream@0.0.7: {}
- mute-stream@1.0.0: {}
-
mutexify@1.4.0:
dependencies:
queue-tick: 1.0.1
+ nano-spawn@1.0.2: {}
+
nanoassert@1.1.0: {}
nanobench@2.1.1:
through2: 2.0.5
transform-ast: 2.4.4
- nanoid@3.3.7: {}
+ nanoid@3.3.11: {}
+
+ napi-build-utils@2.0.0: {}
- napi-build-utils@1.0.2: {}
+ napi-postinstall@0.3.0: {}
natural-compare@1.4.0: {}
+ natural-orderby@5.0.0: {}
+
ndarray-blas-level1@1.1.3: {}
ndarray-cholesky-factorization@1.0.2:
iota-array: 1.0.0
is-buffer: 1.1.6
- negotiator@0.6.3:
+ negotiator@0.6.4:
optional: true
- neo-async@2.6.2: {}
-
- netmask@2.0.2: {}
-
- new-github-release-url@2.0.0:
+ neostandard@0.12.2(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3):
dependencies:
- type-fest: 2.19.0
+ '@humanwhocodes/gitignore-to-minimatch': 1.0.2
+ '@stylistic/eslint-plugin': 2.11.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
+ eslint: 9.30.1(jiti@2.4.2)
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2)))(eslint@9.30.1(jiti@2.4.2))
+ eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.30.1(jiti@2.4.2))
+ eslint-plugin-n: 17.21.0(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
+ eslint-plugin-promise: 7.2.1(eslint@9.30.1(jiti@2.4.2))
+ eslint-plugin-react: 7.37.5(eslint@9.30.1(jiti@2.4.2))
+ find-up: 5.0.0
+ globals: 15.15.0
+ peowly: 1.3.2
+ typescript-eslint: 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
+ transitivePeerDependencies:
+ - '@typescript-eslint/utils'
+ - eslint-import-resolver-node
+ - eslint-plugin-import
+ - supports-color
+ - typescript
next-tick@1.1.0: {}
dependencies:
lower-case: 1.1.4
- node-abi@3.62.0:
+ node-abi@3.75.0:
dependencies:
- semver: 7.6.2
+ semver: 7.7.2
- node-addon-api@7.1.0: {}
-
- node-domexception@1.0.0: {}
+ node-addon-api@7.1.1: {}
node-fetch@2.6.13(encoding@0.1.13):
dependencies:
optionalDependencies:
encoding: 0.1.13
- node-fetch@2.7.0(encoding@0.1.13):
- dependencies:
- whatwg-url: 5.0.0
- optionalDependencies:
- encoding: 0.1.13
-
- node-fetch@3.3.2:
- dependencies:
- data-uri-to-buffer: 4.0.1
- fetch-blob: 3.2.0
- formdata-polyfill: 4.0.10
-
- node-gyp-build@4.8.1:
+ node-gyp-build@4.8.4:
optional: true
node-gyp@8.4.1:
nopt: 5.0.0
npmlog: 6.0.2
rimraf: 3.0.2
- semver: 7.6.2
+ semver: 7.7.2
tar: 6.2.1
which: 2.0.2
transitivePeerDependencies:
- supports-color
optional: true
- node-releases@2.0.14: {}
+ node-releases@2.0.19: {}
nopt@5.0.0:
dependencies:
normalize-path@3.0.0: {}
- normalize-url@8.0.1: {}
+ normalize-url@8.0.2: {}
npm-run-path@4.0.1:
dependencies:
path-key: 3.1.1
- npm-run-path@5.3.0:
- dependencies:
- path-key: 4.0.0
-
npmlog@6.0.2:
dependencies:
are-we-there-yet: 3.0.1
number-is-nan@1.0.1: {}
- nwsapi@2.2.10: {}
+ nwsapi@2.2.20: {}
oauth-sign@0.9.0: {}
+ object-assign@4.1.1: {}
+
object-hash@3.0.0: {}
- object-inspect@1.13.1: {}
+ object-inspect@1.13.4: {}
object-keys@1.1.1: {}
- object.assign@4.1.5:
+ object.assign@4.1.7:
dependencies:
- call-bind: 1.0.7
+ call-bind: 1.0.8
+ call-bound: 1.0.4
define-properties: 1.2.1
- has-symbols: 1.0.3
+ es-object-atoms: 1.1.1
+ has-symbols: 1.1.0
object-keys: 1.1.1
- object.fromentries@2.0.8:
+ object.entries@1.1.9:
dependencies:
- call-bind: 1.0.7
+ call-bind: 1.0.8
+ call-bound: 1.0.4
define-properties: 1.2.1
- es-abstract: 1.23.3
- es-object-atoms: 1.0.0
+ es-object-atoms: 1.1.1
- object.groupby@1.0.3:
+ object.fromentries@2.0.8:
dependencies:
- call-bind: 1.0.7
+ call-bind: 1.0.8
define-properties: 1.2.1
- es-abstract: 1.23.3
+ es-abstract: 1.24.0
+ es-object-atoms: 1.1.1
- object.values@1.2.0:
+ object.values@1.2.1:
dependencies:
- call-bind: 1.0.7
+ call-bind: 1.0.8
+ call-bound: 1.0.4
define-properties: 1.2.1
- es-object-atoms: 1.0.0
+ es-object-atoms: 1.1.1
- obliterator@2.0.4: {}
+ obliterator@2.0.5: {}
on-finished@2.4.1:
dependencies:
dependencies:
mimic-fn: 2.1.0
- onetime@6.0.0:
- dependencies:
- mimic-fn: 4.0.0
-
- open@10.1.0:
+ onetime@7.0.0:
dependencies:
- default-browser: 5.2.1
- define-lazy-prop: 3.0.0
- is-inside-container: 1.0.0
- is-wsl: 3.1.0
+ mimic-function: 5.0.1
open@7.4.2:
dependencies:
strip-ansi: 6.0.1
wcwidth: 1.0.1
- ora@8.0.1:
- dependencies:
- chalk: 5.3.0
- cli-cursor: 4.0.0
- cli-spinners: 2.9.2
- is-interactive: 2.0.0
- is-unicode-supported: 2.0.0
- log-symbols: 6.0.0
- stdin-discarder: 0.2.2
- string-width: 7.1.0
- strip-ansi: 7.1.0
-
os-browserify@0.3.0: {}
os-name@4.0.1:
macos-release: 2.5.1
windows-release: 4.0.0
- os-name@5.1.0:
- dependencies:
- macos-release: 3.2.0
- windows-release: 5.1.1
-
os-tmpdir@1.0.2: {}
+ own-keys@1.0.1:
+ dependencies:
+ get-intrinsic: 1.3.0
+ object-keys: 1.1.1
+ safe-push-apply: 1.0.0
+
p-cancelable@3.0.0: {}
p-limit@2.3.0:
p-limit@4.0.0:
dependencies:
- yocto-queue: 1.0.0
-
- p-limit@5.0.0:
- dependencies:
- yocto-queue: 1.0.0
+ yocto-queue: 1.2.1
p-locate@3.0.0:
dependencies:
p-try@2.2.0: {}
- pac-proxy-agent@7.0.1:
- dependencies:
- '@tootallnate/quickjs-emscripten': 0.23.0
- agent-base: 7.1.1
- debug: 4.3.4
- get-uri: 6.0.3
- http-proxy-agent: 7.0.2
- https-proxy-agent: 7.0.4
- pac-resolver: 7.0.1
- socks-proxy-agent: 8.0.3
- transitivePeerDependencies:
- - supports-color
-
- pac-resolver@7.0.1:
- dependencies:
- degenerator: 5.0.1
- netmask: 2.0.2
+ package-json-from-dist@1.0.1: {}
package-json@6.5.0:
dependencies:
got: 12.6.1
registry-auth-token: 4.2.2
registry-url: 5.1.0
- semver: 7.6.2
-
- package-json@8.1.1:
- dependencies:
- got: 12.6.1
- registry-auth-token: 5.0.2
- registry-url: 6.0.1
- semver: 7.6.2
+ semver: 7.7.2
pako@1.0.11: {}
dependencies:
callsites: 3.1.0
+ parent-module@2.0.0:
+ dependencies:
+ callsites: 3.1.0
+
parent-require@1.0.0: {}
parents@1.0.1:
asn1.js: 4.10.1
browserify-aes: 1.2.0
evp_bytestokey: 1.0.3
- hash-base: 3.0.4
- pbkdf2: 3.1.2
+ hash-base: 3.0.5
+ pbkdf2: 3.1.3
safe-buffer: 5.2.1
- parse-github-url@1.0.2: {}
+ parse-imports-exports@0.2.4:
+ dependencies:
+ parse-statements: 1.0.11
parse-json@5.2.0:
dependencies:
- '@babel/code-frame': 7.24.2
+ '@babel/code-frame': 7.27.1
error-ex: 1.3.2
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
- parse-path@7.0.0:
- dependencies:
- protocols: 2.0.1
-
- parse-url@8.1.0:
- dependencies:
- parse-path: 7.0.0
+ parse-statements@1.0.11: {}
- parse5@7.1.2:
+ parse5@7.3.0:
dependencies:
- entities: 4.5.0
+ entities: 6.0.1
parseurl@1.3.3: {}
path-key@3.1.1: {}
- path-key@4.0.0: {}
-
path-parse@1.0.7: {}
path-platform@0.11.15: {}
path-scurry@1.11.1:
dependencies:
- lru-cache: 10.2.2
- minipass: 7.1.1
+ lru-cache: 10.4.3
+ minipass: 7.1.2
- path-type@4.0.0: {}
+ path-scurry@2.0.0:
+ dependencies:
+ lru-cache: 11.1.0
+ minipass: 7.1.2
- path-type@5.0.0: {}
+ path-type@4.0.0: {}
- pathe@1.1.2: {}
+ pathe@2.0.3: {}
- pathval@1.1.1: {}
+ pathval@2.0.1: {}
- pbkdf2@3.1.2:
+ pbkdf2@3.1.3:
dependencies:
- create-hash: 1.2.0
+ create-hash: 1.1.3
create-hmac: 1.1.7
- ripemd160: 2.0.2
+ ripemd160: 2.0.1
safe-buffer: 5.2.1
- sha.js: 2.4.11
+ sha.js: 2.4.12
+ to-buffer: 1.2.1
+
+ peowly@1.3.2: {}
performance-now@2.1.0: {}
pg-connection-string@2.6.2: {}
- picocolors@1.0.1: {}
+ picocolors@1.1.1: {}
picomatch@2.3.1: {}
+ picomatch@4.0.2: {}
+
pidtree@0.6.0: {}
pify@2.3.0: {}
- pkg-types@1.1.1:
- dependencies:
- confbox: 0.1.7
- mlly: 1.7.0
- pathe: 1.1.2
-
pkg-up@3.1.0:
dependencies:
find-up: 3.0.0
- poolifier@4.0.10: {}
+ poolifier@5.0.2: {}
- possible-typed-array-names@1.0.0: {}
+ possible-typed-array-names@1.1.0: {}
- postcss-import@13.0.0(postcss@8.4.38):
+ postcss-import@13.0.0(postcss@8.5.6):
dependencies:
- postcss: 8.4.38
+ postcss: 8.5.6
postcss-value-parser: 4.2.0
read-cache: 1.0.0
- resolve: 1.22.8
+ resolve: 1.22.10
- postcss-selector-parser@6.0.16:
+ postcss-selector-parser@6.1.2:
dependencies:
cssesc: 3.0.0
util-deprecate: 1.0.2
postcss-value-parser@4.2.0: {}
- postcss@8.4.38:
+ postcss@8.5.6:
dependencies:
- nanoid: 3.3.7
- picocolors: 1.0.1
- source-map-js: 1.2.0
+ nanoid: 3.3.11
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
- prebuild-install@7.1.2:
+ prebuild-install@7.1.3:
dependencies:
- detect-libc: 2.0.3
+ detect-libc: 2.0.4
expand-template: 2.0.3
github-from-package: 0.0.0
minimist: 1.2.8
mkdirp-classic: 0.5.3
- napi-build-utils: 1.0.2
- node-abi: 3.62.0
- pump: 3.0.0
+ napi-build-utils: 2.0.0
+ node-abi: 3.75.0
+ pump: 3.0.3
rc: 1.2.8
simple-get: 4.0.1
- tar-fs: 2.1.1
+ tar-fs: 2.1.3
tunnel-agent: 0.6.0
prelude-ls@1.1.2: {}
prelude-ls@1.2.1: {}
- prettier-linter-helpers@1.0.0:
- dependencies:
- fast-diff: 1.3.0
-
- prettier@3.2.5: {}
+ prettier@3.6.2: {}
pretty-bytes@5.6.0: {}
- pretty-format@29.7.0:
- dependencies:
- '@jest/schemas': 29.6.3
- ansi-styles: 5.2.0
- react-is: 18.3.1
-
pretty-hrtime@1.0.3: {}
process-nextick-args@2.0.1: {}
retry: 0.12.0
optional: true
- promise.allsettled@1.0.7:
+ prop-types@15.8.1:
dependencies:
- array.prototype.map: 1.0.7
- call-bind: 1.0.7
- define-properties: 1.2.1
- es-abstract: 1.23.3
- get-intrinsic: 1.2.4
- iterate-value: 1.0.2
+ loose-envify: 1.4.0
+ object-assign: 4.1.1
+ react-is: 16.13.1
proto-list@1.2.4: {}
protocol-buffers-encodings@1.2.0:
dependencies:
- b4a: 1.6.6
+ b4a: 1.6.7
signed-varint: 2.0.1
varint: 5.0.0
signed-varint: 2.0.1
varint: 5.0.2
- protocols@2.0.1: {}
-
- proxy-agent@6.4.0:
+ psl@1.15.0:
dependencies:
- agent-base: 7.1.1
- debug: 4.3.4
- http-proxy-agent: 7.0.2
- https-proxy-agent: 7.0.4
- lru-cache: 7.18.3
- pac-proxy-agent: 7.0.1
- proxy-from-env: 1.1.0
- socks-proxy-agent: 8.0.3
- transitivePeerDependencies:
- - supports-color
-
- proxy-from-env@1.1.0: {}
-
- psl@1.9.0: {}
+ punycode: 2.3.1
public-encrypt@4.0.3:
dependencies:
- bn.js: 4.12.0
- browserify-rsa: 4.1.0
+ bn.js: 4.12.2
+ browserify-rsa: 4.1.1
create-hash: 1.2.0
parse-asn1: 5.1.7
randombytes: 2.1.0
safe-buffer: 5.2.1
- pump@3.0.0:
+ pump@3.0.3:
dependencies:
- end-of-stream: 1.4.4
+ end-of-stream: 1.4.5
once: 1.4.0
pumpify@2.0.1:
dependencies:
duplexify: 4.1.3
inherits: 2.0.4
- pump: 3.0.0
+ pump: 3.0.3
punycode@1.4.1: {}
dependencies:
escape-goat: 2.1.1
- pupa@3.1.0:
- dependencies:
- escape-goat: 4.0.0
-
- qs@6.12.1:
+ qs@6.14.0:
dependencies:
- side-channel: 1.0.6
+ side-channel: 1.1.0
qs@6.5.3: {}
minimist: 1.2.8
through2: 2.0.5
- rambda@9.2.0: {}
-
randombytes@2.1.0:
dependencies:
safe-buffer: 5.2.1
minimist: 1.2.8
strip-json-comments: 2.0.1
- react-is@18.3.1: {}
+ react-is@16.13.1: {}
read-cache@1.0.0:
dependencies:
dependencies:
picomatch: 2.3.1
- rechoir@0.6.2:
- dependencies:
- resolve: 1.22.8
-
rechoir@0.8.0:
dependencies:
- resolve: 1.22.8
+ resolve: 1.22.10
reflect-metadata@0.2.2: {}
- regexp.prototype.flags@1.5.2:
+ reflect.getprototypeof@1.0.10:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ get-proto: 1.0.1
+ which-builtin-type: 1.2.1
+
+ regexp.prototype.flags@1.5.4:
dependencies:
- call-bind: 1.0.7
+ call-bind: 1.0.8
define-properties: 1.2.1
es-errors: 1.3.0
+ get-proto: 1.0.1
+ gopd: 1.2.0
set-function-name: 2.0.2
registry-auth-token@4.2.2:
dependencies:
rc: 1.2.8
- registry-auth-token@5.0.2:
- dependencies:
- '@pnpm/npm-conf': 2.2.2
-
registry-url@5.1.0:
dependencies:
rc: 1.2.8
- registry-url@6.0.1:
- dependencies:
- rc: 1.2.8
-
reinterval@1.1.0: {}
- release-it@17.3.0(typescript@5.4.5):
- dependencies:
- '@iarna/toml': 2.2.5
- '@octokit/rest': 20.1.1
- async-retry: 1.3.3
- chalk: 5.3.0
- cosmiconfig: 9.0.0(typescript@5.4.5)
- execa: 8.0.1
- git-url-parse: 14.0.0
- globby: 14.0.1
- got: 12.6.1
- inquirer: 9.2.22
- is-ci: 3.0.1
- issue-parser: 7.0.0
- lodash: 4.17.21
- mime-types: 2.1.35
- new-github-release-url: 2.0.0
- node-fetch: 3.3.2
- open: 10.1.0
- ora: 8.0.1
- os-name: 5.1.0
- promise.allsettled: 1.0.7
- proxy-agent: 6.4.0
- semver: 7.6.2
- shelljs: 0.8.5
- update-notifier: 7.0.0
- url-join: 5.0.0
- wildcard-match: 5.1.3
- yargs-parser: 21.1.1
- transitivePeerDependencies:
- - supports-color
- - typescript
+ repeat-string@1.6.1: {}
request@2.88.2:
dependencies:
aws-sign2: 0.7.0
- aws4: 1.13.0
+ aws4: 1.13.2
caseless: 0.12.0
combined-stream: 1.0.8
extend: 3.0.2
resolve-pkg-maps@1.0.0: {}
- resolve@1.19.0:
+ resolve@1.22.10:
dependencies:
- is-core-module: 2.13.1
+ is-core-module: 2.16.1
path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
- resolve@1.22.8:
+ resolve@2.0.0-next.5:
dependencies:
- is-core-module: 2.13.1
+ is-core-module: 2.16.1
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
onetime: 5.1.2
signal-exit: 3.0.7
- restore-cursor@4.0.0:
+ restore-cursor@5.1.0:
dependencies:
- onetime: 5.1.2
- signal-exit: 3.0.7
+ onetime: 7.0.0
+ signal-exit: 4.1.0
retimer@3.0.0: {}
retry@0.12.0:
optional: true
- retry@0.13.1: {}
+ reusify@1.1.0: {}
- reusify@1.0.4: {}
-
- rfdc@1.3.1: {}
+ rfdc@1.4.1: {}
rimraf@3.0.2:
dependencies:
glob: 7.2.3
- rimraf@5.0.7:
+ rimraf@6.0.1:
+ dependencies:
+ glob: 11.0.3
+ package-json-from-dist: 1.0.1
+
+ ripemd160@2.0.1:
dependencies:
- glob: 10.3.15
+ hash-base: 2.0.2
+ inherits: 2.0.4
ripemd160@2.0.2:
dependencies:
- hash-base: 3.1.0
+ hash-base: 3.0.5
inherits: 2.0.4
- rollup@4.17.2:
+ rollup@4.44.1:
dependencies:
- '@types/estree': 1.0.5
+ '@types/estree': 1.0.8
optionalDependencies:
- '@rollup/rollup-android-arm-eabi': 4.17.2
- '@rollup/rollup-android-arm64': 4.17.2
- '@rollup/rollup-darwin-arm64': 4.17.2
- '@rollup/rollup-darwin-x64': 4.17.2
- '@rollup/rollup-linux-arm-gnueabihf': 4.17.2
- '@rollup/rollup-linux-arm-musleabihf': 4.17.2
- '@rollup/rollup-linux-arm64-gnu': 4.17.2
- '@rollup/rollup-linux-arm64-musl': 4.17.2
- '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2
- '@rollup/rollup-linux-riscv64-gnu': 4.17.2
- '@rollup/rollup-linux-s390x-gnu': 4.17.2
- '@rollup/rollup-linux-x64-gnu': 4.17.2
- '@rollup/rollup-linux-x64-musl': 4.17.2
- '@rollup/rollup-win32-arm64-msvc': 4.17.2
- '@rollup/rollup-win32-ia32-msvc': 4.17.2
- '@rollup/rollup-win32-x64-msvc': 4.17.2
+ '@rollup/rollup-android-arm-eabi': 4.44.1
+ '@rollup/rollup-android-arm64': 4.44.1
+ '@rollup/rollup-darwin-arm64': 4.44.1
+ '@rollup/rollup-darwin-x64': 4.44.1
+ '@rollup/rollup-freebsd-arm64': 4.44.1
+ '@rollup/rollup-freebsd-x64': 4.44.1
+ '@rollup/rollup-linux-arm-gnueabihf': 4.44.1
+ '@rollup/rollup-linux-arm-musleabihf': 4.44.1
+ '@rollup/rollup-linux-arm64-gnu': 4.44.1
+ '@rollup/rollup-linux-arm64-musl': 4.44.1
+ '@rollup/rollup-linux-loongarch64-gnu': 4.44.1
+ '@rollup/rollup-linux-powerpc64le-gnu': 4.44.1
+ '@rollup/rollup-linux-riscv64-gnu': 4.44.1
+ '@rollup/rollup-linux-riscv64-musl': 4.44.1
+ '@rollup/rollup-linux-s390x-gnu': 4.44.1
+ '@rollup/rollup-linux-x64-gnu': 4.44.1
+ '@rollup/rollup-linux-x64-musl': 4.44.1
+ '@rollup/rollup-win32-arm64-msvc': 4.44.1
+ '@rollup/rollup-win32-ia32-msvc': 4.44.1
+ '@rollup/rollup-win32-x64-msvc': 4.44.1
fsevents: 2.3.3
- rrweb-cssom@0.6.0: {}
-
- run-applescript@7.0.0: {}
+ rrweb-cssom@0.8.0: {}
run-async@2.4.1: {}
- run-async@3.0.0: {}
-
run-parallel@1.2.0:
dependencies:
queue-microtask: 1.2.3
dependencies:
tslib: 1.14.1
- rxjs@7.8.1:
- dependencies:
- tslib: 2.6.2
-
- safe-array-concat@1.1.2:
+ safe-array-concat@1.1.3:
dependencies:
- call-bind: 1.0.7
- get-intrinsic: 1.2.4
- has-symbols: 1.0.3
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+ has-symbols: 1.1.0
isarray: 2.0.5
safe-buffer@5.1.2: {}
safe-buffer@5.2.1: {}
- safe-regex-test@1.0.3:
+ safe-push-apply@1.0.0:
dependencies:
- call-bind: 1.0.7
es-errors: 1.3.0
- is-regex: 1.1.4
+ isarray: 2.0.5
+
+ safe-regex-test@1.1.0:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-regex: 1.2.1
- safe-stable-stringify@2.4.3: {}
+ safe-stable-stringify@2.5.0: {}
safer-buffer@2.1.2: {}
semver-diff@3.1.1:
dependencies:
- semver: 7.6.2
+ semver: 7.7.2
- semver-diff@4.0.0:
- dependencies:
- semver: 7.6.2
-
- semver@7.6.2: {}
+ semver@7.7.2: {}
- send@0.18.0:
+ send@1.2.0:
dependencies:
- debug: 2.6.9
- depd: 2.0.0
- destroy: 1.2.0
- encodeurl: 1.0.2
+ debug: 4.4.1
+ encodeurl: 2.0.0
escape-html: 1.0.3
etag: 1.8.1
- fresh: 0.5.2
+ fresh: 2.0.0
http-errors: 2.0.0
- mime: 1.6.0
+ mime-types: 3.0.1
ms: 2.1.3
on-finished: 2.4.1
range-parser: 1.2.1
- statuses: 2.0.1
+ statuses: 2.0.2
transitivePeerDependencies:
- supports-color
- serve-static@1.15.0:
+ serve-static@2.2.0:
dependencies:
- encodeurl: 1.0.2
+ encodeurl: 2.0.0
escape-html: 1.0.3
parseurl: 1.3.3
- send: 0.18.0
+ send: 1.2.0
transitivePeerDependencies:
- supports-color
define-data-property: 1.1.4
es-errors: 1.3.0
function-bind: 1.1.2
- get-intrinsic: 1.2.4
- gopd: 1.0.1
+ get-intrinsic: 1.3.0
+ gopd: 1.2.0
has-property-descriptors: 1.0.2
set-function-name@2.0.2:
functions-have-names: 1.2.3
has-property-descriptors: 1.0.2
+ set-proto@1.0.0:
+ dependencies:
+ dunder-proto: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+
setprototypeof@1.2.0: {}
- sha.js@2.4.11:
+ sha.js@2.4.12:
dependencies:
inherits: 2.0.4
safe-buffer: 5.2.1
+ to-buffer: 1.2.1
shallow-copy@0.0.1: {}
shebang-regex@3.0.0: {}
- shell-quote@1.8.1: {}
-
- shelljs@0.8.5:
- dependencies:
- glob: 7.2.3
- interpret: 1.4.0
- rechoir: 0.6.2
+ shell-quote@1.8.3: {}
showdown@1.9.1:
dependencies:
yargs: 14.2.3
- side-channel@1.0.6:
+ side-channel-list@1.0.0:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-map@1.0.1:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-weakmap@1.0.2:
dependencies:
- call-bind: 1.0.7
+ call-bound: 1.0.4
es-errors: 1.3.0
- get-intrinsic: 1.2.4
- object-inspect: 1.13.1
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-map: 1.0.1
+
+ side-channel@1.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-list: 1.0.0
+ side-channel-map: 1.0.1
+ side-channel-weakmap: 1.0.2
siginfo@2.0.0: {}
slash@3.0.0: {}
- slash@5.1.0: {}
-
slice-ansi@5.0.0:
dependencies:
ansi-styles: 6.2.1
ansi-styles: 6.2.1
is-fullwidth-code-point: 5.0.0
- smart-buffer@4.2.0: {}
+ smart-buffer@4.2.0:
+ optional: true
socks-proxy-agent@6.2.1:
dependencies:
agent-base: 6.0.2
- debug: 4.3.4
- socks: 2.8.3
+ debug: 4.4.1
+ socks: 2.8.5
transitivePeerDependencies:
- supports-color
optional: true
- socks-proxy-agent@8.0.3:
- dependencies:
- agent-base: 7.1.1
- debug: 4.3.4
- socks: 2.8.3
- transitivePeerDependencies:
- - supports-color
-
- socks@2.8.3:
+ socks@2.8.5:
dependencies:
ip-address: 9.0.5
smart-buffer: 4.2.0
+ optional: true
sonic-boom@1.4.1:
dependencies:
atomic-sleep: 1.0.0
flatstr: 1.0.12
- source-map-js@1.2.0: {}
+ source-map-js@1.2.1: {}
source-map-support@0.5.21:
dependencies:
spdx-expression-parse@4.0.0:
dependencies:
spdx-exceptions: 2.5.0
- spdx-license-ids: 3.0.17
+ spdx-license-ids: 3.0.21
- spdx-license-ids@3.0.17: {}
+ spdx-license-ids@3.0.21: {}
split2@4.2.0: {}
- sprintf-js@1.1.3: {}
+ sprintf-js@1.1.3:
+ optional: true
sqlite3@5.1.7:
dependencies:
bindings: 1.5.0
- node-addon-api: 7.1.0
- prebuild-install: 7.1.2
+ node-addon-api: 7.1.1
+ prebuild-install: 7.1.3
tar: 6.2.1
optionalDependencies:
node-gyp: 8.4.1
minipass: 3.3.6
optional: true
- stack-trace@0.0.10: {}
+ stable-hash-x@0.2.0: {}
- stack-utils@2.0.6:
- dependencies:
- escape-string-regexp: 2.0.0
+ stable-hash@0.0.5: {}
+
+ stack-trace@0.0.10: {}
stackback@0.0.2: {}
has: 1.0.4
magic-string: 0.25.1
merge-source-map: 1.0.4
- object-inspect: 1.13.1
+ object-inspect: 1.13.4
readable-stream: 2.3.8
scope-analyzer: 2.1.2
shallow-copy: 0.0.1
statuses@2.0.1: {}
- std-env@3.7.0: {}
+ statuses@2.0.2: {}
- stdin-discarder@0.2.2: {}
+ std-env@3.9.0: {}
- stop-iteration-iterator@1.0.0:
+ stop-iteration-iterator@1.1.0:
dependencies:
- internal-slot: 1.0.7
+ es-errors: 1.3.0
+ internal-slot: 1.1.0
stream-browserify@3.0.0:
dependencies:
stream-template@0.0.10:
dependencies:
- end-of-stream: 1.4.4
+ end-of-stream: 1.4.5
readable-stream: 2.3.8
streaming-json-stringify@3.1.0:
emoji-regex: 9.2.2
strip-ansi: 7.1.0
- string-width@7.1.0:
+ string-width@7.2.0:
dependencies:
- emoji-regex: 10.3.0
- get-east-asian-width: 1.2.0
+ emoji-regex: 10.4.0
+ get-east-asian-width: 1.3.0
strip-ansi: 7.1.0
- string.prototype.trim@1.2.9:
+ string.prototype.matchall@4.0.12:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ gopd: 1.2.0
+ has-symbols: 1.1.0
+ internal-slot: 1.1.0
+ regexp.prototype.flags: 1.5.4
+ set-function-name: 2.0.2
+ side-channel: 1.1.0
+
+ string.prototype.repeat@1.0.0:
+ dependencies:
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+
+ string.prototype.trim@1.2.10:
dependencies:
- call-bind: 1.0.7
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-data-property: 1.1.4
define-properties: 1.2.1
- es-abstract: 1.23.3
- es-object-atoms: 1.0.0
+ es-abstract: 1.24.0
+ es-object-atoms: 1.1.1
+ has-property-descriptors: 1.0.2
- string.prototype.trimend@1.0.8:
+ string.prototype.trimend@1.0.9:
dependencies:
- call-bind: 1.0.7
+ call-bind: 1.0.8
+ call-bound: 1.0.4
define-properties: 1.2.1
- es-object-atoms: 1.0.0
+ es-object-atoms: 1.1.1
string.prototype.trimstart@1.0.8:
dependencies:
- call-bind: 1.0.7
+ call-bind: 1.0.8
define-properties: 1.2.1
- es-object-atoms: 1.0.0
+ es-object-atoms: 1.1.1
string_decoder@1.1.1:
dependencies:
strip-ansi@7.1.0:
dependencies:
- ansi-regex: 6.0.1
+ ansi-regex: 6.1.0
strip-bom@3.0.0: {}
strip-final-newline@2.0.0: {}
- strip-final-newline@3.0.0: {}
-
strip-json-comments@2.0.1: {}
strip-json-comments@3.1.1: {}
- strip-literal@2.1.0:
+ strip-literal@3.0.0:
dependencies:
- js-tokens: 9.0.0
+ js-tokens: 9.0.1
subarg@1.0.0:
dependencies:
supports-preserve-symlinks-flag@1.0.0: {}
- svg-tags@1.0.0: {}
-
symbol-tree@3.2.4: {}
- synckit@0.8.8:
+ synckit@0.11.8:
dependencies:
- '@pkgr/core': 0.1.1
- tslib: 2.6.2
+ '@pkgr/core': 0.2.7
syntax-error@1.4.0:
dependencies:
tachyons@4.12.0: {}
- tapable@2.2.1: {}
+ tapable@2.2.2: {}
- tar-fs@2.1.1:
+ tar-fs@2.1.3:
dependencies:
chownr: 1.1.4
mkdirp-classic: 0.5.3
- pump: 3.0.0
+ pump: 3.0.3
tar-stream: 2.2.0
tar-stream@2.2.0:
dependencies:
bl: 4.1.0
- end-of-stream: 1.4.4
+ end-of-stream: 1.4.5
fs-constants: 1.0.0
inherits: 2.0.4
readable-stream: 3.6.2
mkdirp: 1.0.4
yallist: 4.0.0
- tar@7.1.0:
+ tar@7.4.3:
dependencies:
'@isaacs/fs-minipass': 4.0.1
chownr: 3.0.0
- minipass: 7.1.1
- minizlib: 3.0.1
+ minipass: 7.1.2
+ minizlib: 3.0.2
mkdirp: 3.0.1
yallist: 5.0.0
terser@4.8.1:
dependencies:
- acorn: 8.11.3
+ acorn: 8.15.0
commander: 2.20.3
source-map: 0.6.1
source-map-support: 0.5.21
- test-exclude@6.0.0:
+ test-exclude@7.0.1:
dependencies:
'@istanbuljs/schema': 0.1.3
- glob: 7.2.3
- minimatch: 3.1.2
+ glob: 10.4.5
+ minimatch: 9.0.5
text-extensions@2.4.0: {}
text-hex@1.0.0: {}
- text-table@0.2.0: {}
-
through2@2.0.5:
dependencies:
readable-stream: 2.3.8
timestring@6.0.0: {}
- tinybench@2.8.0: {}
+ tinybench@2.9.0: {}
+
+ tinyexec@0.3.2: {}
- tinypool@0.8.4: {}
+ tinyexec@1.0.1: {}
- tinyspy@2.2.1: {}
+ tinyglobby@0.2.14:
+ dependencies:
+ fdir: 6.4.6(picomatch@4.0.2)
+ picomatch: 4.0.2
+
+ tinypool@1.1.1: {}
+
+ tinyrainbow@2.0.0: {}
+
+ tinyspy@4.0.3: {}
tmp@0.0.33:
dependencies:
os-tmpdir: 1.0.2
- to-fast-properties@2.0.0: {}
+ to-buffer@1.2.1:
+ dependencies:
+ isarray: 2.0.5
+ safe-buffer: 5.2.1
+ typed-array-buffer: 1.0.3
to-regex-range@5.0.1:
dependencies:
tough-cookie@4.1.4:
dependencies:
- psl: 1.9.0
+ psl: 1.15.0
punycode: 2.3.1
universalify: 0.2.0
url-parse: 1.5.10
tr46@0.0.3: {}
- tr46@4.1.1:
- dependencies:
- punycode: 2.3.1
-
- tr46@5.0.0:
+ tr46@5.1.1:
dependencies:
punycode: 2.3.1
triple-beam@1.4.1: {}
- ts-api-utils@1.3.0(typescript@5.4.5):
+ ts-api-utils@2.1.0(typescript@5.8.3):
+ dependencies:
+ typescript: 5.8.3
+
+ ts-declaration-location@1.0.7(typescript@5.8.3):
dependencies:
- typescript: 5.4.5
+ picomatch: 4.0.2
+ typescript: 5.8.3
- ts-morph@22.0.0:
+ ts-morph@26.0.0:
dependencies:
- '@ts-morph/common': 0.23.0
- code-block-writer: 13.0.1
+ '@ts-morph/common': 0.27.0
+ code-block-writer: 13.0.3
- ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5):
+ ts-node@10.9.2(@types/node@24.0.10)(typescript@5.8.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.11
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.4
- '@types/node': 20.12.12
- acorn: 8.11.3
- acorn-walk: 8.3.2
+ '@types/node': 24.0.10
+ acorn: 8.15.0
+ acorn-walk: 8.3.4
arg: 4.1.3
create-require: 1.1.1
diff: 4.0.2
make-error: 1.3.6
- typescript: 5.4.5
+ typescript: 5.8.3
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
- tsconfig-paths@3.15.0:
- dependencies:
- '@types/json5': 0.0.29
- json5: 1.0.2
- minimist: 1.2.8
- strip-bom: 3.0.0
-
tsconfig-paths@4.2.0:
dependencies:
json5: 2.2.3
tslib@1.14.1: {}
- tslib@2.6.2: {}
+ tslib@2.8.1:
+ optional: true
- tsx@4.10.5:
+ tsx@4.20.3:
dependencies:
- esbuild: 0.20.2
- get-tsconfig: 4.7.5
+ esbuild: 0.25.5
+ get-tsconfig: 4.10.1
optionalDependencies:
fsevents: 2.3.3
type-component@0.0.1: {}
- type-detect@4.0.8: {}
-
type-fest@0.20.2: {}
- type-fest@0.21.3: {}
-
- type-fest@1.4.0: {}
-
- type-fest@2.19.0: {}
+ type@2.7.3: {}
- type@2.7.2: {}
-
- typed-array-buffer@1.0.2:
+ typed-array-buffer@1.0.3:
dependencies:
- call-bind: 1.0.7
+ call-bound: 1.0.4
es-errors: 1.3.0
- is-typed-array: 1.1.13
+ is-typed-array: 1.1.15
- typed-array-byte-length@1.0.1:
+ typed-array-byte-length@1.0.3:
dependencies:
- call-bind: 1.0.7
- for-each: 0.3.3
- gopd: 1.0.1
- has-proto: 1.0.3
- is-typed-array: 1.1.13
+ call-bind: 1.0.8
+ for-each: 0.3.5
+ gopd: 1.2.0
+ has-proto: 1.2.0
+ is-typed-array: 1.1.15
- typed-array-byte-offset@1.0.2:
+ typed-array-byte-offset@1.0.4:
dependencies:
available-typed-arrays: 1.0.7
- call-bind: 1.0.7
- for-each: 0.3.3
- gopd: 1.0.1
- has-proto: 1.0.3
- is-typed-array: 1.1.13
-
- typed-array-length@1.0.6:
- dependencies:
- call-bind: 1.0.7
- for-each: 0.3.3
- gopd: 1.0.1
- has-proto: 1.0.3
- is-typed-array: 1.1.13
- possible-typed-array-names: 1.0.0
+ call-bind: 1.0.8
+ for-each: 0.3.5
+ gopd: 1.2.0
+ has-proto: 1.2.0
+ is-typed-array: 1.1.15
+ reflect.getprototypeof: 1.0.10
+
+ typed-array-length@1.0.7:
+ dependencies:
+ call-bind: 1.0.8
+ for-each: 0.3.5
+ gopd: 1.2.0
+ is-typed-array: 1.1.15
+ possible-typed-array-names: 1.1.0
+ reflect.getprototypeof: 1.0.10
typedarray-pool@1.2.0:
dependencies:
typedarray@0.0.6: {}
- typescript@5.4.5: {}
-
- ufo@1.5.3: {}
+ typescript-eslint@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3):
+ dependencies:
+ '@typescript-eslint/eslint-plugin': 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
+ '@typescript-eslint/parser': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
+ '@typescript-eslint/utils': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)
+ eslint: 9.30.1(jiti@2.4.2)
+ typescript: 5.8.3
+ transitivePeerDependencies:
+ - supports-color
- uglify-js@3.17.4:
- optional: true
+ typescript@5.8.3: {}
umd@3.0.3: {}
- unbox-primitive@1.0.2:
+ unbox-primitive@1.1.0:
dependencies:
- call-bind: 1.0.7
- has-bigints: 1.0.2
- has-symbols: 1.0.3
- which-boxed-primitive: 1.0.2
+ call-bound: 1.0.4
+ has-bigints: 1.1.0
+ has-symbols: 1.1.0
+ which-boxed-primitive: 1.1.1
undeclared-identifiers@1.1.3:
dependencies:
simple-concat: 1.0.1
xtend: 4.0.2
- undici-types@5.26.5: {}
+ undici-types@6.21.0: {}
+
+ undici-types@7.8.0: {}
unicorn-magic@0.1.0: {}
dependencies:
crypto-random-string: 2.0.0
- unique-string@3.0.0:
- dependencies:
- crypto-random-string: 4.0.0
-
- universal-user-agent@6.0.1: {}
-
universalify@0.2.0: {}
universalify@2.0.1: {}
- unpipe@1.0.0: {}
-
- update-browserslist-db@1.0.16(browserslist@4.23.0):
+ unrs-resolver@1.10.1:
dependencies:
- browserslist: 4.23.0
- escalade: 3.1.2
- picocolors: 1.0.1
+ napi-postinstall: 0.3.0
+ optionalDependencies:
+ '@unrs/resolver-binding-android-arm-eabi': 1.10.1
+ '@unrs/resolver-binding-android-arm64': 1.10.1
+ '@unrs/resolver-binding-darwin-arm64': 1.10.1
+ '@unrs/resolver-binding-darwin-x64': 1.10.1
+ '@unrs/resolver-binding-freebsd-x64': 1.10.1
+ '@unrs/resolver-binding-linux-arm-gnueabihf': 1.10.1
+ '@unrs/resolver-binding-linux-arm-musleabihf': 1.10.1
+ '@unrs/resolver-binding-linux-arm64-gnu': 1.10.1
+ '@unrs/resolver-binding-linux-arm64-musl': 1.10.1
+ '@unrs/resolver-binding-linux-ppc64-gnu': 1.10.1
+ '@unrs/resolver-binding-linux-riscv64-gnu': 1.10.1
+ '@unrs/resolver-binding-linux-riscv64-musl': 1.10.1
+ '@unrs/resolver-binding-linux-s390x-gnu': 1.10.1
+ '@unrs/resolver-binding-linux-x64-gnu': 1.10.1
+ '@unrs/resolver-binding-linux-x64-musl': 1.10.1
+ '@unrs/resolver-binding-wasm32-wasi': 1.10.1
+ '@unrs/resolver-binding-win32-arm64-msvc': 1.10.1
+ '@unrs/resolver-binding-win32-ia32-msvc': 1.10.1
+ '@unrs/resolver-binding-win32-x64-msvc': 1.10.1
+
+ update-browserslist-db@1.1.3(browserslist@4.25.1):
+ dependencies:
+ browserslist: 4.25.1
+ escalade: 3.2.0
+ picocolors: 1.1.1
update-notifier@5.1.0:
dependencies:
is-yarn-global: 0.3.0
latest-version: 5.1.0
pupa: 2.1.1
- semver: 7.6.2
+ semver: 7.7.2
semver-diff: 3.1.1
xdg-basedir: 4.0.0
- update-notifier@7.0.0:
- dependencies:
- boxen: 7.1.1
- chalk: 5.3.0
- configstore: 6.0.0
- import-lazy: 4.0.0
- is-in-ci: 0.1.0
- is-installed-globally: 0.4.0
- is-npm: 6.0.0
- latest-version: 7.0.0
- pupa: 3.1.0
- semver: 7.6.2
- semver-diff: 4.0.0
- xdg-basedir: 5.1.0
-
upper-case@1.1.3: {}
uri-js@4.4.1:
dependencies:
punycode: 2.3.1
- url-join@5.0.0: {}
-
url-parse@1.5.10:
dependencies:
querystringify: 2.2.0
requires-port: 1.0.0
- url@0.11.3:
+ url@0.11.4:
dependencies:
punycode: 1.4.1
- qs: 6.12.1
+ qs: 6.14.0
- utf-8-validate@6.0.4:
+ utf-8-validate@6.0.5:
dependencies:
- node-gyp-build: 4.8.1
+ node-gyp-build: 4.8.4
optional: true
util-deprecate@1.0.2: {}
util@0.12.5:
dependencies:
inherits: 2.0.4
- is-arguments: 1.1.1
- is-generator-function: 1.0.10
- is-typed-array: 1.1.13
- which-typed-array: 1.1.15
+ is-arguments: 1.2.0
+ is-generator-function: 1.1.0
+ is-typed-array: 1.1.15
+ which-typed-array: 1.1.19
uuid-parse@1.1.0: {}
v8-compile-cache-lib@3.0.1: {}
- v8-to-istanbul@9.2.0:
+ v8-to-istanbul@9.3.0:
dependencies:
- '@jridgewell/trace-mapping': 0.3.25
+ '@jridgewell/trace-mapping': 0.3.29
'@types/istanbul-lib-coverage': 2.0.6
convert-source-map: 2.0.0
core-util-is: 1.0.2
extsprintf: 1.3.0
- vite-node@1.6.0(@types/node@20.12.12):
+ vite-node@3.2.4(@types/node@24.0.10)(jiti@2.4.2)(tsx@4.20.3)(yaml@2.8.0):
dependencies:
cac: 6.7.14
- debug: 4.3.4
- pathe: 1.1.2
- picocolors: 1.0.1
- vite: 5.2.11(@types/node@20.12.12)
+ debug: 4.4.1
+ es-module-lexer: 1.7.0
+ pathe: 2.0.3
+ vite: 7.0.2(@types/node@24.0.10)(jiti@2.4.2)(tsx@4.20.3)(yaml@2.8.0)
transitivePeerDependencies:
- '@types/node'
+ - jiti
- less
- lightningcss
- sass
+ - sass-embedded
- stylus
- sugarss
- supports-color
- terser
+ - tsx
+ - yaml
- vite@5.2.11(@types/node@20.12.12):
+ vite@7.0.2(@types/node@24.0.10)(jiti@2.4.2)(tsx@4.20.3)(yaml@2.8.0):
dependencies:
- esbuild: 0.20.2
- postcss: 8.4.38
- rollup: 4.17.2
+ esbuild: 0.25.5
+ fdir: 6.4.6(picomatch@4.0.2)
+ picomatch: 4.0.2
+ postcss: 8.5.6
+ rollup: 4.44.1
+ tinyglobby: 0.2.14
optionalDependencies:
- '@types/node': 20.12.12
+ '@types/node': 24.0.10
fsevents: 2.3.3
-
- vitest@1.6.0(@types/node@20.12.12)(jsdom@24.0.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)):
- dependencies:
- '@vitest/expect': 1.6.0
- '@vitest/runner': 1.6.0
- '@vitest/snapshot': 1.6.0
- '@vitest/spy': 1.6.0
- '@vitest/utils': 1.6.0
- acorn-walk: 8.3.2
- chai: 4.4.1
- debug: 4.3.4
- execa: 8.0.1
- local-pkg: 0.5.0
- magic-string: 0.30.10
- pathe: 1.1.2
- picocolors: 1.0.1
- std-env: 3.7.0
- strip-literal: 2.1.0
- tinybench: 2.8.0
- tinypool: 0.8.4
- vite: 5.2.11(@types/node@20.12.12)
- vite-node: 1.6.0(@types/node@20.12.12)
- why-is-node-running: 2.2.2
+ jiti: 2.4.2
+ tsx: 4.20.3
+ yaml: 2.8.0
+
+ vitest@3.2.4(@types/node@24.0.10)(jiti@2.4.2)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(tsx@4.20.3)(yaml@2.8.0):
+ dependencies:
+ '@types/chai': 5.2.2
+ '@vitest/expect': 3.2.4
+ '@vitest/mocker': 3.2.4(vite@7.0.2(@types/node@24.0.10)(jiti@2.4.2)(tsx@4.20.3)(yaml@2.8.0))
+ '@vitest/pretty-format': 3.2.4
+ '@vitest/runner': 3.2.4
+ '@vitest/snapshot': 3.2.4
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
+ chai: 5.2.0
+ debug: 4.4.1
+ expect-type: 1.2.1
+ magic-string: 0.30.17
+ pathe: 2.0.3
+ picomatch: 4.0.2
+ std-env: 3.9.0
+ tinybench: 2.9.0
+ tinyexec: 0.3.2
+ tinyglobby: 0.2.14
+ tinypool: 1.1.1
+ tinyrainbow: 2.0.0
+ vite: 7.0.2(@types/node@24.0.10)(jiti@2.4.2)(tsx@4.20.3)(yaml@2.8.0)
+ vite-node: 3.2.4(@types/node@24.0.10)(jiti@2.4.2)(tsx@4.20.3)(yaml@2.8.0)
+ why-is-node-running: 2.3.0
optionalDependencies:
- '@types/node': 20.12.12
- jsdom: 24.0.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)
+ '@types/node': 24.0.10
+ jsdom: 26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)
transitivePeerDependencies:
+ - jiti
- less
- lightningcss
+ - msw
- sass
+ - sass-embedded
- stylus
- sugarss
- supports-color
- terser
+ - tsx
+ - yaml
vm-browserify@1.1.2: {}
- vue-component-type-helpers@2.0.19: {}
+ vscode-languageserver-textdocument@1.0.12: {}
+
+ vscode-uri@3.1.0: {}
- vue-eslint-parser@9.4.2(eslint@8.57.0):
+ vue-component-type-helpers@2.2.12: {}
+
+ vue-eslint-parser@10.2.0(eslint@9.30.1(jiti@2.4.2)):
dependencies:
- debug: 4.3.4
- eslint: 8.57.0
- eslint-scope: 7.2.2
- eslint-visitor-keys: 3.4.3
- espree: 9.6.1
- esquery: 1.5.0
- lodash: 4.17.21
- semver: 7.6.2
+ debug: 4.4.1
+ eslint: 9.30.1(jiti@2.4.2)
+ eslint-scope: 8.4.0
+ eslint-visitor-keys: 4.2.1
+ espree: 10.4.0
+ esquery: 1.6.0
+ semver: 7.7.2
transitivePeerDependencies:
- supports-color
- vue-router@4.3.2(vue@3.4.27(typescript@5.4.5)):
+ vue-router@4.5.1(vue@3.5.17(typescript@5.8.3)):
dependencies:
- '@vue/devtools-api': 6.6.1
- vue: 3.4.27(typescript@5.4.5)
+ '@vue/devtools-api': 6.6.4
+ vue: 3.5.17(typescript@5.8.3)
- vue-toast-notification@3.1.2(vue@3.4.27(typescript@5.4.5)):
+ vue-toast-notification@3.1.3(vue@3.5.17(typescript@5.8.3)):
dependencies:
- vue: 3.4.27(typescript@5.4.5)
+ vue: 3.5.17(typescript@5.8.3)
- vue@3.4.27(typescript@5.4.5):
+ vue@3.5.17(typescript@5.8.3):
dependencies:
- '@vue/compiler-dom': 3.4.27
- '@vue/compiler-sfc': 3.4.27
- '@vue/runtime-dom': 3.4.27
- '@vue/server-renderer': 3.4.27(vue@3.4.27(typescript@5.4.5))
- '@vue/shared': 3.4.27
+ '@vue/compiler-dom': 3.5.17
+ '@vue/compiler-sfc': 3.5.17
+ '@vue/runtime-dom': 3.5.17
+ '@vue/server-renderer': 3.5.17(vue@3.5.17(typescript@5.8.3))
+ '@vue/shared': 3.5.17
optionalDependencies:
- typescript: 5.4.5
+ typescript: 5.8.3
w3c-xmlserializer@5.0.0:
dependencies:
dependencies:
defaults: 1.0.4
- web-streams-polyfill@3.3.3: {}
-
webfontloader@1.6.28: {}
webidl-conversions@3.0.1: {}
whatwg-mimetype@4.0.0: {}
- whatwg-url@13.0.0:
- dependencies:
- tr46: 4.1.1
- webidl-conversions: 7.0.0
-
- whatwg-url@14.0.0:
+ whatwg-url@14.2.0:
dependencies:
- tr46: 5.0.0
+ tr46: 5.1.1
webidl-conversions: 7.0.0
whatwg-url@5.0.0:
tr46: 0.0.3
webidl-conversions: 3.0.1
- which-boxed-primitive@1.0.2:
+ which-boxed-primitive@1.1.1:
+ dependencies:
+ is-bigint: 1.1.0
+ is-boolean-object: 1.2.2
+ is-number-object: 1.1.1
+ is-string: 1.1.1
+ is-symbol: 1.1.1
+
+ which-builtin-type@1.2.1:
+ dependencies:
+ call-bound: 1.0.4
+ function.prototype.name: 1.1.8
+ has-tostringtag: 1.0.2
+ is-async-function: 2.1.1
+ is-date-object: 1.1.0
+ is-finalizationregistry: 1.1.1
+ is-generator-function: 1.1.0
+ is-regex: 1.2.1
+ is-weakref: 1.1.1
+ isarray: 2.0.5
+ which-boxed-primitive: 1.1.1
+ which-collection: 1.0.2
+ which-typed-array: 1.1.19
+
+ which-collection@1.0.2:
dependencies:
- is-bigint: 1.0.4
- is-boolean-object: 1.1.2
- is-number-object: 1.0.7
- is-string: 1.0.7
- is-symbol: 1.0.4
+ is-map: 2.0.3
+ is-set: 2.0.3
+ is-weakmap: 2.0.2
+ is-weakset: 2.0.4
which-module@2.0.1: {}
- which-typed-array@1.1.15:
+ which-typed-array@1.1.19:
dependencies:
available-typed-arrays: 1.0.7
- call-bind: 1.0.7
- for-each: 0.3.3
- gopd: 1.0.1
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ for-each: 0.3.5
+ get-proto: 1.0.1
+ gopd: 1.2.0
has-tostringtag: 1.0.2
which@2.0.2:
dependencies:
isexe: 2.0.0
- why-is-node-running@2.2.2:
+ why-is-node-running@2.3.0:
dependencies:
siginfo: 2.0.0
stackback: 0.0.2
dependencies:
string-width: 4.2.3
- widest-line@4.0.1:
- dependencies:
- string-width: 5.1.2
-
- wildcard-match@5.1.3: {}
-
windows-release@4.0.0:
dependencies:
execa: 4.1.0
- windows-release@5.1.1:
- dependencies:
- execa: 5.1.1
-
- winston-daily-rotate-file@5.0.0(winston@3.13.0):
+ winston-daily-rotate-file@5.0.0(winston@3.17.0):
dependencies:
file-stream-rotator: 0.6.1
object-hash: 3.0.0
triple-beam: 1.4.1
- winston: 3.13.0
- winston-transport: 4.7.0
+ winston: 3.17.0
+ winston-transport: 4.9.0
- winston-transport@4.7.0:
+ winston-transport@4.9.0:
dependencies:
- logform: 2.6.0
+ logform: 2.7.0
readable-stream: 3.6.2
triple-beam: 1.4.1
- winston@3.13.0:
+ winston@3.17.0:
dependencies:
'@colors/colors': 1.6.0
'@dabh/diagnostics': 2.0.3
- async: 3.2.5
+ async: 3.2.6
is-stream: 2.0.1
- logform: 2.6.0
+ logform: 2.7.0
one-time: 1.0.0
readable-stream: 3.6.2
- safe-stable-stringify: 2.4.3
+ safe-stable-stringify: 2.5.0
stack-trace: 0.0.10
triple-beam: 1.4.1
- winston-transport: 4.7.0
+ winston-transport: 4.9.0
word-wrap@1.2.5: {}
- wordwrap@1.0.0: {}
-
wrap-ansi@5.1.0:
dependencies:
ansi-styles: 3.2.1
string-width: 3.1.0
strip-ansi: 5.2.0
- wrap-ansi@6.2.0:
- dependencies:
- ansi-styles: 4.3.0
- string-width: 4.2.3
- strip-ansi: 6.0.1
-
wrap-ansi@7.0.0:
dependencies:
ansi-styles: 4.3.0
wrap-ansi@9.0.0:
dependencies:
ansi-styles: 6.2.1
- string-width: 7.1.0
+ string-width: 7.2.0
strip-ansi: 7.1.0
wrappy@1.0.2: {}
signal-exit: 3.0.7
typedarray-to-buffer: 3.1.5
- ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.4):
+ ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5):
optionalDependencies:
- bufferutil: 4.0.8
- utf-8-validate: 6.0.4
+ bufferutil: 4.0.9
+ utf-8-validate: 6.0.5
xdg-basedir@4.0.0: {}
yallist@5.0.0: {}
- yaml@2.3.4: {}
+ yaml@2.8.0: {}
yargs-parser@15.0.3:
dependencies:
yargs@17.7.2:
dependencies:
cliui: 8.0.1
- escalade: 3.1.2
+ escalade: 3.2.0
get-caller-file: 2.0.5
require-directory: 2.1.1
string-width: 4.2.3
yocto-queue@0.1.0: {}
- yocto-queue@1.0.0: {}
+ yocto-queue@1.2.1: {}
+import chalk from 'chalk'
import { readFileSync } from 'node:fs'
import { exit, version } from 'node:process'
-
-import chalk from 'chalk'
// eslint-disable-next-line n/no-unpublished-import
import { satisfies } from 'semver'
+import { JSRuntime, runtime } from './runtime.js'
+
const packageJson = JSON.parse(readFileSync('./package.json', 'utf8'))
/**
`Required node version ${enginesNodeVersion} not satisfied with current version ${version}`
)
)
- // eslint-disable-next-line n/no-process-exit
exit(1)
}
}
-checkNodeVersion()
+switch (runtime) {
+ case JSRuntime.node:
+ checkNodeVersion()
+ break
+ case JSRuntime.browser:
+ case JSRuntime.bun:
+ case JSRuntime.deno:
+ case JSRuntime.workerd:
+ default:
+ console.warn(chalk.yellow(`Unsupported '${runtime}' runtime detected`))
+ break
+}
/* eslint-disable n/no-unpublished-import */
-import { env } from 'node:process'
import chalk from 'chalk'
import { build } from 'esbuild'
import { clean } from 'esbuild-plugin-clean'
import { copy } from 'esbuild-plugin-copy'
+import { env } from 'node:process'
const isDevelopmentBuild = env.BUILD === 'development'
const sourcemap = !!isDevelopmentBuild
console.info(chalk.green(`Building in ${isDevelopmentBuild ? 'development' : 'production'} mode`))
console.time('Build time')
await build({
- entryPoints: ['./src/start.ts', './src/charging-station/ChargingStationWorker.ts'],
bundle: true,
- platform: 'node',
- format: 'esm',
+ entryNames: '[name]',
+ entryPoints: ['./src/start.ts', './src/charging-station/ChargingStationWorker.ts'],
external: [
'@mikro-orm/*',
'ajv',
'mongodb',
'node:*',
'poolifier',
- 'rambda',
'tar',
'winston',
'winston/*',
'winston-daily-rotate-file',
- 'ws'
+ 'ws',
],
- treeShaking: true,
+ format: 'esm',
minify: true,
- sourcemap,
- entryNames: '[name]',
outdir: './dist',
+ platform: 'node',
plugins: [
clean({
patterns: [
'./dist/assets/json-schemas',
'./dist/assets/station-templates',
'./dist/assets/ui-protocol',
- './dist/assets/configs-docker'
- ]
+ './dist/assets/configs-docker',
+ ],
}),
copy({
assets: [
{
from: ['./src/assets/config.json'],
- to: ['./assets']
+ to: ['./assets'],
},
{
from: ['./src/assets/idtags!(-template)*.json'],
- to: ['./assets']
+ to: ['./assets'],
},
{
from: ['./src/assets/json-schemas/**/*.json'],
- to: ['./assets/json-schemas']
+ to: ['./assets/json-schemas'],
},
{
from: ['./src/assets/station-templates/**/*.json'],
- to: ['./assets/station-templates']
+ to: ['./assets/station-templates'],
},
{
from: ['./src/assets/configs-docker/*.json'],
- to: ['./assets/configs-docker']
- }
- ]
- })
- ]
+ to: ['./assets/configs-docker'],
+ },
+ ],
+ }),
+ ],
+ sourcemap,
+ treeShaking: true,
})
console.timeEnd('Build time')
const isCFEnvironment = env.VCAP_APPLICATION != null
if (isCFEnvironment === false && isCIEnvironment === false) {
// eslint-disable-next-line n/no-unpublished-import
- import('husky').then(husky => console.warn(husky.default()))
+ import('husky')
+ .then(husky => {
+ return console.warn(husky.default())
+ })
+ .catch(console.error)
}
--- /dev/null
+export const JSRuntime = {
+ browser: 'browser',
+ bun: 'bun',
+ deno: 'deno',
+ node: 'node',
+ workerd: 'workerd',
+}
+
+const isBun = !!globalThis.Bun || !!globalThis.process?.versions?.bun
+const isDeno = !!globalThis.Deno
+const isNode = globalThis.process?.release?.name === 'node'
+// eslint-disable-next-line n/no-unsupported-features/node-builtins
+const isWorkerd = globalThis.navigator?.userAgent === 'Cloudflare-Workers'
+// eslint-disable-next-line n/no-unsupported-features/node-builtins
+const isBrowser = !!globalThis.window && !!globalThis.navigator
+
+export const runtime = (() => {
+ if (isBun) return JSRuntime.bun
+ if (isDeno) return JSRuntime.deno
+ if (isNode) return JSRuntime.node
+ if (isWorkerd) return JSRuntime.workerd
+ if (isBrowser) return JSRuntime.browser
+
+ return 'unknown'
+})()
--- /dev/null
+import { env, exit } from 'node:process'
+
+const skipPreinstall = Number.parseInt(env.SKIP_PREINSTALL) || env.VCAP_APPLICATION != null
+if (skipPreinstall) {
+ exit()
+} else {
+ exit(1)
+}
--- /dev/null
+{
+ "main": "./dist/start.js",
+ "output": "./dist/evse-simulator.blob",
+ "disableExperimentalSEAWarning": true
+}
+++ /dev/null
-import { env, exit } from 'node:process'
-
-const skipPreinstall = parseInt(env.SKIP_PREINSTALL) || env.VCAP_APPLICATION != null
-if (skipPreinstall) {
- // eslint-disable-next-line n/no-process-exit
- exit()
-} else {
- // eslint-disable-next-line n/no-process-exit
- exit(1)
-}
# This is the name and version displayed in the SonarCloud UI.
sonar.projectName=e-mobility-charging-stations-simulator
-sonar.projectVersion=1.3.3
+# x-release-please-start-version
+sonar.projectVersion=2.0.10
+# x-release-please-end
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
sonar.sources=src
sonar.tests=tests
-sonar.javascript.lcov.reportPaths=coverage/lcov.info
+sonar.typescript.lcov.reportPaths=coverage/lcov.info
# Encoding of the source code. Default is default system encoding
#sonar.sourceEncoding=UTF-8
"username": "admin",
"password": "admin"
},
- "dataPropertyOrder": { "&": ["baseUrl", "protocol", "version", "username", "password"] },
+ "dataPropertyOrder": {
+ "&": ["baseUrl", "protocol", "version", "username", "password"]
+ },
"color": null,
"isPrivate": false,
"metaSortKey": 1661789025528,
"protocol": "ui",
"version": "0.0.1"
},
- "dataPropertyOrder": { "&": ["baseUrl", "username", "password", "protocol", "version"] },
+ "dataPropertyOrder": {
+ "&": ["baseUrl", "username", "password", "protocol", "version"]
+ },
"color": null,
"isPrivate": false,
"metaSortKey": 1671183662529,
// Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
+import { hoursToMilliseconds, secondsToMilliseconds } from 'date-fns'
import { randomInt } from 'node:crypto'
-import { hoursToMilliseconds, secondsToMilliseconds } from 'date-fns'
+import type { ChargingStation } from './ChargingStation.js'
import { BaseError } from '../exception/index.js'
import { PerformanceStatistics } from '../performance/index.js'
import {
AuthorizationStatus,
+ ChargingStationEvents,
RequestCommand,
type StartTransactionRequest,
type StartTransactionResponse,
type Status,
StopTransactionReason,
- type StopTransactionResponse
+ type StopTransactionResponse,
} from '../types/index.js'
import {
clone,
logger,
logPrefix,
secureRandom,
- sleep
+ sleep,
} from '../utils/index.js'
-import type { ChargingStation } from './ChargingStation.js'
-import { checkChargingStation } from './Helpers.js'
+import { checkChargingStationState } from './Helpers.js'
import { IdTagsCache } from './IdTagsCache.js'
import { isIdTagAuthorized } from './ocpp/index.js'
export class AutomaticTransactionGenerator {
private static readonly instances: Map<string, AutomaticTransactionGenerator> = new Map<
- string,
- AutomaticTransactionGenerator
+ string,
+ AutomaticTransactionGenerator
>()
public readonly connectorsStatus: Map<number, Status>
public started: boolean
+
+ private readonly chargingStation: ChargingStation
private starting: boolean
private stopping: boolean
- private readonly chargingStation: ChargingStation
private constructor (chargingStation: ChargingStation) {
this.started = false
this.initializeConnectorsStatus()
}
+ public static deleteInstance (chargingStation: ChargingStation): boolean {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return AutomaticTransactionGenerator.instances.delete(chargingStation.stationInfo!.hashId)
+ }
+
public static getInstance (
chargingStation: ChargingStation
): AutomaticTransactionGenerator | undefined {
return AutomaticTransactionGenerator.instances.get(chargingStation.stationInfo!.hashId)
}
- public static deleteInstance (chargingStation: ChargingStation): boolean {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return AutomaticTransactionGenerator.instances.delete(chargingStation.stationInfo!.hashId)
- }
-
public start (stopAbsoluteDuration?: boolean): void {
- if (!checkChargingStation(this.chargingStation, this.logPrefix())) {
+ if (!checkChargingStationState(this.chargingStation, this.logPrefix())) {
return
}
if (this.started) {
this.starting = false
}
+ public startConnector (connectorId: number, stopAbsoluteDuration?: boolean): void {
+ if (!checkChargingStationState(this.chargingStation, this.logPrefix(connectorId))) {
+ return
+ }
+ if (!this.connectorsStatus.has(connectorId)) {
+ logger.error(`${this.logPrefix(connectorId)} starting on non existing connector`)
+ throw new BaseError(`Connector ${connectorId.toString()} does not exist`)
+ }
+ if (this.connectorsStatus.get(connectorId)?.start === false) {
+ this.internalStartConnector(connectorId, stopAbsoluteDuration).catch(Constants.EMPTY_FUNCTION)
+ } else if (this.connectorsStatus.get(connectorId)?.start === true) {
+ logger.warn(`${this.logPrefix(connectorId)} is already started on connector`)
+ }
+ }
+
public stop (): void {
if (!this.started) {
logger.warn(`${this.logPrefix()} is already stopped`)
this.stopping = false
}
- public startConnector (connectorId: number, stopAbsoluteDuration?: boolean): void {
- if (!checkChargingStation(this.chargingStation, this.logPrefix(connectorId))) {
- return
- }
- if (!this.connectorsStatus.has(connectorId)) {
- logger.error(`${this.logPrefix(connectorId)} starting on non existing connector`)
- throw new BaseError(`Connector ${connectorId} does not exist`)
- }
- if (this.connectorsStatus.get(connectorId)?.start === false) {
- this.internalStartConnector(connectorId, stopAbsoluteDuration).catch(Constants.EMPTY_FUNCTION)
- } else if (this.connectorsStatus.get(connectorId)?.start === true) {
- logger.warn(`${this.logPrefix(connectorId)} is already started on connector`)
- }
- }
-
public stopConnector (connectorId: number): void {
if (!this.connectorsStatus.has(connectorId)) {
logger.error(`${this.logPrefix(connectorId)} stopping on non existing connector`)
- throw new BaseError(`Connector ${connectorId} does not exist`)
+ throw new BaseError(`Connector ${connectorId.toString()} does not exist`)
}
if (this.connectorsStatus.get(connectorId)?.start === true) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
}
}
- private startConnectors (stopAbsoluteDuration?: boolean): void {
- if (
- this.connectorsStatus.size > 0 &&
- this.connectorsStatus.size !== this.chargingStation.getNumberOfConnectors()
- ) {
- this.connectorsStatus.clear()
- this.initializeConnectorsStatus()
+ private canStartConnector (connectorId: number): boolean {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ if (new Date() > this.connectorsStatus.get(connectorId)!.stopDate!) {
+ logger.info(
+ `${this.logPrefix(
+ connectorId
+ )} entered in transaction loop while the ATG stop date has been reached`
+ )
+ return false
}
- if (this.chargingStation.hasEvses) {
- for (const [evseId, evseStatus] of this.chargingStation.evses) {
- if (evseId > 0) {
- for (const connectorId of evseStatus.connectors.keys()) {
- this.startConnector(connectorId, stopAbsoluteDuration)
- }
- }
- }
+ if (!this.chargingStation.inAcceptedState()) {
+ logger.error(
+ `${this.logPrefix(
+ connectorId
+ )} entered in transaction loop while the charging station is not in accepted state`
+ )
+ return false
+ }
+ if (!this.chargingStation.isChargingStationAvailable()) {
+ logger.info(
+ `${this.logPrefix(
+ connectorId
+ )} entered in transaction loop while the charging station is unavailable`
+ )
+ return false
+ }
+ if (!this.chargingStation.isConnectorAvailable(connectorId)) {
+ logger.info(
+ `${this.logPrefix(
+ connectorId
+ )} entered in transaction loop while the connector ${connectorId.toString()} is unavailable`
+ )
+ return false
+ }
+ const connectorStatus = this.chargingStation.getConnectorStatus(connectorId)
+ if (connectorStatus?.transactionStarted === true) {
+ logger.info(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `${this.logPrefix(connectorId)} entered in transaction loop while a transaction ${connectorStatus.transactionId?.toString()} is already started on connector ${connectorId.toString()}`
+ )
+ return false
+ }
+ return true
+ }
+
+ private getConnectorStatus (connectorId: number): Status {
+ const statusIndex = connectorId - 1
+ if (statusIndex < 0) {
+ logger.error(`${this.logPrefix(connectorId)} invalid connector id`)
+ throw new BaseError(`Invalid connector id ${connectorId.toString()}`)
+ }
+ let connectorStatus: Status | undefined
+ if (this.chargingStation.getAutomaticTransactionGeneratorStatuses()?.[statusIndex] != null) {
+ connectorStatus = clone<Status>(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.chargingStation.getAutomaticTransactionGeneratorStatuses()![statusIndex]
+ )
} else {
- for (const connectorId of this.chargingStation.connectors.keys()) {
- if (connectorId > 0) {
- this.startConnector(connectorId, stopAbsoluteDuration)
- }
+ logger.warn(
+ `${this.logPrefix(
+ connectorId
+ )} no status found for connector #${connectorId.toString()} in charging station configuration file. New status will be created`
+ )
+ }
+ if (connectorStatus != null) {
+ connectorStatus.startDate = convertToDate(connectorStatus.startDate)
+ connectorStatus.lastRunDate = convertToDate(connectorStatus.lastRunDate)
+ connectorStatus.stopDate = convertToDate(connectorStatus.stopDate)
+ connectorStatus.stoppedDate = convertToDate(connectorStatus.stoppedDate)
+ if (
+ !this.started &&
+ (connectorStatus.start ||
+ this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.enable !== true)
+ ) {
+ connectorStatus.start = false
}
}
+ return (
+ connectorStatus ?? {
+ acceptedAuthorizeRequests: 0,
+ acceptedStartTransactionRequests: 0,
+ acceptedStopTransactionRequests: 0,
+ authorizeRequests: 0,
+ rejectedAuthorizeRequests: 0,
+ rejectedStartTransactionRequests: 0,
+ rejectedStopTransactionRequests: 0,
+ skippedConsecutiveTransactions: 0,
+ skippedTransactions: 0,
+ start: false,
+ startTransactionRequests: 0,
+ stopTransactionRequests: 0,
+ }
+ )
}
- private stopConnectors (): void {
+ private getRequireAuthorize (): boolean {
+ return (
+ this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.requireAuthorize ?? true
+ )
+ }
+
+ private handleStartTransactionResponse (
+ connectorId: number,
+ startResponse: StartTransactionResponse
+ ): void {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.connectorsStatus.get(connectorId)!.startTransactionRequests
+ if (startResponse.idTagInfo.status === AuthorizationStatus.ACCEPTED) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.connectorsStatus.get(connectorId)!.acceptedStartTransactionRequests
+ } else {
+ logger.warn(`${this.logPrefix(connectorId)} start transaction rejected`)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.connectorsStatus.get(connectorId)!.rejectedStartTransactionRequests
+ }
+ }
+
+ private initializeConnectorsStatus (): void {
if (this.chargingStation.hasEvses) {
for (const [evseId, evseStatus] of this.chargingStation.evses) {
if (evseId > 0) {
for (const connectorId of evseStatus.connectors.keys()) {
- this.stopConnector(connectorId)
+ this.connectorsStatus.set(connectorId, this.getConnectorStatus(connectorId))
}
}
}
} else {
for (const connectorId of this.chargingStation.connectors.keys()) {
if (connectorId > 0) {
- this.stopConnector(connectorId)
+ this.connectorsStatus.set(connectorId, this.getConnectorStatus(connectorId))
}
}
}
}
const wait = secondsToMilliseconds(
randomInt(
- this.chargingStation.getAutomaticTransactionGeneratorConfiguration()
- ?.minDelayBetweenTwoTransactions,
- this.chargingStation.getAutomaticTransactionGeneratorConfiguration()
- ?.maxDelayBetweenTwoTransactions
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.chargingStation.getAutomaticTransactionGeneratorConfiguration()!
+ .minDelayBetweenTwoTransactions,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.chargingStation.getAutomaticTransactionGeneratorConfiguration()!
+ .maxDelayBetweenTwoTransactions
)
)
logger.info(`${this.logPrefix(connectorId)} waiting for ${formatDurationMilliSeconds(wait)}`)
// Wait until end of transaction
const waitTrxEnd = secondsToMilliseconds(
randomInt(
- this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.minDuration,
- this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.maxDuration
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.chargingStation.getAutomaticTransactionGeneratorConfiguration()!.minDuration,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.chargingStation.getAutomaticTransactionGeneratorConfiguration()!.maxDuration
)
)
logger.info(
- `${this.logPrefix(connectorId)} transaction started with id ${
- this.chargingStation.getConnectorStatus(connectorId)?.transactionId
- } and will stop in ${formatDurationMilliSeconds(waitTrxEnd)}`
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `${this.logPrefix(connectorId)} transaction started with id ${this.chargingStation
+ .getConnectorStatus(connectorId)
+ ?.transactionId?.toString()} and will stop in ${formatDurationMilliSeconds(waitTrxEnd)}`
)
await sleep(waitTrxEnd)
await this.stopTransaction(connectorId)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
++this.connectorsStatus.get(connectorId)!.skippedTransactions
logger.info(
- `${this.logPrefix(connectorId)} skipped consecutively ${
- this.connectorsStatus.get(connectorId)?.skippedConsecutiveTransactions
- }/${this.connectorsStatus.get(connectorId)?.skippedTransactions} transaction(s)`
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `${this.logPrefix(connectorId)} skipped consecutively ${this.connectorsStatus
+ .get(connectorId)
+ ?.skippedConsecutiveTransactions.toString()
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ }/${this.connectorsStatus.get(connectorId)?.skippedTransactions.toString()} transaction(s)`
)
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
)}`
)
logger.debug(
- `${this.logPrefix(connectorId)} connector status: %j`,
+ `${this.logPrefix(connectorId)} stopped with connector status: %j`,
this.connectorsStatus.get(connectorId)
)
+ this.chargingStation.emit(ChargingStationEvents.updated)
+ }
+
+ private readonly logPrefix = (connectorId?: number): string => {
+ return logPrefix(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ ` ${this.chargingStation.stationInfo?.chargingStationId} | ATG${
+ connectorId != null ? ` on connector #${connectorId.toString()}` : ''
+ }:`
+ )
}
private setStartConnectorStatus (
this.connectorsStatus.get(connectorId)!.skippedConsecutiveTransactions = 0
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.connectorsStatus.get(connectorId)!.start = true
+ this.chargingStation.emit(ChargingStationEvents.updated)
}
- private canStartConnector (connectorId: number): boolean {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- if (new Date() > this.connectorsStatus.get(connectorId)!.stopDate!) {
- logger.info(
- `${this.logPrefix(
- connectorId
- )} entered in transaction loop while the ATG stop date has been reached`
- )
- return false
- }
- if (!this.chargingStation.inAcceptedState()) {
- logger.error(
- `${this.logPrefix(
- connectorId
- )} entered in transaction loop while the charging station is not in accepted state`
- )
- return false
- }
- if (!this.chargingStation.isChargingStationAvailable()) {
- logger.info(
- `${this.logPrefix(
- connectorId
- )} entered in transaction loop while the charging station is unavailable`
- )
- return false
- }
- if (!this.chargingStation.isConnectorAvailable(connectorId)) {
- logger.info(
- `${this.logPrefix(
- connectorId
- )} entered in transaction loop while the connector ${connectorId} is unavailable`
- )
- return false
- }
- const connectorStatus = this.chargingStation.getConnectorStatus(connectorId)
- if (connectorStatus?.transactionStarted === true) {
- logger.info(
- `${this.logPrefix(
- connectorId
- )} entered in transaction loop while a transaction ${connectorStatus.transactionId} is already started on connector ${connectorId}`
- )
- return false
- }
- return true
- }
-
- private async waitChargingStationAvailable (connectorId: number): Promise<void> {
- let logged = false
- while (!this.chargingStation.isChargingStationAvailable()) {
- if (!logged) {
- logger.info(
- `${this.logPrefix(
- connectorId
- )} transaction loop waiting for charging station to be available`
- )
- logged = true
- }
- await sleep(Constants.DEFAULT_ATG_WAIT_TIME)
- }
- }
-
- private async waitConnectorAvailable (connectorId: number): Promise<void> {
- let logged = false
- while (!this.chargingStation.isConnectorAvailable(connectorId)) {
- if (!logged) {
- logger.info(
- `${this.logPrefix(
- connectorId
- )} transaction loop waiting for connector ${connectorId} to be available`
- )
- logged = true
- }
- await sleep(Constants.DEFAULT_ATG_WAIT_TIME)
- }
- }
-
- private async waitRunningTransactionStopped (connectorId: number): Promise<void> {
- const connectorStatus = this.chargingStation.getConnectorStatus(connectorId)
- let logged = false
- while (connectorStatus?.transactionStarted === true) {
- if (!logged) {
- logger.info(
- `${this.logPrefix(
- connectorId
- )} transaction loop waiting for started transaction ${connectorStatus.transactionId} on connector ${connectorId} to be stopped`
- )
- logged = true
- }
- await sleep(Constants.DEFAULT_ATG_WAIT_TIME)
+ private startConnectors (stopAbsoluteDuration?: boolean): void {
+ if (
+ this.connectorsStatus.size > 0 &&
+ this.connectorsStatus.size !== this.chargingStation.getNumberOfConnectors()
+ ) {
+ this.connectorsStatus.clear()
+ this.initializeConnectorsStatus()
}
- }
-
- private initializeConnectorsStatus (): void {
if (this.chargingStation.hasEvses) {
for (const [evseId, evseStatus] of this.chargingStation.evses) {
if (evseId > 0) {
for (const connectorId of evseStatus.connectors.keys()) {
- this.connectorsStatus.set(connectorId, this.getConnectorStatus(connectorId))
+ this.startConnector(connectorId, stopAbsoluteDuration)
}
}
}
} else {
for (const connectorId of this.chargingStation.connectors.keys()) {
if (connectorId > 0) {
- this.connectorsStatus.set(connectorId, this.getConnectorStatus(connectorId))
+ this.startConnector(connectorId, stopAbsoluteDuration)
}
}
}
}
- private getConnectorStatus (connectorId: number): Status {
- const statusIndex = connectorId - 1
- let connectorStatus: Status | undefined
- if (this.chargingStation.getAutomaticTransactionGeneratorStatuses()?.[statusIndex] != null) {
- connectorStatus = clone<Status>(
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.chargingStation.getAutomaticTransactionGeneratorStatuses()![statusIndex]
- )
- } else if (this.chargingStation.getAutomaticTransactionGeneratorStatuses() != null) {
- logger.warn(
- `${this.logPrefix(connectorId)} no status found for connector #${connectorId} in charging station configuration file. New status will be created`
- )
- }
- if (connectorStatus != null) {
- connectorStatus.startDate = convertToDate(connectorStatus.startDate)
- connectorStatus.lastRunDate = convertToDate(connectorStatus.lastRunDate)
- connectorStatus.stopDate = convertToDate(connectorStatus.stopDate)
- connectorStatus.stoppedDate = convertToDate(connectorStatus.stoppedDate)
- if (
- !this.started &&
- (connectorStatus.start ||
- this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.enable !== true)
- ) {
- connectorStatus.start = false
- }
- }
- return (
- connectorStatus ?? {
- start: false,
- authorizeRequests: 0,
- acceptedAuthorizeRequests: 0,
- rejectedAuthorizeRequests: 0,
- startTransactionRequests: 0,
- acceptedStartTransactionRequests: 0,
- rejectedStartTransactionRequests: 0,
- stopTransactionRequests: 0,
- acceptedStopTransactionRequests: 0,
- rejectedStopTransactionRequests: 0,
- skippedConsecutiveTransactions: 0,
- skippedTransactions: 0
- }
- )
- }
-
private async startTransaction (
connectorId: number
): Promise<StartTransactionResponse | undefined> {
logger.info(startTransactionLogMsg)
// Start transaction
startResponse = await this.chargingStation.ocppRequestService.requestHandler<
- Partial<StartTransactionRequest>,
- StartTransactionResponse
+ Partial<StartTransactionRequest>,
+ StartTransactionResponse
>(this.chargingStation, RequestCommand.START_TRANSACTION, {
connectorId,
- idTag
+ idTag,
})
this.handleStartTransactionResponse(connectorId, startResponse)
PerformanceStatistics.endMeasure(measureId, beginId)
logger.info(startTransactionLogMsg)
// Start transaction
startResponse = await this.chargingStation.ocppRequestService.requestHandler<
- Partial<StartTransactionRequest>,
- StartTransactionResponse
+ Partial<StartTransactionRequest>,
+ StartTransactionResponse
>(this.chargingStation, RequestCommand.START_TRANSACTION, {
connectorId,
- idTag
+ idTag,
})
this.handleStartTransactionResponse(connectorId, startResponse)
PerformanceStatistics.endMeasure(measureId, beginId)
}
logger.info(`${this.logPrefix(connectorId)} start transaction without an idTag`)
startResponse = await this.chargingStation.ocppRequestService.requestHandler<
- Partial<StartTransactionRequest>,
- StartTransactionResponse
- >(this.chargingStation, RequestCommand.START_TRANSACTION, { connectorId })
+ Partial<StartTransactionRequest>,
+ StartTransactionResponse
+ >(this.chargingStation, RequestCommand.START_TRANSACTION, {
+ connectorId,
+ })
this.handleStartTransactionResponse(connectorId, startResponse)
PerformanceStatistics.endMeasure(measureId, beginId)
return startResponse
}
+ private stopConnectors (): void {
+ if (this.chargingStation.hasEvses) {
+ for (const [evseId, evseStatus] of this.chargingStation.evses) {
+ if (evseId > 0) {
+ for (const connectorId of evseStatus.connectors.keys()) {
+ this.stopConnector(connectorId)
+ }
+ }
+ }
+ } else {
+ for (const connectorId of this.chargingStation.connectors.keys()) {
+ if (connectorId > 0) {
+ this.stopConnector(connectorId)
+ }
+ }
+ }
+ }
+
private async stopTransaction (
connectorId: number,
reason = StopTransactionReason.LOCAL
let stopResponse: StopTransactionResponse | undefined
if (this.chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
logger.info(
- `${this.logPrefix(connectorId)} stop transaction with id ${
- this.chargingStation.getConnectorStatus(connectorId)?.transactionId
- }`
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `${this.logPrefix(connectorId)} stop transaction with id ${this.chargingStation
+ .getConnectorStatus(connectorId)
+ ?.transactionId?.toString()}`
)
stopResponse = await this.chargingStation.stopTransactionOnConnector(connectorId, reason)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const transactionId = this.chargingStation.getConnectorStatus(connectorId)?.transactionId
logger.debug(
`${this.logPrefix(connectorId)} stopping a not started transaction${
- transactionId != null ? ` with id ${transactionId}` : ''
+ transactionId != null ? ` with id ${transactionId.toString()}` : ''
}`
)
}
return stopResponse
}
- private getRequireAuthorize (): boolean {
- return (
- this.chargingStation.getAutomaticTransactionGeneratorConfiguration()?.requireAuthorize ?? true
- )
+ private async waitChargingStationAvailable (connectorId: number): Promise<void> {
+ let logged = false
+ while (!this.chargingStation.isChargingStationAvailable()) {
+ if (!logged) {
+ logger.info(
+ `${this.logPrefix(
+ connectorId
+ )} transaction loop waiting for charging station to be available`
+ )
+ logged = true
+ }
+ await sleep(Constants.DEFAULT_ATG_WAIT_TIME)
+ }
}
- private readonly logPrefix = (connectorId?: number): string => {
- return logPrefix(
- ` ${this.chargingStation.stationInfo?.chargingStationId} | ATG${
- connectorId != null ? ` on connector #${connectorId}` : ''
- }:`
- )
+ private async waitConnectorAvailable (connectorId: number): Promise<void> {
+ let logged = false
+ while (!this.chargingStation.isConnectorAvailable(connectorId)) {
+ if (!logged) {
+ logger.info(
+ `${this.logPrefix(
+ connectorId
+ )} transaction loop waiting for connector ${connectorId.toString()} to be available`
+ )
+ logged = true
+ }
+ await sleep(Constants.DEFAULT_ATG_WAIT_TIME)
+ }
}
- private handleStartTransactionResponse (
- connectorId: number,
- startResponse: StartTransactionResponse
- ): void {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- ++this.connectorsStatus.get(connectorId)!.startTransactionRequests
- if (startResponse.idTagInfo.status === AuthorizationStatus.ACCEPTED) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- ++this.connectorsStatus.get(connectorId)!.acceptedStartTransactionRequests
- } else {
- logger.warn(`${this.logPrefix(connectorId)} start transaction rejected`)
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- ++this.connectorsStatus.get(connectorId)!.rejectedStartTransactionRequests
+ private async waitRunningTransactionStopped (connectorId: number): Promise<void> {
+ const connectorStatus = this.chargingStation.getConnectorStatus(connectorId)
+ let logged = false
+ while (connectorStatus?.transactionStarted === true) {
+ if (!logged) {
+ logger.info(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `${this.logPrefix(connectorId)} transaction loop waiting for started transaction ${connectorStatus.transactionId?.toString()} on connector ${connectorId.toString()} to be stopped`
+ )
+ logged = true
+ }
+ await sleep(Constants.DEFAULT_ATG_WAIT_TIME)
}
}
}
// Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
+import type { Worker } from 'node:worker_threads'
+
+import chalk from 'chalk'
import { EventEmitter } from 'node:events'
import { dirname, extname, join } from 'node:path'
import process, { exit } from 'node:process'
import { fileURLToPath } from 'node:url'
import { isMainThread } from 'node:worker_threads'
-
-import chalk from 'chalk'
import { availableParallelism, type MessageHandler } from 'poolifier'
-import type { Worker } from 'worker_threads'
+
+import type { AbstractUIServer } from './ui-server/AbstractUIServer.js'
import { version } from '../../package.json'
import { BaseError } from '../exception/index.js'
type StorageConfiguration,
type TemplateStatistics,
type UIServerConfiguration,
- type WorkerConfiguration
+ type WorkerConfiguration,
} from '../types/index.js'
import {
Configuration,
isAsyncFunction,
isNotEmptyArray,
logger,
- logPrefix
+ logPrefix,
} from '../utils/index.js'
import { DEFAULT_ELEMENTS_PER_WORKER, type WorkerAbstract, WorkerFactory } from '../worker/index.js'
import { buildTemplateName, waitChargingStationEvents } from './Helpers.js'
-import type { AbstractUIServer } from './ui-server/AbstractUIServer.js'
import { UIServerFactory } from './ui-server/UIServerFactory.js'
const moduleName = 'Bootstrap'
+/* eslint-disable perfectionist/sort-enums */
enum exitCodes {
succeeded = 0,
missingChargingStationsConfiguration = 1,
duplicateChargingStationTemplateUrls = 2,
noChargingStationTemplates = 3,
- gracefulShutdownError = 4
+ gracefulShutdownError = 4,
}
+/* eslint-enable perfectionist/sort-enums */
export class Bootstrap extends EventEmitter {
private static instance: Bootstrap | null = null
- private workerImplementation?: WorkerAbstract<ChargingStationWorkerData, ChargingStationInfo>
- private readonly uiServer: AbstractUIServer
- private storage?: Storage
- private readonly templateStatistics: Map<string, TemplateStatistics>
- private readonly version: string = version
+ public get numberOfChargingStationTemplates (): number {
+ return this.templateStatistics.size
+ }
+
+ public get numberOfConfiguredChargingStations (): number {
+ return [...this.templateStatistics.values()].reduce(
+ (accumulator, value) => accumulator + value.configured,
+ 0
+ )
+ }
+
+ public get numberOfProvisionedChargingStations (): number {
+ return [...this.templateStatistics.values()].reduce(
+ (accumulator, value) => accumulator + value.provisioned,
+ 0
+ )
+ }
+
private started: boolean
private starting: boolean
private stopping: boolean
+ private storage?: Storage
+ private readonly templateStatistics: Map<string, TemplateStatistics>
+ private readonly uiServer: AbstractUIServer
private uiServerStarted: boolean
+ private readonly version: string = version
+ private workerImplementation?: WorkerAbstract<ChargingStationWorkerData, ChargingStationInfo>
+
+ private get numberOfAddedChargingStations (): number {
+ return [...this.templateStatistics.values()].reduce(
+ (accumulator, value) => accumulator + value.added,
+ 0
+ )
+ }
+
+ private get numberOfStartedChargingStations (): number {
+ return [...this.templateStatistics.values()].reduce(
+ (accumulator, value) => accumulator + value.started,
+ 0
+ )
+ }
private constructor () {
super()
}
public static getInstance (): Bootstrap {
- if (Bootstrap.instance === null) {
- Bootstrap.instance = new Bootstrap()
- }
+ Bootstrap.instance ??= new Bootstrap()
return Bootstrap.instance
}
- public get numberOfChargingStationTemplates (): number {
- return this.templateStatistics.size
- }
-
- public get numberOfConfiguredChargingStations (): number {
- return [...this.templateStatistics.values()].reduce(
- (accumulator, value) => accumulator + value.configured,
- 0
- )
- }
-
- public get numberOfProvisionedChargingStations (): number {
- return [...this.templateStatistics.values()].reduce(
- (accumulator, value) => accumulator + value.provisioned,
- 0
- )
- }
-
- public getState (): SimulatorState {
- return {
- version: this.version,
- configuration: Configuration.getConfigurationData(),
- started: this.started,
- templateStatistics: this.templateStatistics
+ public async addChargingStation (
+ index: number,
+ templateFile: string,
+ options?: ChargingStationOptions
+ ): Promise<ChargingStationInfo | undefined> {
+ if (!this.started && !this.starting) {
+ throw new BaseError(
+ 'Cannot add charging station while the charging stations simulator is not started'
+ )
}
+ const stationInfo = await this.workerImplementation?.addElement({
+ index,
+ options,
+ templateFile: join(
+ dirname(fileURLToPath(import.meta.url)),
+ 'assets',
+ 'station-templates',
+ templateFile
+ ),
+ })
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const templateStatistics = this.templateStatistics.get(buildTemplateName(templateFile))!
+ ++templateStatistics.added
+ templateStatistics.indexes.add(index)
+ return stationInfo
}
public getLastIndex (templateName: string): number {
return this.storage?.getPerformanceStatistics()
}
- private get numberOfAddedChargingStations (): number {
- return [...this.templateStatistics.values()].reduce(
- (accumulator, value) => accumulator + value.added,
- 0
- )
- }
-
- private get numberOfStartedChargingStations (): number {
- return [...this.templateStatistics.values()].reduce(
- (accumulator, value) => accumulator + value.started,
- 0
- )
+ public getState (): SimulatorState {
+ return {
+ configuration: Configuration.getConfigurationData(),
+ started: this.started,
+ templateStatistics: this.templateStatistics,
+ version: this.version,
+ }
}
public async start (): Promise<void> {
if (isAsyncFunction(this.workerImplementation?.start)) {
await this.workerImplementation.start()
} else {
- (this.workerImplementation?.start as () => void)()
+ ;(this.workerImplementation?.start as () => void)()
}
const performanceStorageConfiguration =
Configuration.getConfigurationSection<StorageConfiguration>(
)
console.info(
chalk.green(
- `Charging stations simulator ${
- this.version
- } started with ${this.numberOfConfiguredChargingStations} configured and ${this.numberOfProvisionedChargingStations} provisioned charging station(s) from ${this.numberOfChargingStationTemplates} charging station template(s) and ${
- Configuration.workerDynamicPoolInUse() ? `${workerConfiguration.poolMinSize}/` : ''
- }${this.workerImplementation?.size}${
- Configuration.workerPoolInUse() ? `/${workerConfiguration.poolMaxSize}` : ''
+ `Charging stations simulator ${this.version} started with ${this.numberOfConfiguredChargingStations.toString()} configured and ${this.numberOfProvisionedChargingStations.toString()} provisioned charging station(s) from ${this.numberOfChargingStationTemplates.toString()} charging station template(s) and ${
+ Configuration.workerDynamicPoolInUse()
+ ? // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `${workerConfiguration.poolMinSize?.toString()}/`
+ : ''
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ }${this.workerImplementation?.size.toString()}${
+ Configuration.workerPoolInUse()
+ ? // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `/${workerConfiguration.poolMaxSize?.toString()}`
+ : ''
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
} worker(s) concurrently running in '${workerConfiguration.processType}' mode${
this.workerImplementation?.maxElementsPerWorker != null
- ? ` (${this.workerImplementation.maxElementsPerWorker} charging station(s) per worker)`
+ ? ` (${this.workerImplementation.maxElementsPerWorker.toString()} charging station(s) per worker)`
: ''
}`
)
}
}
- private async restart (): Promise<void> {
- await this.stop()
+ private gracefulShutdown (): void {
+ this.stop()
+ .then(() => {
+ console.info(chalk.green('Graceful shutdown'))
+ this.uiServer.stop()
+ this.uiServerStarted = false
+ this.waitChargingStationsStopped()
+ // eslint-disable-next-line promise/no-nesting
+ .then(() => {
+ return exit(exitCodes.succeeded)
+ })
+ // eslint-disable-next-line promise/no-nesting
+ .catch(() => {
+ exit(exitCodes.gracefulShutdownError)
+ })
+ return undefined
+ })
+ .catch((error: unknown) => {
+ console.error(chalk.red('Error while shutdowning charging stations simulator: '), error)
+ exit(exitCodes.gracefulShutdownError)
+ })
+ }
+
+ private initializeCounters (): void {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const stationTemplateUrls = Configuration.getStationTemplateUrls()!
+ if (isNotEmptyArray(stationTemplateUrls)) {
+ for (const stationTemplateUrl of stationTemplateUrls) {
+ const templateName = buildTemplateName(stationTemplateUrl.file)
+ this.templateStatistics.set(templateName, {
+ added: 0,
+ configured: stationTemplateUrl.numberOfStations,
+ indexes: new Set<number>(),
+ provisioned: stationTemplateUrl.provisionedNumberOfStations ?? 0,
+ started: 0,
+ })
+ this.uiServer.chargingStationTemplates.add(templateName)
+ }
+ if (this.templateStatistics.size !== stationTemplateUrls.length) {
+ console.error(
+ chalk.red(
+ "'stationTemplateUrls' contains duplicate entries, please check your configuration"
+ )
+ )
+ exit(exitCodes.duplicateChargingStationTemplateUrls)
+ }
+ } else {
+ console.error(
+ chalk.red("'stationTemplateUrls' not defined or empty, please check your configuration")
+ )
+ exit(exitCodes.missingChargingStationsConfiguration)
+ }
if (
- this.uiServerStarted &&
+ this.numberOfConfiguredChargingStations === 0 &&
Configuration.getConfigurationSection<UIServerConfiguration>(ConfigurationSection.uiServer)
.enabled !== true
) {
- this.uiServer.stop()
- this.uiServerStarted = false
- }
- this.initializeCounters()
- // FIXME: initialize worker implementation only if the worker section has changed
- this.initializeWorkerImplementation(
- Configuration.getConfigurationSection<WorkerConfiguration>(ConfigurationSection.worker)
- )
- await this.start()
- }
-
- private async waitChargingStationsStopped (): Promise<string> {
- return await new Promise<string>((resolve, reject: (reason?: unknown) => void) => {
- const waitTimeout = setTimeout(() => {
- const timeoutMessage = `Timeout ${formatDurationMilliSeconds(
- Constants.STOP_CHARGING_STATIONS_TIMEOUT
- )} reached at stopping charging stations`
- console.warn(chalk.yellow(timeoutMessage))
- reject(new Error(timeoutMessage))
- }, Constants.STOP_CHARGING_STATIONS_TIMEOUT)
- waitChargingStationEvents(
- this,
- ChargingStationWorkerMessageEvents.stopped,
- this.numberOfStartedChargingStations
+ console.error(
+ chalk.red(
+ "'stationTemplateUrls' has no charging station enabled and UI server is disabled, please check your configuration"
+ )
)
- .then(() => {
- resolve('Charging stations stopped')
- })
- .catch(reject)
- .finally(() => {
- clearTimeout(waitTimeout)
- })
- })
+ exit(exitCodes.noChargingStationTemplates)
+ }
}
private initializeWorkerImplementation (workerConfiguration: WorkerConfiguration): void {
elementsPerWorker = workerConfiguration.elementsPerWorker ?? DEFAULT_ELEMENTS_PER_WORKER
}
this.workerImplementation = WorkerFactory.getWorkerImplementation<
- ChargingStationWorkerData,
- ChargingStationInfo
+ ChargingStationWorkerData,
+ ChargingStationInfo
>(
join(
dirname(fileURLToPath(import.meta.url)),
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
workerConfiguration.processType!,
{
- workerStartDelay: workerConfiguration.startDelay,
elementAddDelay: workerConfiguration.elementAddDelay,
+ elementsPerWorker,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
poolMaxSize: workerConfiguration.poolMaxSize!,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
poolMinSize: workerConfiguration.poolMinSize!,
- elementsPerWorker,
poolOptions: {
messageHandler: this.messageHandler.bind(this) as MessageHandler<Worker>,
...(workerConfiguration.resourceLimits != null && {
- workerOptions: { resourceLimits: workerConfiguration.resourceLimits }
- })
- }
+ workerOptions: {
+ resourceLimits: workerConfiguration.resourceLimits,
+ },
+ }),
+ },
+ workerStartDelay: workerConfiguration.startDelay,
}
)
}
+ private readonly logPrefix = (): string => {
+ return logPrefix(' Bootstrap |')
+ }
+
private messageHandler (
msg: ChargingStationWorkerMessage<ChargingStationWorkerMessageData>
): void {
if (msg['uuid'] != null) {
return
}
- const { event, data } = msg
+ const { data, event } = msg
try {
switch (event) {
case ChargingStationWorkerMessageEvents.added:
case ChargingStationWorkerMessageEvents.deleted:
this.emit(ChargingStationWorkerMessageEvents.deleted, data)
break
+ case ChargingStationWorkerMessageEvents.performanceStatistics:
+ this.emit(ChargingStationWorkerMessageEvents.performanceStatistics, data)
+ break
case ChargingStationWorkerMessageEvents.started:
this.emit(ChargingStationWorkerMessageEvents.started, data)
break
case ChargingStationWorkerMessageEvents.updated:
this.emit(ChargingStationWorkerMessageEvents.updated, data)
break
- case ChargingStationWorkerMessageEvents.performanceStatistics:
- this.emit(ChargingStationWorkerMessageEvents.performanceStatistics, data)
- break
default:
throw new BaseError(
- `Unknown charging station worker message event: '${event}' received with data: ${JSON.stringify(data, undefined, 2)}`
+ `Unknown charging station worker message event: '${event}' received with data: ${JSON.stringify(
+ data,
+ undefined,
+ 2
+ )}`
)
}
} catch (error) {
}
}
+ private async restart (): Promise<void> {
+ await this.stop()
+ if (
+ this.uiServerStarted &&
+ Configuration.getConfigurationSection<UIServerConfiguration>(ConfigurationSection.uiServer)
+ .enabled !== true
+ ) {
+ this.uiServer.stop()
+ this.uiServerStarted = false
+ }
+ this.initializeCounters()
+ // FIXME: initialize worker implementation only if the worker section has changed
+ this.initializeWorkerImplementation(
+ Configuration.getConfigurationSection<WorkerConfiguration>(ConfigurationSection.worker)
+ )
+ await this.start()
+ }
+
+ private async waitChargingStationsStopped (): Promise<string> {
+ return await new Promise<string>((resolve, reject: (reason?: unknown) => void) => {
+ const waitTimeout = setTimeout(() => {
+ const timeoutMessage = `Timeout ${formatDurationMilliSeconds(
+ Constants.STOP_CHARGING_STATIONS_TIMEOUT
+ )} reached at stopping charging stations`
+ console.warn(chalk.yellow(timeoutMessage))
+ reject(new Error(timeoutMessage))
+ }, Constants.STOP_CHARGING_STATIONS_TIMEOUT)
+ waitChargingStationEvents(
+ this,
+ ChargingStationWorkerMessageEvents.stopped,
+ this.numberOfStartedChargingStations
+ )
+ .then(events => {
+ resolve('Charging stations stopped')
+ return events
+ })
+ .finally(() => {
+ clearTimeout(waitTimeout)
+ })
+ .catch(reject)
+ })
+ }
+
private readonly workerEventAdded = (data: ChargingStationData): void => {
this.uiServer.chargingStations.set(data.stationInfo.hashId, data)
logger.info(
`${this.logPrefix()} ${moduleName}.workerEventAdded: Charging station ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
data.stationInfo.chargingStationId
- } (hashId: ${data.stationInfo.hashId}) added (${
- this.numberOfAddedChargingStations
- } added from ${this.numberOfConfiguredChargingStations} configured and ${this.numberOfProvisionedChargingStations} provisioned charging station(s))`
+ } (hashId: ${data.stationInfo.hashId}) added (${this.numberOfAddedChargingStations.toString()} added from ${this.numberOfConfiguredChargingStations.toString()} configured and ${this.numberOfProvisionedChargingStations.toString()} provisioned charging station(s))`
)
}
templateStatistics.indexes.delete(data.stationInfo.templateIndex)
logger.info(
`${this.logPrefix()} ${moduleName}.workerEventDeleted: Charging station ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
data.stationInfo.chargingStationId
- } (hashId: ${data.stationInfo.hashId}) deleted (${
- this.numberOfAddedChargingStations
- } added from ${this.numberOfConfiguredChargingStations} configured and ${this.numberOfProvisionedChargingStations} provisioned charging station(s))`
+ } (hashId: ${data.stationInfo.hashId}) deleted (${this.numberOfAddedChargingStations.toString()} added from ${this.numberOfConfiguredChargingStations.toString()} configured and ${this.numberOfProvisionedChargingStations.toString()} provisioned charging station(s))`
)
}
+ private readonly workerEventPerformanceStatistics = (data: Statistics): void => {
+ // eslint-disable-next-line @typescript-eslint/unbound-method
+ if (isAsyncFunction(this.storage?.storePerformanceStatistics)) {
+ ;(
+ this.storage.storePerformanceStatistics as (
+ performanceStatistics: Statistics
+ ) => Promise<void>
+ )(data).catch(Constants.EMPTY_FUNCTION)
+ } else {
+ ;(this.storage?.storePerformanceStatistics as (performanceStatistics: Statistics) => void)(
+ data
+ )
+ }
+ }
+
private readonly workerEventStarted = (data: ChargingStationData): void => {
this.uiServer.chargingStations.set(data.stationInfo.hashId, data)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
++this.templateStatistics.get(data.stationInfo.templateName)!.started
logger.info(
`${this.logPrefix()} ${moduleName}.workerEventStarted: Charging station ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
data.stationInfo.chargingStationId
- } (hashId: ${data.stationInfo.hashId}) started (${
- this.numberOfStartedChargingStations
- } started from ${this.numberOfAddedChargingStations} added charging station(s))`
+ } (hashId: ${data.stationInfo.hashId}) started (${this.numberOfStartedChargingStations.toString()} started from ${this.numberOfAddedChargingStations.toString()} added charging station(s))`
)
}
--this.templateStatistics.get(data.stationInfo.templateName)!.started
logger.info(
`${this.logPrefix()} ${moduleName}.workerEventStopped: Charging station ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
data.stationInfo.chargingStationId
- } (hashId: ${data.stationInfo.hashId}) stopped (${
- this.numberOfStartedChargingStations
- } started from ${this.numberOfAddedChargingStations} added charging station(s))`
+ } (hashId: ${data.stationInfo.hashId}) stopped (${this.numberOfStartedChargingStations.toString()} started from ${this.numberOfAddedChargingStations.toString()} added charging station(s))`
)
}
private readonly workerEventUpdated = (data: ChargingStationData): void => {
this.uiServer.chargingStations.set(data.stationInfo.hashId, data)
}
-
- private readonly workerEventPerformanceStatistics = (data: Statistics): void => {
- // eslint-disable-next-line @typescript-eslint/unbound-method
- if (isAsyncFunction(this.storage?.storePerformanceStatistics)) {
- (
- this.storage.storePerformanceStatistics as (
- performanceStatistics: Statistics
- ) => Promise<void>
- )(data).catch(Constants.EMPTY_FUNCTION)
- } else {
- (this.storage?.storePerformanceStatistics as (performanceStatistics: Statistics) => void)(
- data
- )
- }
- }
-
- private initializeCounters (): void {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const stationTemplateUrls = Configuration.getStationTemplateUrls()!
- if (isNotEmptyArray(stationTemplateUrls)) {
- for (const stationTemplateUrl of stationTemplateUrls) {
- const templateName = buildTemplateName(stationTemplateUrl.file)
- this.templateStatistics.set(templateName, {
- configured: stationTemplateUrl.numberOfStations,
- provisioned: stationTemplateUrl.provisionedNumberOfStations ?? 0,
- added: 0,
- started: 0,
- indexes: new Set<number>()
- })
- this.uiServer.chargingStationTemplates.add(templateName)
- }
- if (this.templateStatistics.size !== stationTemplateUrls.length) {
- console.error(
- chalk.red(
- "'stationTemplateUrls' contains duplicate entries, please check your configuration"
- )
- )
- exit(exitCodes.duplicateChargingStationTemplateUrls)
- }
- } else {
- console.error(
- chalk.red("'stationTemplateUrls' not defined or empty, please check your configuration")
- )
- exit(exitCodes.missingChargingStationsConfiguration)
- }
- if (
- this.numberOfConfiguredChargingStations === 0 &&
- Configuration.getConfigurationSection<UIServerConfiguration>(ConfigurationSection.uiServer)
- .enabled !== true
- ) {
- console.error(
- chalk.red(
- "'stationTemplateUrls' has no charging station enabled and UI server is disabled, please check your configuration"
- )
- )
- exit(exitCodes.noChargingStationTemplates)
- }
- }
-
- public async addChargingStation (
- index: number,
- templateFile: string,
- options?: ChargingStationOptions
- ): Promise<ChargingStationInfo | undefined> {
- if (!this.started && !this.starting) {
- throw new BaseError(
- 'Cannot add charging station while the charging stations simulator is not started'
- )
- }
- const stationInfo = await this.workerImplementation?.addElement({
- index,
- templateFile: join(
- dirname(fileURLToPath(import.meta.url)),
- 'assets',
- 'station-templates',
- templateFile
- ),
- options
- })
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const templateStatistics = this.templateStatistics.get(buildTemplateName(templateFile))!
- ++templateStatistics.added
- templateStatistics.indexes.add(index)
- return stationInfo
- }
-
- private gracefulShutdown (): void {
- this.stop()
- .then(() => {
- console.info(chalk.green('Graceful shutdown'))
- this.uiServer.stop()
- this.uiServerStarted = false
- this.waitChargingStationsStopped()
- .then(() => {
- exit(exitCodes.succeeded)
- })
- .catch(() => {
- exit(exitCodes.gracefulShutdownError)
- })
- })
- .catch((error: unknown) => {
- console.error(chalk.red('Error while shutdowning charging stations simulator: '), error)
- exit(exitCodes.gracefulShutdownError)
- })
- }
-
- private readonly logPrefix = (): string => {
- return logPrefix(' Bootstrap |')
- }
}
// Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
-import { createHash, randomInt } from 'node:crypto'
+import { millisecondsToSeconds, secondsToMilliseconds } from 'date-fns'
+import { hash, randomInt } from 'node:crypto'
import { EventEmitter } from 'node:events'
import { existsSync, type FSWatcher, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { URL } from 'node:url'
import { parentPort } from 'node:worker_threads'
-
-import { millisecondsToSeconds, secondsToMilliseconds } from 'date-fns'
-import { mergeDeepRight, once } from 'rambda'
import { type RawData, WebSocket } from 'ws'
import { BaseError, OCPPError } from '../exception/index.js'
type Voltage,
WebSocketCloseEventStatusCode,
type WSError,
- type WsOptions
+ type WsOptions,
} from '../types/index.js'
import {
ACElectricUtils,
formatDurationSeconds,
getWebSocketCloseEventStatusString,
handleFileException,
+ isEmpty,
isNotEmptyArray,
isNotEmptyString,
logger,
logPrefix,
+ mergeDeepRight,
min,
+ once,
roundTo,
secureRandom,
sleep,
- watchJsonFile
+ watchJsonFile,
} from '../utils/index.js'
import { AutomaticTransactionGenerator } from './AutomaticTransactionGenerator.js'
import { ChargingStationWorkerBroadcastChannel } from './broadcast-channel/ChargingStationWorkerBroadcastChannel.js'
addConfigurationKey,
deleteConfigurationKey,
getConfigurationKey,
- setConfigurationKeyValue
+ setConfigurationKeyValue,
} from './ConfigurationKeyUtils.js'
import {
buildConnectorsMap,
buildTemplateName,
- checkChargingStation,
+ checkChargingStationState,
checkConfiguration,
checkConnectorsConfiguration,
checkStationInfoConnectorStatus,
createSerialNumber,
getAmperageLimitationUnitDivider,
getBootConnectorStatus,
- getChargingStationConnectorChargingProfilesPowerLimit,
+ getChargingStationChargingProfilesLimit,
getChargingStationId,
+ getConnectorChargingProfilesLimit,
getDefaultVoltageOut,
getHashId,
getIdTagsFile,
hasFeatureProfile,
hasReservationExpired,
initializeConnectorsMapStatus,
+ prepareConnectorStatus,
propagateSerialNumber,
setChargingStationOptions,
stationTemplateToStationInfo,
- warnTemplateKeysDeprecation
+ validateStationInfo,
+ warnTemplateKeysDeprecation,
} from './Helpers.js'
import { IdTagsCache } from './IdTagsCache.js'
import {
OCPP20ResponseService,
type OCPPIncomingRequestService,
type OCPPRequestService,
- sendAndSetConnectorStatus
+ sendAndSetConnectorStatus,
} from './ocpp/index.js'
import { SharedLRUCache } from './SharedLRUCache.js'
export class ChargingStation extends EventEmitter {
- public readonly index: number
- public readonly templateFile: string
- public stationInfo?: ChargingStationInfo
- public started: boolean
- public starting: boolean
- public idTagsCache: IdTagsCache
public automaticTransactionGenerator?: AutomaticTransactionGenerator
- public ocppConfiguration?: ChargingStationOcppConfiguration
- public wsConnection: WebSocket | null
+ public bootNotificationRequest?: BootNotificationRequest
+ public bootNotificationResponse?: BootNotificationResponse
public readonly connectors: Map<number, ConnectorStatus>
public readonly evses: Map<number, EvseStatus>
- public readonly requests: Map<string, CachedRequest>
- public performanceStatistics?: PerformanceStatistics
public heartbeatSetInterval?: NodeJS.Timeout
+ public idTagsCache: IdTagsCache
+ public readonly index: number
+ public ocppConfiguration?: ChargingStationOcppConfiguration
public ocppRequestService!: OCPPRequestService
- public bootNotificationRequest?: BootNotificationRequest
- public bootNotificationResponse?: BootNotificationResponse
+ public performanceStatistics?: PerformanceStatistics
public powerDivider?: number
- private stopping: boolean
+ public readonly requests: Map<string, CachedRequest>
+ public started: boolean
+ public starting: boolean
+ public stationInfo?: ChargingStationInfo
+ public readonly templateFile: string
+ public wsConnection: null | WebSocket
+
+ public get hasEvses (): boolean {
+ return isEmpty(this.connectors) && this.evses.size > 0
+ }
+
+ public get wsConnectionUrl (): URL {
+ const wsConnectionBaseUrlStr = `${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ this.stationInfo?.supervisionUrlOcppConfiguration === true &&
+ isNotEmptyString(this.stationInfo.supervisionUrlOcppKey) &&
+ isNotEmptyString(getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey)?.value)
+ ? getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey)?.value
+ : this.configuredSupervisionUrl.href
+ }`
+ return new URL(
+ `${wsConnectionBaseUrlStr}${
+ !wsConnectionBaseUrlStr.endsWith('/') ? '/' : ''
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ }${this.stationInfo?.chargingStationId}`
+ )
+ }
+
+ private automaticTransactionGeneratorConfiguration?: AutomaticTransactionGeneratorConfiguration
+ private readonly chargingStationWorkerBroadcastChannel: ChargingStationWorkerBroadcastChannel
private configurationFile!: string
private configurationFileHash!: string
+ private configuredSupervisionUrl!: URL
private connectorsConfigurationHash!: string
private evsesConfigurationHash!: string
- private automaticTransactionGeneratorConfiguration?: AutomaticTransactionGeneratorConfiguration
+ private flushingMessageBuffer: boolean
+ private flushMessageBufferSetInterval?: NodeJS.Timeout
+ private readonly messageQueue: string[]
private ocppIncomingRequestService!: OCPPIncomingRequestService
- private readonly messageBuffer: Set<string>
- private configuredSupervisionUrl!: URL
- private wsConnectionRetried: boolean
- private wsConnectionRetryCount: number
- private templateFileWatcher?: FSWatcher
- private templateFileHash!: string
private readonly sharedLRUCache: SharedLRUCache
+ private stopping: boolean
+ private templateFileHash!: string
+ private templateFileWatcher?: FSWatcher
+ private wsConnectionRetryCount: number
private wsPingSetInterval?: NodeJS.Timeout
- private readonly chargingStationWorkerBroadcastChannel: ChargingStationWorkerBroadcastChannel
- private flushMessageBufferSetInterval?: NodeJS.Timeout
constructor (index: number, templateFile: string, options?: ChargingStationOptions) {
super()
this.starting = false
this.stopping = false
this.wsConnection = null
- this.wsConnectionRetried = false
this.wsConnectionRetryCount = 0
this.index = index
this.templateFile = templateFile
this.connectors = new Map<number, ConnectorStatus>()
this.evses = new Map<number, EvseStatus>()
this.requests = new Map<string, CachedRequest>()
- this.messageBuffer = new Set<string>()
+ this.flushingMessageBuffer = false
+ this.messageQueue = [] as string[]
this.sharedLRUCache = SharedLRUCache.getInstance()
this.idTagsCache = IdTagsCache.getInstance()
this.chargingStationWorkerBroadcastChannel = new ChargingStationWorkerBroadcastChannel(this)
})
this.on(ChargingStationEvents.accepted, () => {
this.startMessageSequence(
- this.wsConnectionRetried
+ this.wsConnectionRetryCount > 0
? true
: this.getAutomaticTransactionGeneratorConfiguration()?.stopAbsoluteDuration
).catch((error: unknown) => {
logger.error(`${this.logPrefix()} Error while starting the message sequence:`, error)
})
- this.wsConnectionRetried = false
+ this.wsConnectionRetryCount = 0
})
this.on(ChargingStationEvents.rejected, () => {
- this.wsConnectionRetried = false
+ this.wsConnectionRetryCount = 0
+ })
+ this.on(ChargingStationEvents.connected, () => {
+ if (this.wsPingSetInterval == null) {
+ this.startWebSocketPing()
+ }
})
this.on(ChargingStationEvents.disconnected, () => {
try {
}
}
- public get hasEvses (): boolean {
- return this.connectors.size === 0 && this.evses.size > 0
- }
-
- public get wsConnectionUrl (): URL {
- const wsConnectionBaseUrlStr = `${
- this.stationInfo?.supervisionUrlOcppConfiguration === true &&
- isNotEmptyString(this.stationInfo.supervisionUrlOcppKey) &&
- isNotEmptyString(getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey)?.value)
- ? getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey)?.value
- : this.configuredSupervisionUrl.href
- }`
- return new URL(
- `${wsConnectionBaseUrlStr}${!wsConnectionBaseUrlStr.endsWith('/') ? '/' : ''}${this.stationInfo?.chargingStationId}`
- )
- }
-
- public logPrefix = (): string => {
- if (
- this instanceof ChargingStation &&
- this.stationInfo != null &&
- isNotEmptyString(this.stationInfo.chargingStationId)
- ) {
- return logPrefix(` ${this.stationInfo.chargingStationId} |`)
- }
- let stationTemplate: ChargingStationTemplate | undefined
- try {
- stationTemplate = JSON.parse(
- readFileSync(this.templateFile, 'utf8')
- ) as ChargingStationTemplate
- } catch {
- // Ignore
+ public async addReservation (reservation: Reservation): Promise<void> {
+ const reservationFound = this.getReservationBy('reservationId', reservation.reservationId)
+ if (reservationFound != null) {
+ await this.removeReservation(reservationFound, ReservationTerminationReason.REPLACE_EXISTING)
}
- return logPrefix(` ${getChargingStationId(this.index, stationTemplate)} |`)
- }
-
- public hasIdTags (): boolean {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return isNotEmptyArray(this.idTagsCache.getIdTags(getIdTagsFile(this.stationInfo!)!))
- }
-
- public getNumberOfPhases (stationInfo?: ChargingStationInfo): number {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const localStationInfo = stationInfo ?? this.stationInfo!
- switch (this.getCurrentOutType(stationInfo)) {
- case CurrentType.AC:
- return localStationInfo.numberOfPhases ?? 3
- case CurrentType.DC:
- return 0
- }
- }
-
- public isWebSocketConnectionOpened (): boolean {
- return this.wsConnection?.readyState === WebSocket.OPEN
- }
-
- public inUnknownState (): boolean {
- return this.bootNotificationResponse?.status == null
- }
-
- public inPendingState (): boolean {
- return this.bootNotificationResponse?.status === RegistrationStatusEnumType.PENDING
- }
-
- public inAcceptedState (): boolean {
- return this.bootNotificationResponse?.status === RegistrationStatusEnumType.ACCEPTED
- }
-
- public inRejectedState (): boolean {
- return this.bootNotificationResponse?.status === RegistrationStatusEnumType.REJECTED
+ this.getConnectorStatus(reservation.connectorId)!.reservation = reservation
+ await sendAndSetConnectorStatus(
+ this,
+ reservation.connectorId,
+ ConnectorStatusEnum.Reserved,
+ undefined,
+ { send: reservation.connectorId !== 0 }
+ )
}
- public isRegistered (): boolean {
- return !this.inUnknownState() && (this.inAcceptedState() || this.inPendingState())
+ public bufferMessage (message: string): void {
+ this.messageQueue.push(message)
+ this.setIntervalFlushMessageBuffer()
}
- public isChargingStationAvailable (): boolean {
- return this.getConnectorStatus(0)?.availability === AvailabilityType.Operative
+ public closeWSConnection (): void {
+ if (this.isWebSocketConnectionOpened()) {
+ this.wsConnection?.close()
+ this.wsConnection = null
+ }
}
- public hasConnector (connectorId: number): boolean {
- if (this.hasEvses) {
- for (const evseStatus of this.evses.values()) {
- if (evseStatus.connectors.has(connectorId)) {
- return true
- }
- }
- return false
+ public async delete (deleteConfiguration = true): Promise<void> {
+ if (this.started) {
+ await this.stop()
}
- return this.connectors.has(connectorId)
+ AutomaticTransactionGenerator.deleteInstance(this)
+ PerformanceStatistics.deleteInstance(this.stationInfo?.hashId)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.idTagsCache.deleteIdTags(getIdTagsFile(this.stationInfo!)!)
+ this.requests.clear()
+ this.connectors.clear()
+ this.evses.clear()
+ this.templateFileWatcher?.unref()
+ deleteConfiguration && rmSync(this.configurationFile, { force: true })
+ this.chargingStationWorkerBroadcastChannel.unref()
+ this.emit(ChargingStationEvents.deleted)
+ this.removeAllListeners()
}
- public isConnectorAvailable (connectorId: number): boolean {
- return (
- connectorId > 0 &&
- this.getConnectorStatus(connectorId)?.availability === AvailabilityType.Operative
+ public getAuthorizeRemoteTxRequests (): boolean {
+ const authorizeRemoteTxRequests = getConfigurationKey(
+ this,
+ StandardParametersKey.AuthorizeRemoteTxRequests
)
+ return authorizeRemoteTxRequests != null
+ ? convertToBoolean(authorizeRemoteTxRequests.value)
+ : false
}
- public getNumberOfConnectors (): number {
- if (this.hasEvses) {
- let numberOfConnectors = 0
- for (const [evseId, evseStatus] of this.evses) {
- if (evseId > 0) {
- numberOfConnectors += evseStatus.connectors.size
- }
+ public getAutomaticTransactionGeneratorConfiguration ():
+ | AutomaticTransactionGeneratorConfiguration
+ | undefined {
+ if (this.automaticTransactionGeneratorConfiguration == null) {
+ let automaticTransactionGeneratorConfiguration:
+ | AutomaticTransactionGeneratorConfiguration
+ | undefined
+ const stationTemplate = this.getTemplateFromFile()
+ const stationConfiguration = this.getConfigurationFromFile()
+ if (
+ this.stationInfo?.automaticTransactionGeneratorPersistentConfiguration === true &&
+ stationConfiguration?.stationInfo?.templateHash === stationTemplate?.templateHash &&
+ stationConfiguration?.automaticTransactionGenerator != null
+ ) {
+ automaticTransactionGeneratorConfiguration =
+ stationConfiguration.automaticTransactionGenerator
+ } else {
+ automaticTransactionGeneratorConfiguration = stationTemplate?.AutomaticTransactionGenerator
+ }
+ this.automaticTransactionGeneratorConfiguration = {
+ ...Constants.DEFAULT_ATG_CONFIGURATION,
+ ...automaticTransactionGeneratorConfiguration,
}
- return numberOfConnectors
}
- return this.connectors.has(0) ? this.connectors.size - 1 : this.connectors.size
+ return this.automaticTransactionGeneratorConfiguration
}
- public getNumberOfEvses (): number {
- return this.evses.has(0) ? this.evses.size - 1 : this.evses.size
+ public getAutomaticTransactionGeneratorStatuses (): Status[] | undefined {
+ return this.getConfigurationFromFile()?.automaticTransactionGeneratorStatuses
}
- public getConnectorStatus (connectorId: number): ConnectorStatus | undefined {
- if (this.hasEvses) {
+ public getConnectorIdByTransactionId (transactionId: number | undefined): number | undefined {
+ if (transactionId == null) {
+ return undefined
+ } else if (this.hasEvses) {
for (const evseStatus of this.evses.values()) {
- if (evseStatus.connectors.has(connectorId)) {
- return evseStatus.connectors.get(connectorId)
+ for (const [connectorId, connectorStatus] of evseStatus.connectors) {
+ if (connectorStatus.transactionId === transactionId) {
+ return connectorId
+ }
+ }
+ }
+ } else {
+ for (const connectorId of this.connectors.keys()) {
+ if (this.getConnectorStatus(connectorId)?.transactionId === transactionId) {
+ return connectorId
}
}
- return undefined
}
- return this.connectors.get(connectorId)
}
public getConnectorMaximumAvailablePower (connectorId: number): number {
- let connectorAmperageLimitationPowerLimit: number | undefined
+ let connectorAmperageLimitationLimit: number | undefined
const amperageLimitation = this.getAmperageLimitation()
if (
amperageLimitation != null &&
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
amperageLimitation < this.stationInfo!.maximumAmperage!
) {
- connectorAmperageLimitationPowerLimit =
+ connectorAmperageLimitationLimit =
(this.stationInfo?.currentOutType === CurrentType.AC
? ACElectricUtils.powerTotal(
this.getNumberOfPhases(),
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const connectorMaximumPower = this.stationInfo!.maximumPower! / this.powerDivider!
- const connectorChargingProfilesPowerLimit =
- getChargingStationConnectorChargingProfilesPowerLimit(this, connectorId)
- return min(
- isNaN(connectorMaximumPower) ? Number.POSITIVE_INFINITY : connectorMaximumPower,
+ const chargingStationChargingProfilesLimit =
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- isNaN(connectorAmperageLimitationPowerLimit!)
+ getChargingStationChargingProfilesLimit(this)! / this.powerDivider!
+ const connectorChargingProfilesLimit = getConnectorChargingProfilesLimit(this, connectorId)
+ return min(
+ Number.isNaN(connectorMaximumPower) ? Number.POSITIVE_INFINITY : connectorMaximumPower,
+ connectorAmperageLimitationLimit == null || Number.isNaN(connectorAmperageLimitationLimit)
? Number.POSITIVE_INFINITY
- : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- connectorAmperageLimitationPowerLimit!,
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- isNaN(connectorChargingProfilesPowerLimit!)
+ : connectorAmperageLimitationLimit,
+ Number.isNaN(chargingStationChargingProfilesLimit)
? Number.POSITIVE_INFINITY
- : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- connectorChargingProfilesPowerLimit!
+ : chargingStationChargingProfilesLimit,
+ connectorChargingProfilesLimit == null || Number.isNaN(connectorChargingProfilesLimit)
+ ? Number.POSITIVE_INFINITY
+ : connectorChargingProfilesLimit
)
}
- public getTransactionIdTag (transactionId: number): string | undefined {
+ public getConnectorStatus (connectorId: number): ConnectorStatus | undefined {
if (this.hasEvses) {
for (const evseStatus of this.evses.values()) {
- for (const connectorStatus of evseStatus.connectors.values()) {
- if (connectorStatus.transactionId === transactionId) {
- return connectorStatus.transactionIdTag
- }
- }
- }
- } else {
- for (const connectorId of this.connectors.keys()) {
- if (this.getConnectorStatus(connectorId)?.transactionId === transactionId) {
- return this.getConnectorStatus(connectorId)?.transactionIdTag
+ if (evseStatus.connectors.has(connectorId)) {
+ return evseStatus.connectors.get(connectorId)
}
}
+ return undefined
}
+ return this.connectors.get(connectorId)
}
- public getNumberOfRunningTransactions (): number {
+ public getEnergyActiveImportRegisterByConnectorId (connectorId: number, rounded = false): number {
+ return this.getEnergyActiveImportRegister(this.getConnectorStatus(connectorId), rounded)
+ }
+
+ public getEnergyActiveImportRegisterByTransactionId (
+ transactionId: number | undefined,
+ rounded = false
+ ): number {
+ return this.getEnergyActiveImportRegister(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.getConnectorStatus(this.getConnectorIdByTransactionId(transactionId)!),
+ rounded
+ )
+ }
+
+ public getHeartbeatInterval (): number {
+ const HeartbeatInterval = getConfigurationKey(this, StandardParametersKey.HeartbeatInterval)
+ if (HeartbeatInterval != null) {
+ return secondsToMilliseconds(convertToInt(HeartbeatInterval.value))
+ }
+ const HeartBeatInterval = getConfigurationKey(this, StandardParametersKey.HeartBeatInterval)
+ if (HeartBeatInterval != null) {
+ return secondsToMilliseconds(convertToInt(HeartBeatInterval.value))
+ }
+ this.stationInfo?.autoRegister === false &&
+ logger.warn(
+ `${this.logPrefix()} Heartbeat interval configuration key not set, using default value: ${Constants.DEFAULT_HEARTBEAT_INTERVAL.toString()}`
+ )
+ return Constants.DEFAULT_HEARTBEAT_INTERVAL
+ }
+
+ public getLocalAuthListEnabled (): boolean {
+ const localAuthListEnabled = getConfigurationKey(
+ this,
+ StandardParametersKey.LocalAuthListEnabled
+ )
+ return localAuthListEnabled != null ? convertToBoolean(localAuthListEnabled.value) : false
+ }
+
+ public getNumberOfConnectors (): number {
+ if (this.hasEvses) {
+ let numberOfConnectors = 0
+ for (const [evseId, evseStatus] of this.evses) {
+ if (evseId > 0) {
+ numberOfConnectors += evseStatus.connectors.size
+ }
+ }
+ return numberOfConnectors
+ }
+ return this.connectors.has(0) ? this.connectors.size - 1 : this.connectors.size
+ }
+
+ public getNumberOfEvses (): number {
+ return this.evses.has(0) ? this.evses.size - 1 : this.evses.size
+ }
+
+ public getNumberOfPhases (stationInfo?: ChargingStationInfo): number {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const localStationInfo = stationInfo ?? this.stationInfo!
+ switch (this.getCurrentOutType(stationInfo)) {
+ case CurrentType.AC:
+ return localStationInfo.numberOfPhases ?? 3
+ case CurrentType.DC:
+ return 0
+ }
+ }
+
+ public getNumberOfRunningTransactions (): number {
let numberOfRunningTransactions = 0
if (this.hasEvses) {
for (const [evseId, evseStatus] of this.evses) {
return numberOfRunningTransactions
}
- public getConnectorIdByTransactionId (transactionId: number | undefined): number | undefined {
- if (transactionId == null) {
- return undefined
- } else if (this.hasEvses) {
+ public getReservationBy (
+ filterKey: ReservationKey,
+ value: number | string
+ ): Reservation | undefined {
+ if (this.hasEvses) {
for (const evseStatus of this.evses.values()) {
- for (const [connectorId, connectorStatus] of evseStatus.connectors) {
- if (connectorStatus.transactionId === transactionId) {
- return connectorId
+ for (const connectorStatus of evseStatus.connectors.values()) {
+ if (connectorStatus.reservation?.[filterKey] === value) {
+ return connectorStatus.reservation
}
}
}
} else {
- for (const connectorId of this.connectors.keys()) {
- if (this.getConnectorStatus(connectorId)?.transactionId === transactionId) {
- return connectorId
+ for (const connectorStatus of this.connectors.values()) {
+ if (connectorStatus.reservation?.[filterKey] === value) {
+ return connectorStatus.reservation
}
}
}
}
- public getEnergyActiveImportRegisterByTransactionId (
- transactionId: number | undefined,
- rounded = false
- ): number {
- return this.getEnergyActiveImportRegister(
+ public getReserveConnectorZeroSupported (): boolean {
+ return convertToBoolean(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.getConnectorStatus(this.getConnectorIdByTransactionId(transactionId)!),
- rounded
+ getConfigurationKey(this, StandardParametersKey.ReserveConnectorZeroSupported)!.value
)
}
- public getEnergyActiveImportRegisterByConnectorId (connectorId: number, rounded = false): number {
- return this.getEnergyActiveImportRegister(this.getConnectorStatus(connectorId), rounded)
+ public getTransactionIdTag (transactionId: number): string | undefined {
+ if (this.hasEvses) {
+ for (const evseStatus of this.evses.values()) {
+ for (const connectorStatus of evseStatus.connectors.values()) {
+ if (connectorStatus.transactionId === transactionId) {
+ return connectorStatus.transactionIdTag
+ }
+ }
+ }
+ } else {
+ for (const connectorId of this.connectors.keys()) {
+ if (this.getConnectorStatus(connectorId)?.transactionId === transactionId) {
+ return this.getConnectorStatus(connectorId)?.transactionIdTag
+ }
+ }
+ }
}
- public getAuthorizeRemoteTxRequests (): boolean {
- const authorizeRemoteTxRequests = getConfigurationKey(
- this,
- StandardParametersKey.AuthorizeRemoteTxRequests
- )
- return authorizeRemoteTxRequests != null
- ? convertToBoolean(authorizeRemoteTxRequests.value)
- : false
+ public hasConnector (connectorId: number): boolean {
+ if (this.hasEvses) {
+ for (const evseStatus of this.evses.values()) {
+ if (evseStatus.connectors.has(connectorId)) {
+ return true
+ }
+ }
+ return false
+ }
+ return this.connectors.has(connectorId)
}
- public getLocalAuthListEnabled (): boolean {
- const localAuthListEnabled = getConfigurationKey(
- this,
- StandardParametersKey.LocalAuthListEnabled
- )
- return localAuthListEnabled != null ? convertToBoolean(localAuthListEnabled.value) : false
+ public hasIdTags (): boolean {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return isNotEmptyArray(this.idTagsCache.getIdTags(getIdTagsFile(this.stationInfo!)!))
}
- public getHeartbeatInterval (): number {
- const HeartbeatInterval = getConfigurationKey(this, StandardParametersKey.HeartbeatInterval)
- if (HeartbeatInterval != null) {
- return secondsToMilliseconds(convertToInt(HeartbeatInterval.value))
- }
- const HeartBeatInterval = getConfigurationKey(this, StandardParametersKey.HeartBeatInterval)
- if (HeartBeatInterval != null) {
- return secondsToMilliseconds(convertToInt(HeartBeatInterval.value))
- }
- this.stationInfo?.autoRegister === false &&
- logger.warn(
- `${this.logPrefix()} Heartbeat interval configuration key not set, using default value: ${
- Constants.DEFAULT_HEARTBEAT_INTERVAL
- }`
- )
- return Constants.DEFAULT_HEARTBEAT_INTERVAL
+ public inAcceptedState (): boolean {
+ return this.bootNotificationResponse?.status === RegistrationStatusEnumType.ACCEPTED
}
- public setSupervisionUrl (url: string): void {
- if (
- this.stationInfo?.supervisionUrlOcppConfiguration === true &&
- isNotEmptyString(this.stationInfo.supervisionUrlOcppKey)
- ) {
- setConfigurationKeyValue(this, this.stationInfo.supervisionUrlOcppKey, url)
- } else {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.stationInfo!.supervisionUrls = url
- this.configuredSupervisionUrl = this.getConfiguredSupervisionUrl()
- this.saveStationInfo()
- }
+ public inPendingState (): boolean {
+ return this.bootNotificationResponse?.status === RegistrationStatusEnumType.PENDING
}
- public startHeartbeat (): void {
- if (this.getHeartbeatInterval() > 0 && this.heartbeatSetInterval == null) {
- this.heartbeatSetInterval = setInterval(() => {
- this.ocppRequestService
- .requestHandler<HeartbeatRequest, HeartbeatResponse>(this, RequestCommand.HEARTBEAT)
- .catch((error: unknown) => {
- logger.error(
- `${this.logPrefix()} Error while sending '${RequestCommand.HEARTBEAT}':`,
- error
- )
- })
- }, this.getHeartbeatInterval())
- logger.info(
- `${this.logPrefix()} Heartbeat started every ${formatDurationMilliSeconds(
- this.getHeartbeatInterval()
- )}`
- )
- } else if (this.heartbeatSetInterval != null) {
- logger.info(
- `${this.logPrefix()} Heartbeat already started every ${formatDurationMilliSeconds(
- this.getHeartbeatInterval()
- )}`
- )
- } else {
- logger.error(
- `${this.logPrefix()} Heartbeat interval set to ${this.getHeartbeatInterval()}, not starting the heartbeat`
- )
- }
+ public inRejectedState (): boolean {
+ return this.bootNotificationResponse?.status === RegistrationStatusEnumType.REJECTED
}
- public restartHeartbeat (): void {
- // Stop heartbeat
- this.stopHeartbeat()
- // Start heartbeat
- this.startHeartbeat()
+ public inUnknownState (): boolean {
+ return this.bootNotificationResponse?.status == null
}
- public restartWebSocketPing (): void {
- // Stop WebSocket ping
- this.stopWebSocketPing()
- // Start WebSocket ping
- this.startWebSocketPing()
+ public isChargingStationAvailable (): boolean {
+ return this.getConnectorStatus(0)?.availability === AvailabilityType.Operative
}
- public startMeterValues (connectorId: number, interval: number): void {
- if (connectorId === 0) {
- logger.error(`${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId}`)
- return
- }
- const connectorStatus = this.getConnectorStatus(connectorId)
- if (connectorStatus == null) {
- logger.error(
- `${this.logPrefix()} Trying to start MeterValues on non existing connector id
- ${connectorId}`
- )
- return
- }
- if (connectorStatus.transactionStarted === false) {
- logger.error(
- `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId} with no transaction started`
- )
- return
- } else if (
- connectorStatus.transactionStarted === true &&
- connectorStatus.transactionId == null
- ) {
- logger.error(
- `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId} with no transaction id`
+ public isConnectorAvailable (connectorId: number): boolean {
+ return (
+ connectorId > 0 &&
+ this.getConnectorStatus(connectorId)?.availability === AvailabilityType.Operative
+ )
+ }
+
+ public isConnectorReservable (
+ reservationId: number,
+ idTag?: string,
+ connectorId?: number
+ ): boolean {
+ const reservation = this.getReservationBy('reservationId', reservationId)
+ const reservationExists = reservation != null && !hasReservationExpired(reservation)
+ if (arguments.length === 1) {
+ return !reservationExists
+ } else if (arguments.length > 1) {
+ const userReservation = idTag != null ? this.getReservationBy('idTag', idTag) : undefined
+ const userReservationExists =
+ userReservation != null && !hasReservationExpired(userReservation)
+ const notConnectorZero = connectorId == null ? true : connectorId > 0
+ const freeConnectorsAvailable = this.getNumberOfReservableConnectors() > 0
+ return (
+ !reservationExists && !userReservationExists && notConnectorZero && freeConnectorsAvailable
)
- return
}
- if (interval > 0) {
- connectorStatus.transactionSetInterval = setInterval(() => {
- const meterValue = buildMeterValue(
- this,
- connectorId,
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- connectorStatus.transactionId!,
- interval
- )
- this.ocppRequestService
- .requestHandler<MeterValuesRequest, MeterValuesResponse>(
- this,
- RequestCommand.METER_VALUES,
- {
- connectorId,
- transactionId: connectorStatus.transactionId,
- meterValue: [meterValue]
- }
- )
- .catch((error: unknown) => {
- logger.error(
- `${this.logPrefix()} Error while sending '${RequestCommand.METER_VALUES}':`,
- error
- )
- })
- }, interval)
- } else {
- logger.error(
- `${this.logPrefix()} Charging station ${
- StandardParametersKey.MeterValueSampleInterval
- } configuration set to ${interval}, not sending MeterValues`
+ return false
+ }
+
+ public isWebSocketConnectionOpened (): boolean {
+ return this.wsConnection?.readyState === WebSocket.OPEN
+ }
+
+ public logPrefix = (): string => {
+ if (
+ this instanceof ChargingStation &&
+ this.stationInfo != null &&
+ isNotEmptyString(this.stationInfo.chargingStationId)
+ ) {
+ return logPrefix(` ${this.stationInfo.chargingStationId} |`)
+ }
+ let stationTemplate: ChargingStationTemplate | undefined
+ try {
+ stationTemplate = JSON.parse(
+ readFileSync(this.templateFile, 'utf8')
+ ) as ChargingStationTemplate
+ } catch {
+ // Ignore
+ }
+ return logPrefix(` ${getChargingStationId(this.index, stationTemplate)} |`)
+ }
+
+ public openWSConnection (
+ options?: WsOptions,
+ params?: { closeOpened?: boolean; terminateOpened?: boolean }
+ ): void {
+ options = {
+ handshakeTimeout: secondsToMilliseconds(this.getConnectionTimeout()),
+ ...this.stationInfo?.wsOptions,
+ ...options,
+ }
+ params = { ...{ closeOpened: false, terminateOpened: false }, ...params }
+ if (!checkChargingStationState(this, this.logPrefix())) {
+ return
+ }
+ if (this.stationInfo?.supervisionUser != null && this.stationInfo.supervisionPassword != null) {
+ options.auth = `${this.stationInfo.supervisionUser}:${this.stationInfo.supervisionPassword}`
+ }
+ if (params.closeOpened) {
+ this.closeWSConnection()
+ }
+ if (params.terminateOpened) {
+ this.terminateWSConnection()
+ }
+
+ if (this.isWebSocketConnectionOpened()) {
+ logger.warn(
+ `${this.logPrefix()} OCPP connection to URL ${this.wsConnectionUrl.href} is already opened`
)
+ return
}
+
+ logger.info(`${this.logPrefix()} Open OCPP connection to URL ${this.wsConnectionUrl.href}`)
+
+ this.wsConnection = new WebSocket(
+ this.wsConnectionUrl,
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `ocpp${this.stationInfo?.ocppVersion}`,
+ options
+ )
+
+ // Handle WebSocket message
+ this.wsConnection.on('message', data => {
+ this.onMessage(data).catch(Constants.EMPTY_FUNCTION)
+ })
+ // Handle WebSocket error
+ this.wsConnection.on('error', this.onError.bind(this))
+ // Handle WebSocket close
+ this.wsConnection.on('close', this.onClose.bind(this))
+ // Handle WebSocket open
+ this.wsConnection.on('open', () => {
+ this.onOpen().catch((error: unknown) =>
+ logger.error(`${this.logPrefix()} Error while opening WebSocket connection:`, error)
+ )
+ })
+ // Handle WebSocket ping
+ this.wsConnection.on('ping', this.onPing.bind(this))
+ // Handle WebSocket pong
+ this.wsConnection.on('pong', this.onPong.bind(this))
}
- public stopMeterValues (connectorId: number): void {
- const connectorStatus = this.getConnectorStatus(connectorId)
- if (connectorStatus?.transactionSetInterval != null) {
- clearInterval(connectorStatus.transactionSetInterval)
+ public async removeReservation (
+ reservation: Reservation,
+ reason: ReservationTerminationReason
+ ): Promise<void> {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const connector = this.getConnectorStatus(reservation.connectorId)!
+ switch (reason) {
+ case ReservationTerminationReason.CONNECTOR_STATE_CHANGED:
+ case ReservationTerminationReason.TRANSACTION_STARTED:
+ delete connector.reservation
+ break
+ case ReservationTerminationReason.EXPIRED:
+ case ReservationTerminationReason.REPLACE_EXISTING:
+ case ReservationTerminationReason.RESERVATION_CANCELED:
+ await sendAndSetConnectorStatus(
+ this,
+ reservation.connectorId,
+ ConnectorStatusEnum.Available,
+ undefined,
+ { send: reservation.connectorId !== 0 }
+ )
+ delete connector.reservation
+ break
+ default:
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ throw new BaseError(`Unknown reservation termination reason '${reason}'`)
}
}
- private add (): void {
- this.emit(ChargingStationEvents.added)
+ public async reset (reason?: StopTransactionReason): Promise<void> {
+ await this.stop(reason)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ await sleep(this.stationInfo!.resetTime!)
+ this.initialize()
+ this.start()
}
- public async delete (deleteConfiguration = true): Promise<void> {
- if (this.started) {
- await this.stop()
+ public restartHeartbeat (): void {
+ // Stop heartbeat
+ this.stopHeartbeat()
+ // Start heartbeat
+ this.startHeartbeat()
+ }
+
+ public restartMeterValues (connectorId: number, interval: number): void {
+ this.stopMeterValues(connectorId)
+ this.startMeterValues(connectorId, interval)
+ }
+
+ public restartWebSocketPing (): void {
+ // Stop WebSocket ping
+ this.stopWebSocketPing()
+ // Start WebSocket ping
+ this.startWebSocketPing()
+ }
+
+ public saveOcppConfiguration (): void {
+ if (this.stationInfo?.ocppPersistentConfiguration === true) {
+ this.saveConfiguration()
+ }
+ }
+
+ public setSupervisionUrl (url: string): void {
+ if (
+ this.stationInfo?.supervisionUrlOcppConfiguration === true &&
+ isNotEmptyString(this.stationInfo.supervisionUrlOcppKey)
+ ) {
+ setConfigurationKeyValue(this, this.stationInfo.supervisionUrlOcppKey, url)
+ } else {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.stationInfo!.supervisionUrls = url
+ this.configuredSupervisionUrl = this.getConfiguredSupervisionUrl()
+ this.saveStationInfo()
}
- AutomaticTransactionGenerator.deleteInstance(this)
- PerformanceStatistics.deleteInstance(this.stationInfo?.hashId)
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.idTagsCache.deleteIdTags(getIdTagsFile(this.stationInfo!)!)
- this.requests.clear()
- this.connectors.clear()
- this.evses.clear()
- this.templateFileWatcher?.unref()
- deleteConfiguration && rmSync(this.configurationFile, { force: true })
- this.chargingStationWorkerBroadcastChannel.unref()
- this.emit(ChargingStationEvents.deleted)
- this.removeAllListeners()
}
public start (): void {
}
}
- public async stop (
- reason?: StopTransactionReason,
- stopTransactions = this.stationInfo?.stopTransactionsOnStopped
- ): Promise<void> {
- if (this.started) {
- if (!this.stopping) {
- this.stopping = true
- await this.stopMessageSequence(reason, stopTransactions)
- this.closeWSConnection()
- if (this.stationInfo?.enableStatistics === true) {
- this.performanceStatistics?.stop()
- }
- this.templateFileWatcher?.close()
- delete this.bootNotificationResponse
- this.started = false
- this.saveConfiguration()
- this.sharedLRUCache.deleteChargingStationConfiguration(this.configurationFileHash)
- this.emit(ChargingStationEvents.stopped)
- this.stopping = false
- } else {
- logger.warn(`${this.logPrefix()} Charging station is already stopping...`)
+ public startAutomaticTransactionGenerator (
+ connectorIds?: number[],
+ stopAbsoluteDuration?: boolean
+ ): void {
+ this.automaticTransactionGenerator = AutomaticTransactionGenerator.getInstance(this)
+ if (isNotEmptyArray(connectorIds)) {
+ for (const connectorId of connectorIds) {
+ this.automaticTransactionGenerator?.startConnector(connectorId, stopAbsoluteDuration)
}
} else {
- logger.warn(`${this.logPrefix()} Charging station is already stopped...`)
+ this.automaticTransactionGenerator?.start(stopAbsoluteDuration)
}
+ this.saveAutomaticTransactionGeneratorConfiguration()
+ this.emit(ChargingStationEvents.updated)
}
- public async reset (reason?: StopTransactionReason): Promise<void> {
- await this.stop(reason)
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- await sleep(this.stationInfo!.resetTime!)
- this.initialize()
- this.start()
- }
-
- public saveOcppConfiguration (): void {
- if (this.stationInfo?.ocppPersistentConfiguration === true) {
- this.saveConfiguration()
+ public startHeartbeat (): void {
+ const heartbeatInterval = this.getHeartbeatInterval()
+ if (heartbeatInterval > 0 && this.heartbeatSetInterval == null) {
+ this.heartbeatSetInterval = setInterval(() => {
+ this.ocppRequestService
+ .requestHandler<HeartbeatRequest, HeartbeatResponse>(this, RequestCommand.HEARTBEAT)
+ .catch((error: unknown) => {
+ logger.error(
+ `${this.logPrefix()} Error while sending '${RequestCommand.HEARTBEAT}':`,
+ error
+ )
+ })
+ }, heartbeatInterval)
+ logger.info(
+ `${this.logPrefix()} Heartbeat started every ${formatDurationMilliSeconds(
+ heartbeatInterval
+ )}`
+ )
+ } else if (this.heartbeatSetInterval != null) {
+ logger.info(
+ `${this.logPrefix()} Heartbeat already started every ${formatDurationMilliSeconds(
+ heartbeatInterval
+ )}`
+ )
+ } else {
+ logger.error(
+ `${this.logPrefix()} Heartbeat interval set to ${heartbeatInterval.toString()}, not starting the heartbeat`
+ )
}
}
- public bufferMessage (message: string): void {
- this.messageBuffer.add(message)
- this.setIntervalFlushMessageBuffer()
- }
-
- public openWSConnection (
- options?: WsOptions,
- params?: { closeOpened?: boolean, terminateOpened?: boolean }
- ): void {
- options = {
- handshakeTimeout: secondsToMilliseconds(this.getConnectionTimeout()),
- ...this.stationInfo?.wsOptions,
- ...options
- }
- params = { ...{ closeOpened: false, terminateOpened: false }, ...params }
- if (!checkChargingStation(this, this.logPrefix())) {
+ public startMeterValues (connectorId: number, interval: number): void {
+ if (connectorId === 0) {
+ logger.error(
+ `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId.toString()}`
+ )
return
}
- if (this.stationInfo?.supervisionUser != null && this.stationInfo.supervisionPassword != null) {
- options.auth = `${this.stationInfo.supervisionUser}:${this.stationInfo.supervisionPassword}`
- }
- if (params.closeOpened === true) {
- this.closeWSConnection()
- }
- if (params.terminateOpened === true) {
- this.terminateWSConnection()
+ const connectorStatus = this.getConnectorStatus(connectorId)
+ if (connectorStatus == null) {
+ logger.error(
+ `${this.logPrefix()} Trying to start MeterValues on non existing connector id
+ ${connectorId.toString()}`
+ )
+ return
}
-
- if (this.isWebSocketConnectionOpened()) {
- logger.warn(
- `${this.logPrefix()} OCPP connection to URL ${this.wsConnectionUrl.href} is already opened`
+ if (connectorStatus.transactionStarted === false) {
+ logger.error(
+ `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId.toString()} with no transaction started`
+ )
+ return
+ } else if (
+ connectorStatus.transactionStarted === true &&
+ connectorStatus.transactionId == null
+ ) {
+ logger.error(
+ `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId.toString()} with no transaction id`
)
return
}
-
- logger.info(`${this.logPrefix()} Open OCPP connection to URL ${this.wsConnectionUrl.href}`)
-
- this.wsConnection = new WebSocket(
- this.wsConnectionUrl,
- `ocpp${this.stationInfo?.ocppVersion}`,
- options
- )
-
- // Handle WebSocket message
- this.wsConnection.on('message', data => {
- this.onMessage(data).catch(Constants.EMPTY_FUNCTION)
- })
- // Handle WebSocket error
- this.wsConnection.on('error', this.onError.bind(this))
- // Handle WebSocket close
- this.wsConnection.on('close', this.onClose.bind(this))
- // Handle WebSocket open
- this.wsConnection.on('open', () => {
- this.onOpen().catch((error: unknown) =>
- logger.error(`${this.logPrefix()} Error while opening WebSocket connection:`, error)
+ if (interval > 0) {
+ connectorStatus.transactionSetInterval = setInterval(() => {
+ const meterValue = buildMeterValue(
+ this,
+ connectorId,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ connectorStatus.transactionId!,
+ interval
+ )
+ this.ocppRequestService
+ .requestHandler<MeterValuesRequest, MeterValuesResponse>(
+ this,
+ RequestCommand.METER_VALUES,
+ {
+ connectorId,
+ meterValue: [meterValue],
+ transactionId: connectorStatus.transactionId,
+ }
+ )
+ .catch((error: unknown) => {
+ logger.error(
+ `${this.logPrefix()} Error while sending '${RequestCommand.METER_VALUES}':`,
+ error
+ )
+ })
+ }, interval)
+ } else {
+ logger.error(
+ `${this.logPrefix()} Charging station ${
+ StandardParametersKey.MeterValueSampleInterval
+ } configuration set to ${interval.toString()}, not sending MeterValues`
)
- })
- // Handle WebSocket ping
- this.wsConnection.on('ping', this.onPing.bind(this))
- // Handle WebSocket pong
- this.wsConnection.on('pong', this.onPong.bind(this))
- }
-
- public closeWSConnection (): void {
- if (this.isWebSocketConnectionOpened()) {
- this.wsConnection?.close()
- this.wsConnection = null
}
}
- public getAutomaticTransactionGeneratorConfiguration ():
- | AutomaticTransactionGeneratorConfiguration
- | undefined {
- if (this.automaticTransactionGeneratorConfiguration == null) {
- let automaticTransactionGeneratorConfiguration:
- | AutomaticTransactionGeneratorConfiguration
- | undefined
- const stationTemplate = this.getTemplateFromFile()
- const stationConfiguration = this.getConfigurationFromFile()
- if (
- this.stationInfo?.automaticTransactionGeneratorPersistentConfiguration === true &&
- stationConfiguration?.stationInfo?.templateHash === stationTemplate?.templateHash &&
- stationConfiguration?.automaticTransactionGenerator != null
- ) {
- automaticTransactionGeneratorConfiguration =
- stationConfiguration.automaticTransactionGenerator
+ public async stop (
+ reason?: StopTransactionReason,
+ stopTransactions = this.stationInfo?.stopTransactionsOnStopped
+ ): Promise<void> {
+ if (this.started) {
+ if (!this.stopping) {
+ this.stopping = true
+ await this.stopMessageSequence(reason, stopTransactions)
+ this.closeWSConnection()
+ if (this.stationInfo?.enableStatistics === true) {
+ this.performanceStatistics?.stop()
+ }
+ this.templateFileWatcher?.close()
+ delete this.bootNotificationResponse
+ this.started = false
+ this.saveConfiguration()
+ this.sharedLRUCache.deleteChargingStationConfiguration(this.configurationFileHash)
+ this.emit(ChargingStationEvents.stopped)
+ this.stopping = false
} else {
- automaticTransactionGeneratorConfiguration = stationTemplate?.AutomaticTransactionGenerator
- }
- this.automaticTransactionGeneratorConfiguration = {
- ...Constants.DEFAULT_ATG_CONFIGURATION,
- ...automaticTransactionGeneratorConfiguration
- }
- }
- return this.automaticTransactionGeneratorConfiguration
- }
-
- public getAutomaticTransactionGeneratorStatuses (): Status[] | undefined {
- return this.getConfigurationFromFile()?.automaticTransactionGeneratorStatuses
- }
-
- public startAutomaticTransactionGenerator (
- connectorIds?: number[],
- stopAbsoluteDuration?: boolean
- ): void {
- this.automaticTransactionGenerator = AutomaticTransactionGenerator.getInstance(this)
- if (isNotEmptyArray(connectorIds)) {
- for (const connectorId of connectorIds) {
- this.automaticTransactionGenerator?.startConnector(connectorId, stopAbsoluteDuration)
+ logger.warn(`${this.logPrefix()} Charging station is already stopping...`)
}
} else {
- this.automaticTransactionGenerator?.start(stopAbsoluteDuration)
+ logger.warn(`${this.logPrefix()} Charging station is already stopped...`)
}
- this.saveAutomaticTransactionGeneratorConfiguration()
- this.emit(ChargingStationEvents.updated)
}
public stopAutomaticTransactionGenerator (connectorIds?: number[]): void {
this.emit(ChargingStationEvents.updated)
}
+ public stopMeterValues (connectorId: number): void {
+ const connectorStatus = this.getConnectorStatus(connectorId)
+ if (connectorStatus?.transactionSetInterval != null) {
+ clearInterval(connectorStatus.transactionSetInterval)
+ }
+ }
+
public async stopTransactionOnConnector (
connectorId: number,
reason?: StopTransactionReason
RequestCommand.METER_VALUES,
{
connectorId,
+ meterValue: [transactionEndMeterValue],
transactionId,
- meterValue: [transactionEndMeterValue]
}
)
}
return await this.ocppRequestService.requestHandler<
- Partial<StopTransactionRequest>,
- StopTransactionResponse
+ Partial<StopTransactionRequest>,
+ StopTransactionResponse
>(this, RequestCommand.STOP_TRANSACTION, {
- transactionId,
meterStop: this.getEnergyActiveImportRegisterByTransactionId(transactionId, true),
- ...(reason != null && { reason })
+ transactionId,
+ ...(reason != null && { reason }),
})
}
- public getReserveConnectorZeroSupported (): boolean {
- return convertToBoolean(
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- getConfigurationKey(this, StandardParametersKey.ReserveConnectorZeroSupported)!.value
- )
+ private add (): void {
+ this.emit(ChargingStationEvents.added)
}
- public async addReservation (reservation: Reservation): Promise<void> {
- const reservationFound = this.getReservationBy('reservationId', reservation.reservationId)
- if (reservationFound != null) {
- await this.removeReservation(reservationFound, ReservationTerminationReason.REPLACE_EXISTING)
+ private clearIntervalFlushMessageBuffer (): void {
+ if (this.flushMessageBufferSetInterval != null) {
+ clearInterval(this.flushMessageBufferSetInterval)
+ delete this.flushMessageBufferSetInterval
}
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.getConnectorStatus(reservation.connectorId)!.reservation = reservation
- await sendAndSetConnectorStatus(
- this,
- reservation.connectorId,
- ConnectorStatusEnum.Reserved,
- undefined,
- { send: reservation.connectorId !== 0 }
- )
}
- public async removeReservation (
- reservation: Reservation,
- reason: ReservationTerminationReason
- ): Promise<void> {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const connector = this.getConnectorStatus(reservation.connectorId)!
- switch (reason) {
- case ReservationTerminationReason.CONNECTOR_STATE_CHANGED:
- case ReservationTerminationReason.TRANSACTION_STARTED:
- delete connector.reservation
- break
- case ReservationTerminationReason.RESERVATION_CANCELED:
- case ReservationTerminationReason.REPLACE_EXISTING:
- case ReservationTerminationReason.EXPIRED:
- await sendAndSetConnectorStatus(
- this,
- reservation.connectorId,
- ConnectorStatusEnum.Available,
- undefined,
- { send: reservation.connectorId !== 0 }
- )
- delete connector.reservation
- break
- default:
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- throw new BaseError(`Unknown reservation termination reason '${reason}'`)
+ private flushMessageBuffer (): void {
+ if (!this.flushingMessageBuffer && this.messageQueue.length > 0) {
+ this.flushingMessageBuffer = true
+ this.sendMessageBuffer(() => {
+ this.flushingMessageBuffer = false
+ })
}
}
- public getReservationBy (
- filterKey: ReservationKey,
- value: number | string
- ): Reservation | undefined {
- if (this.hasEvses) {
- for (const evseStatus of this.evses.values()) {
- for (const connectorStatus of evseStatus.connectors.values()) {
- if (connectorStatus.reservation?.[filterKey] === value) {
- return connectorStatus.reservation
- }
- }
- }
- } else {
- for (const connectorStatus of this.connectors.values()) {
- if (connectorStatus.reservation?.[filterKey] === value) {
- return connectorStatus.reservation
- }
- }
+ private getAmperageLimitation (): number | undefined {
+ if (
+ isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
+ getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey) != null
+ ) {
+ return (
+ convertToInt(getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey)?.value) /
+ getAmperageLimitationUnitDivider(this.stationInfo)
+ )
}
}
- public isConnectorReservable (
- reservationId: number,
- idTag?: string,
- connectorId?: number
- ): boolean {
- const reservation = this.getReservationBy('reservationId', reservationId)
- const reservationExists = reservation != null && !hasReservationExpired(reservation)
- if (arguments.length === 1) {
- return !reservationExists
- } else if (arguments.length > 1) {
- const userReservation = idTag != null ? this.getReservationBy('idTag', idTag) : undefined
- const userReservationExists =
- userReservation != null && !hasReservationExpired(userReservation)
- const notConnectorZero = connectorId == null ? true : connectorId > 0
- const freeConnectorsAvailable = this.getNumberOfReservableConnectors() > 0
- return (
- !reservationExists && !userReservationExists && notConnectorZero && freeConnectorsAvailable
- )
+ private getCachedRequest (
+ messageType: MessageType | undefined,
+ messageId: string
+ ): CachedRequest | undefined {
+ const cachedRequest = this.requests.get(messageId)
+ if (Array.isArray(cachedRequest)) {
+ return cachedRequest
}
- return false
+ throw new OCPPError(
+ ErrorType.PROTOCOL_ERROR,
+ `Cached request for message id '${messageId}' ${getMessageTypeString(
+ messageType
+ )} is not an array`,
+ undefined,
+ cachedRequest
+ )
}
- private setIntervalFlushMessageBuffer (): void {
- if (this.flushMessageBufferSetInterval == null) {
- this.flushMessageBufferSetInterval = setInterval(() => {
- if (this.isWebSocketConnectionOpened() && this.inAcceptedState()) {
- this.flushMessageBuffer()
- }
- if (this.messageBuffer.size === 0) {
- this.clearIntervalFlushMessageBuffer()
+ private getConfigurationFromFile (): ChargingStationConfiguration | undefined {
+ let configuration: ChargingStationConfiguration | undefined
+ if (isNotEmptyString(this.configurationFile) && existsSync(this.configurationFile)) {
+ try {
+ if (this.sharedLRUCache.hasChargingStationConfiguration(this.configurationFileHash)) {
+ configuration = this.sharedLRUCache.getChargingStationConfiguration(
+ this.configurationFileHash
+ )
+ } else {
+ const measureId = `${FileType.ChargingStationConfiguration} read`
+ const beginId = PerformanceStatistics.beginMeasure(measureId)
+ configuration = JSON.parse(
+ readFileSync(this.configurationFile, 'utf8')
+ ) as ChargingStationConfiguration
+ PerformanceStatistics.endMeasure(measureId, beginId)
+ this.sharedLRUCache.setChargingStationConfiguration(configuration)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.configurationFileHash = configuration.configurationHash!
}
- }, Constants.DEFAULT_MESSAGE_BUFFER_FLUSH_INTERVAL)
+ } catch (error) {
+ handleFileException(
+ this.configurationFile,
+ FileType.ChargingStationConfiguration,
+ error as NodeJS.ErrnoException,
+ this.logPrefix()
+ )
+ }
}
+ return configuration
}
- private clearIntervalFlushMessageBuffer (): void {
- if (this.flushMessageBufferSetInterval != null) {
- clearInterval(this.flushMessageBufferSetInterval)
- delete this.flushMessageBufferSetInterval
+ private getConfiguredSupervisionUrl (): URL {
+ let configuredSupervisionUrl: string | undefined
+ const supervisionUrls = this.stationInfo?.supervisionUrls ?? Configuration.getSupervisionUrls()
+ if (isNotEmptyArray(supervisionUrls)) {
+ let configuredSupervisionUrlIndex: number
+ switch (Configuration.getSupervisionUrlDistribution()) {
+ case SupervisionUrlDistribution.RANDOM:
+ configuredSupervisionUrlIndex = Math.floor(secureRandom() * supervisionUrls.length)
+ break
+ case SupervisionUrlDistribution.CHARGING_STATION_AFFINITY:
+ case SupervisionUrlDistribution.ROUND_ROBIN:
+ default:
+ !Object.values(SupervisionUrlDistribution).includes(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ Configuration.getSupervisionUrlDistribution()!
+ ) &&
+ logger.warn(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions, @typescript-eslint/no-base-to-string
+ `${this.logPrefix()} Unknown supervision url distribution '${Configuration.getSupervisionUrlDistribution()}' in configuration from values '${SupervisionUrlDistribution.toString()}', defaulting to '${
+ SupervisionUrlDistribution.CHARGING_STATION_AFFINITY
+ }'`
+ )
+ configuredSupervisionUrlIndex = (this.index - 1) % supervisionUrls.length
+ break
+ }
+ configuredSupervisionUrl = supervisionUrls[configuredSupervisionUrlIndex]
+ } else if (typeof supervisionUrls === 'string') {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ configuredSupervisionUrl = supervisionUrls!
+ }
+ if (isNotEmptyString(configuredSupervisionUrl)) {
+ return new URL(configuredSupervisionUrl)
+ }
+ const errorMsg = 'No supervision url(s) configured'
+ logger.error(`${this.logPrefix()} ${errorMsg}`)
+ throw new BaseError(errorMsg)
+ }
+
+ // 0 for disabling
+ private getConnectionTimeout (): number {
+ if (getConfigurationKey(this, StandardParametersKey.ConnectionTimeOut) != null) {
+ return convertToInt(
+ getConfigurationKey(this, StandardParametersKey.ConnectionTimeOut)?.value ??
+ Constants.DEFAULT_CONNECTION_TIMEOUT
+ )
+ }
+ return Constants.DEFAULT_CONNECTION_TIMEOUT
+ }
+
+ private getCurrentOutType (stationInfo?: ChargingStationInfo): CurrentType {
+ return (
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ (stationInfo ?? this.stationInfo!).currentOutType ??
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ Constants.DEFAULT_STATION_INFO.currentOutType!
+ )
+ }
+
+ private getEnergyActiveImportRegister (
+ connectorStatus: ConnectorStatus | undefined,
+ rounded = false
+ ): number {
+ if (this.stationInfo?.meteringPerTransaction === true) {
+ return (
+ (rounded
+ ? connectorStatus?.transactionEnergyActiveImportRegisterValue != null
+ ? Math.round(connectorStatus.transactionEnergyActiveImportRegisterValue)
+ : undefined
+ : connectorStatus?.transactionEnergyActiveImportRegisterValue) ?? 0
+ )
+ }
+ return (
+ (rounded
+ ? connectorStatus?.energyActiveImportRegisterValue != null
+ ? Math.round(connectorStatus.energyActiveImportRegisterValue)
+ : undefined
+ : connectorStatus?.energyActiveImportRegisterValue) ?? 0
+ )
+ }
+
+ private getMaximumAmperage (stationInfo?: ChargingStationInfo): number | undefined {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const maximumPower = (stationInfo ?? this.stationInfo!).maximumPower!
+ switch (this.getCurrentOutType(stationInfo)) {
+ case CurrentType.AC:
+ return ACElectricUtils.amperagePerPhaseFromPower(
+ this.getNumberOfPhases(stationInfo),
+ maximumPower / (this.hasEvses ? this.getNumberOfEvses() : this.getNumberOfConnectors()),
+ this.getVoltageOut(stationInfo)
+ )
+ case CurrentType.DC:
+ return DCElectricUtils.amperage(maximumPower, this.getVoltageOut(stationInfo))
}
}
return 0
}
- private flushMessageBuffer (): void {
- if (this.messageBuffer.size > 0) {
- for (const message of this.messageBuffer.values()) {
- let beginId: string | undefined
- let commandName: RequestCommand | undefined
- const [messageType] = JSON.parse(message) as OutgoingRequest | Response | ErrorResponse
- const isRequest = messageType === MessageType.CALL_MESSAGE
- if (isRequest) {
- [, , commandName] = JSON.parse(message) as OutgoingRequest
- beginId = PerformanceStatistics.beginMeasure(commandName)
- }
- this.wsConnection?.send(message, (error?: Error) => {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- isRequest && PerformanceStatistics.endMeasure(commandName!, beginId!)
- if (error == null) {
- logger.debug(
- `${this.logPrefix()} >> Buffered ${getMessageTypeString(
- messageType
- )} OCPP message sent '${JSON.stringify(message)}'`
- )
- this.messageBuffer.delete(message)
- } else {
- logger.debug(
- `${this.logPrefix()} >> Buffered ${getMessageTypeString(
- messageType
- )} OCPP message '${JSON.stringify(message)}' send failed:`,
- error
- )
- }
- })
- }
+ private getOcppConfiguration (
+ ocppPersistentConfiguration: boolean | undefined = this.stationInfo?.ocppPersistentConfiguration
+ ): ChargingStationOcppConfiguration | undefined {
+ let ocppConfiguration: ChargingStationOcppConfiguration | undefined =
+ this.getOcppConfigurationFromFile(ocppPersistentConfiguration)
+ ocppConfiguration ??= this.getOcppConfigurationFromTemplate()
+ return ocppConfiguration
+ }
+
+ private getOcppConfigurationFromFile (
+ ocppPersistentConfiguration?: boolean
+ ): ChargingStationOcppConfiguration | undefined {
+ const configurationKey = this.getConfigurationFromFile()?.configurationKey
+ if (ocppPersistentConfiguration && Array.isArray(configurationKey)) {
+ return { configurationKey }
}
+ return undefined
}
- private getTemplateFromFile (): ChargingStationTemplate | undefined {
- let template: ChargingStationTemplate | undefined
- try {
- if (this.sharedLRUCache.hasChargingStationTemplate(this.templateFileHash)) {
- template = this.sharedLRUCache.getChargingStationTemplate(this.templateFileHash)
- } else {
- const measureId = `${FileType.ChargingStationTemplate} read`
- const beginId = PerformanceStatistics.beginMeasure(measureId)
- template = JSON.parse(readFileSync(this.templateFile, 'utf8')) as ChargingStationTemplate
- PerformanceStatistics.endMeasure(measureId, beginId)
- template.templateHash = createHash(Constants.DEFAULT_HASH_ALGORITHM)
- .update(JSON.stringify(template))
- .digest('hex')
- this.sharedLRUCache.setChargingStationTemplate(template)
- this.templateFileHash = template.templateHash
+ private getOcppConfigurationFromTemplate (): ChargingStationOcppConfiguration | undefined {
+ return this.getTemplateFromFile()?.Configuration
+ }
+
+ private getPowerDivider (): number {
+ let powerDivider = this.hasEvses ? this.getNumberOfEvses() : this.getNumberOfConnectors()
+ if (this.stationInfo?.powerSharedByConnectors === true) {
+ powerDivider = this.getNumberOfRunningTransactions()
+ }
+ return powerDivider
+ }
+
+ private getStationInfo (options?: ChargingStationOptions): ChargingStationInfo {
+ const stationInfoFromTemplate = this.getStationInfoFromTemplate()
+ options?.persistentConfiguration != null &&
+ (stationInfoFromTemplate.stationInfoPersistentConfiguration = options.persistentConfiguration)
+ const stationInfoFromFile = this.getStationInfoFromFile(
+ stationInfoFromTemplate.stationInfoPersistentConfiguration
+ )
+ let stationInfo: ChargingStationInfo
+ // Priority:
+ // 1. charging station info from template
+ // 2. charging station info from configuration file
+ if (
+ stationInfoFromFile != null &&
+ stationInfoFromFile.templateHash === stationInfoFromTemplate.templateHash
+ ) {
+ stationInfo = stationInfoFromFile
+ } else {
+ stationInfo = stationInfoFromTemplate
+ stationInfoFromFile != null &&
+ propagateSerialNumber(this.getTemplateFromFile(), stationInfoFromFile, stationInfo)
+ }
+ return setChargingStationOptions(
+ mergeDeepRight(Constants.DEFAULT_STATION_INFO, stationInfo),
+ options
+ )
+ }
+
+ private getStationInfoFromFile (
+ stationInfoPersistentConfiguration: boolean | undefined = Constants.DEFAULT_STATION_INFO
+ .stationInfoPersistentConfiguration
+ ): ChargingStationInfo | undefined {
+ let stationInfo: ChargingStationInfo | undefined
+ if (stationInfoPersistentConfiguration) {
+ stationInfo = this.getConfigurationFromFile()?.stationInfo
+ if (stationInfo != null) {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ delete stationInfo.infoHash
+ delete (stationInfo as ChargingStationTemplate).numberOfConnectors
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ stationInfo.templateIndex ??= this.index
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ stationInfo.templateName ??= buildTemplateName(this.templateFile)
}
- } catch (error) {
- handleFileException(
- this.templateFile,
- FileType.ChargingStationTemplate,
- error as NodeJS.ErrnoException,
- this.logPrefix()
- )
}
- return template
+ return stationInfo
}
private getStationInfoFromTemplate (): ChargingStationInfo {
stationInfo.chargingStationId = getChargingStationId(this.index, stationTemplate)
createSerialNumber(stationTemplate, stationInfo)
stationInfo.voltageOut = this.getVoltageOut(stationInfo)
- if (isNotEmptyArray(stationTemplate.power)) {
+ if (isNotEmptyArray<number>(stationTemplate.power)) {
const powerArrayRandomIndex = Math.floor(secureRandom() * stationTemplate.power.length)
stationInfo.maximumPower =
stationTemplate.powerUnit === PowerUnits.KILO_WATT
? stationTemplate.power[powerArrayRandomIndex] * 1000
: stationTemplate.power[powerArrayRandomIndex]
- } else {
+ } else if (typeof stationTemplate.power === 'number') {
stationInfo.maximumPower =
stationTemplate.powerUnit === PowerUnits.KILO_WATT
- ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- stationTemplate.power! * 1000
+ ? stationTemplate.power * 1000
: stationTemplate.power
}
stationInfo.maximumAmperage = this.getMaximumAmperage(stationInfo)
return stationInfo
}
- private getStationInfoFromFile (
- stationInfoPersistentConfiguration: boolean | undefined = Constants.DEFAULT_STATION_INFO
- .stationInfoPersistentConfiguration
- ): ChargingStationInfo | undefined {
- let stationInfo: ChargingStationInfo | undefined
- if (stationInfoPersistentConfiguration === true) {
- stationInfo = this.getConfigurationFromFile()?.stationInfo
- if (stationInfo != null) {
- delete stationInfo.infoHash
- delete (stationInfo as ChargingStationTemplate).numberOfConnectors
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
- if (stationInfo.templateIndex == null) {
- stationInfo.templateIndex = this.index
- }
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
- if (stationInfo.templateName == null) {
- stationInfo.templateName = buildTemplateName(this.templateFile)
- }
- }
- }
- return stationInfo
- }
-
- private getStationInfo (options?: ChargingStationOptions): ChargingStationInfo {
- const stationInfoFromTemplate = this.getStationInfoFromTemplate()
- options?.persistentConfiguration != null &&
- (stationInfoFromTemplate.stationInfoPersistentConfiguration = options.persistentConfiguration)
- const stationInfoFromFile = this.getStationInfoFromFile(
- stationInfoFromTemplate.stationInfoPersistentConfiguration
+ private getTemplateFromFile (): ChargingStationTemplate | undefined {
+ let template: ChargingStationTemplate | undefined
+ try {
+ if (this.sharedLRUCache.hasChargingStationTemplate(this.templateFileHash)) {
+ template = this.sharedLRUCache.getChargingStationTemplate(this.templateFileHash)
+ } else {
+ const measureId = `${FileType.ChargingStationTemplate} read`
+ const beginId = PerformanceStatistics.beginMeasure(measureId)
+ template = JSON.parse(readFileSync(this.templateFile, 'utf8')) as ChargingStationTemplate
+ PerformanceStatistics.endMeasure(measureId, beginId)
+ template.templateHash = hash(
+ Constants.DEFAULT_HASH_ALGORITHM,
+ JSON.stringify(template),
+ 'hex'
+ )
+ this.sharedLRUCache.setChargingStationTemplate(template)
+ this.templateFileHash = template.templateHash
+ }
+ } catch (error) {
+ handleFileException(
+ this.templateFile,
+ FileType.ChargingStationTemplate,
+ error as NodeJS.ErrnoException,
+ this.logPrefix()
+ )
+ }
+ return template
+ }
+
+ private getUseConnectorId0 (stationTemplate?: ChargingStationTemplate): boolean {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return stationTemplate?.useConnectorId0 ?? Constants.DEFAULT_STATION_INFO.useConnectorId0!
+ }
+
+ private getVoltageOut (stationInfo?: ChargingStationInfo): Voltage {
+ return (
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ (stationInfo ?? this.stationInfo!).voltageOut ??
+ getDefaultVoltageOut(this.getCurrentOutType(stationInfo), this.logPrefix(), this.templateFile)
)
- let stationInfo: ChargingStationInfo
- // Priority:
- // 1. charging station info from template
- // 2. charging station info from configuration file
- if (
- stationInfoFromFile != null &&
- stationInfoFromFile.templateHash === stationInfoFromTemplate.templateHash
- ) {
- stationInfo = stationInfoFromFile
- } else {
- stationInfo = stationInfoFromTemplate
- stationInfoFromFile != null &&
- propagateSerialNumber(this.getTemplateFromFile(), stationInfoFromFile, stationInfo)
+ }
+
+ private getWebSocketPingInterval (): number {
+ return getConfigurationKey(this, StandardParametersKey.WebSocketPingInterval) != null
+ ? convertToInt(getConfigurationKey(this, StandardParametersKey.WebSocketPingInterval)?.value)
+ : 0
+ }
+
+ private handleErrorMessage (errorResponse: ErrorResponse): void {
+ const [messageType, messageId, errorType, errorMessage, errorDetails] = errorResponse
+ if (!this.requests.has(messageId)) {
+ // Error
+ throw new OCPPError(
+ ErrorType.INTERNAL_ERROR,
+ `Error response for unknown message id '${messageId}'`,
+ undefined,
+ { errorDetails, errorMessage, errorType }
+ )
}
- return setChargingStationOptions(
- mergeDeepRight(Constants.DEFAULT_STATION_INFO, stationInfo),
- options
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const [, errorCallback, requestCommandName] = this.getCachedRequest(messageType, messageId)!
+ logger.debug(
+ `${this.logPrefix()} << Command '${requestCommandName}' received error response payload: ${JSON.stringify(
+ errorResponse
+ )}`
)
+ errorCallback(new OCPPError(errorType, errorMessage, requestCommandName, errorDetails))
}
- private saveStationInfo (): void {
- if (this.stationInfo?.stationInfoPersistentConfiguration === true) {
- this.saveConfiguration()
+ private async handleIncomingMessage (request: IncomingRequest): Promise<void> {
+ const [messageType, messageId, commandName, commandPayload] = request
+ if (this.requests.has(messageId)) {
+ throw new OCPPError(
+ ErrorType.SECURITY_ERROR,
+ `Received message with duplicate message id '${messageId}'`,
+ commandName,
+ commandPayload
+ )
+ }
+ if (this.stationInfo?.enableStatistics === true) {
+ this.performanceStatistics?.addRequestStatistic(commandName, messageType)
+ }
+ logger.debug(
+ `${this.logPrefix()} << Command '${commandName}' received request payload: ${JSON.stringify(
+ request
+ )}`
+ )
+ // Process the message
+ await this.ocppIncomingRequestService.incomingRequestHandler(
+ this,
+ messageId,
+ commandName,
+ commandPayload
+ )
+ this.emit(ChargingStationEvents.updated)
+ }
+
+ private handleResponseMessage (response: Response): void {
+ const [messageType, messageId, commandPayload] = response
+ if (!this.requests.has(messageId)) {
+ // Error
+ throw new OCPPError(
+ ErrorType.INTERNAL_ERROR,
+ `Response for unknown message id '${messageId}'`,
+ undefined,
+ commandPayload
+ )
}
+ // Respond
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const [responseCallback, , requestCommandName, requestPayload] = this.getCachedRequest(
+ messageType,
+ messageId
+ )!
+ logger.debug(
+ `${this.logPrefix()} << Command '${requestCommandName}' received response payload: ${JSON.stringify(
+ response
+ )}`
+ )
+ responseCallback(commandPayload, requestPayload)
}
private handleUnsupportedVersion (version: OCPPVersion | undefined): void {
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
const errorMsg = `Unsupported protocol version '${version}' configured in template file ${this.templateFile}`
logger.error(`${this.logPrefix()} ${errorMsg}`)
throw new BaseError(errorMsg)
this.initializeConnectorsOrEvsesFromTemplate(stationTemplate)
}
this.stationInfo = this.getStationInfo(options)
+ validateStationInfo(this)
if (
this.stationInfo.firmwareStatus === FirmwareStatus.Installing &&
isNotEmptyString(this.stationInfo.firmwareVersionPattern) &&
this.bootNotificationResponse = {
currentTime: new Date(),
interval: millisecondsToSeconds(this.getHeartbeatInterval()),
- status: RegistrationStatusEnumType.ACCEPTED
+ status: RegistrationStatusEnumType.ACCEPTED,
}
}
}
- private initializeOcppServices (): void {
- const ocppVersion = this.stationInfo?.ocppVersion
- switch (ocppVersion) {
- case OCPPVersion.VERSION_16:
- this.ocppIncomingRequestService =
- OCPP16IncomingRequestService.getInstance<OCPP16IncomingRequestService>()
- this.ocppRequestService = OCPP16RequestService.getInstance<OCPP16RequestService>(
- OCPP16ResponseService.getInstance<OCPP16ResponseService>()
- )
- break
- case OCPPVersion.VERSION_20:
- case OCPPVersion.VERSION_201:
- this.ocppIncomingRequestService =
- OCPP20IncomingRequestService.getInstance<OCPP20IncomingRequestService>()
- this.ocppRequestService = OCPP20RequestService.getInstance<OCPP20RequestService>(
- OCPP20ResponseService.getInstance<OCPP20ResponseService>()
- )
- break
- default:
- this.handleUnsupportedVersion(ocppVersion)
- break
- }
- }
-
- private initializeOcppConfiguration (): void {
- if (getConfigurationKey(this, StandardParametersKey.HeartbeatInterval) == null) {
- addConfigurationKey(this, StandardParametersKey.HeartbeatInterval, '0')
- }
- if (getConfigurationKey(this, StandardParametersKey.HeartBeatInterval) == null) {
- addConfigurationKey(this, StandardParametersKey.HeartBeatInterval, '0', { visible: false })
- }
- if (
- this.stationInfo?.supervisionUrlOcppConfiguration === true &&
- isNotEmptyString(this.stationInfo.supervisionUrlOcppKey) &&
- getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey) == null
- ) {
- addConfigurationKey(
- this,
- this.stationInfo.supervisionUrlOcppKey,
- this.configuredSupervisionUrl.href,
- { reboot: true }
- )
- } else if (
- this.stationInfo?.supervisionUrlOcppConfiguration === false &&
- isNotEmptyString(this.stationInfo.supervisionUrlOcppKey) &&
- getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey) != null
- ) {
- deleteConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey, { save: false })
- }
- if (
- isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
- getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey) == null
- ) {
- addConfigurationKey(
- this,
- this.stationInfo.amperageLimitationOcppKey,
- // prettier-ignore
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- (this.stationInfo.maximumAmperage! * getAmperageLimitationUnitDivider(this.stationInfo)).toString()
- )
+ private initializeConnectorsFromTemplate (stationTemplate: ChargingStationTemplate): void {
+ if (stationTemplate.Connectors == null && isEmpty(this.connectors)) {
+ const errorMsg = `No already defined connectors and charging station information from template ${this.templateFile} with no connectors configuration defined`
+ logger.error(`${this.logPrefix()} ${errorMsg}`)
+ throw new BaseError(errorMsg)
}
- if (getConfigurationKey(this, StandardParametersKey.SupportedFeatureProfiles) == null) {
- addConfigurationKey(
- this,
- StandardParametersKey.SupportedFeatureProfiles,
- `${SupportedFeatureProfiles.Core},${SupportedFeatureProfiles.FirmwareManagement},${SupportedFeatureProfiles.LocalAuthListManagement},${SupportedFeatureProfiles.SmartCharging},${SupportedFeatureProfiles.RemoteTrigger}`
+ if (stationTemplate.Connectors?.[0] == null) {
+ logger.warn(
+ `${this.logPrefix()} Charging station information from template ${
+ this.templateFile
+ } with no connector id 0 configuration`
)
}
- addConfigurationKey(
- this,
- StandardParametersKey.NumberOfConnectors,
- this.getNumberOfConnectors().toString(),
- { readonly: true },
- { overwrite: true }
- )
- if (getConfigurationKey(this, StandardParametersKey.MeterValuesSampledData) == null) {
- addConfigurationKey(
- this,
- StandardParametersKey.MeterValuesSampledData,
- MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
+ if (stationTemplate.Connectors != null) {
+ const { configuredMaxConnectors, templateMaxAvailableConnectors, templateMaxConnectors } =
+ checkConnectorsConfiguration(stationTemplate, this.logPrefix(), this.templateFile)
+ const connectorsConfigHash = hash(
+ Constants.DEFAULT_HASH_ALGORITHM,
+ `${JSON.stringify(stationTemplate.Connectors)}${configuredMaxConnectors.toString()}`,
+ 'hex'
)
- }
- if (getConfigurationKey(this, StandardParametersKey.ConnectorPhaseRotation) == null) {
- const connectorsPhaseRotation: string[] = []
- if (this.hasEvses) {
- for (const evseStatus of this.evses.values()) {
- for (const connectorId of evseStatus.connectors.keys()) {
- connectorsPhaseRotation.push(
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- getPhaseRotationValue(connectorId, this.getNumberOfPhases())!
+ const connectorsConfigChanged =
+ this.connectors.size !== 0 && this.connectorsConfigurationHash !== connectorsConfigHash
+ if (isEmpty(this.connectors) || connectorsConfigChanged) {
+ connectorsConfigChanged && this.connectors.clear()
+ this.connectorsConfigurationHash = connectorsConfigHash
+ if (templateMaxConnectors > 0) {
+ for (let connectorId = 0; connectorId <= configuredMaxConnectors; connectorId++) {
+ if (
+ connectorId === 0 &&
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ (stationTemplate.Connectors[connectorId] == null ||
+ !this.getUseConnectorId0(stationTemplate))
+ ) {
+ continue
+ }
+ const templateConnectorId =
+ connectorId > 0 && stationTemplate.randomConnectors === true
+ ? randomInt(1, templateMaxAvailableConnectors)
+ : connectorId
+ const connectorStatus = stationTemplate.Connectors[templateConnectorId]
+ checkStationInfoConnectorStatus(
+ templateConnectorId,
+ connectorStatus,
+ this.logPrefix(),
+ this.templateFile
)
+ this.connectors.set(connectorId, clone<ConnectorStatus>(connectorStatus))
}
- }
- } else {
- for (const connectorId of this.connectors.keys()) {
- connectorsPhaseRotation.push(
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- getPhaseRotationValue(connectorId, this.getNumberOfPhases())!
+ initializeConnectorsMapStatus(this.connectors, this.logPrefix())
+ this.saveConnectorsStatus()
+ } else {
+ logger.warn(
+ `${this.logPrefix()} Charging station information from template ${
+ this.templateFile
+ } with no connectors configuration defined, cannot create connectors`
)
}
}
- addConfigurationKey(
- this,
- StandardParametersKey.ConnectorPhaseRotation,
- connectorsPhaseRotation.toString()
- )
- }
- if (getConfigurationKey(this, StandardParametersKey.AuthorizeRemoteTxRequests) == null) {
- addConfigurationKey(this, StandardParametersKey.AuthorizeRemoteTxRequests, 'true')
- }
- if (
- getConfigurationKey(this, StandardParametersKey.LocalAuthListEnabled) == null &&
- hasFeatureProfile(this, SupportedFeatureProfiles.LocalAuthListManagement) === true
- ) {
- addConfigurationKey(this, StandardParametersKey.LocalAuthListEnabled, 'false')
- }
- if (getConfigurationKey(this, StandardParametersKey.ConnectionTimeOut) == null) {
- addConfigurationKey(
- this,
- StandardParametersKey.ConnectionTimeOut,
- Constants.DEFAULT_CONNECTION_TIMEOUT.toString()
+ } else {
+ logger.warn(
+ `${this.logPrefix()} Charging station information from template ${
+ this.templateFile
+ } with no connectors configuration defined, using already defined connectors`
)
}
- this.saveOcppConfiguration()
}
private initializeConnectorsOrEvsesFromFile (configuration: ChargingStationConfiguration): void {
if (configuration.connectorsStatus != null && configuration.evsesStatus == null) {
for (const [connectorId, connectorStatus] of configuration.connectorsStatus.entries()) {
- this.connectors.set(connectorId, clone<ConnectorStatus>(connectorStatus))
+ this.connectors.set(
+ connectorId,
+ prepareConnectorStatus(clone<ConnectorStatus>(connectorStatus))
+ )
}
} else if (configuration.evsesStatus != null && configuration.connectorsStatus == null) {
for (const [evseId, evseStatusConfiguration] of configuration.evsesStatus.entries()) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
evseStatusConfiguration.connectorsStatus!.map((connectorStatus, connectorId) => [
connectorId,
- connectorStatus
+ prepareConnectorStatus(connectorStatus),
])
- )
+ ),
})
}
} else if (configuration.evsesStatus != null && configuration.connectorsStatus != null) {
}
}
- private initializeConnectorsFromTemplate (stationTemplate: ChargingStationTemplate): void {
- if (stationTemplate.Connectors == null && this.connectors.size === 0) {
- const errorMsg = `No already defined connectors and charging station information from template ${this.templateFile} with no connectors configuration defined`
- logger.error(`${this.logPrefix()} ${errorMsg}`)
- throw new BaseError(errorMsg)
- }
- if (stationTemplate.Connectors?.[0] == null) {
- logger.warn(
- `${this.logPrefix()} Charging station information from template ${
- this.templateFile
- } with no connector id 0 configuration`
- )
- }
- if (stationTemplate.Connectors != null) {
- const { configuredMaxConnectors, templateMaxConnectors, templateMaxAvailableConnectors } =
- checkConnectorsConfiguration(stationTemplate, this.logPrefix(), this.templateFile)
- const connectorsConfigHash = createHash(Constants.DEFAULT_HASH_ALGORITHM)
- .update(
- `${JSON.stringify(stationTemplate.Connectors)}${configuredMaxConnectors.toString()}`
- )
- .digest('hex')
- const connectorsConfigChanged =
- this.connectors.size !== 0 && this.connectorsConfigurationHash !== connectorsConfigHash
- if (this.connectors.size === 0 || connectorsConfigChanged) {
- connectorsConfigChanged && this.connectors.clear()
- this.connectorsConfigurationHash = connectorsConfigHash
- if (templateMaxConnectors > 0) {
- for (let connectorId = 0; connectorId <= configuredMaxConnectors; connectorId++) {
- if (
- connectorId === 0 &&
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
- (stationTemplate.Connectors[connectorId] == null ||
- !this.getUseConnectorId0(stationTemplate))
- ) {
- continue
- }
- const templateConnectorId =
- connectorId > 0 && stationTemplate.randomConnectors === true
- ? randomInt(1, templateMaxAvailableConnectors)
- : connectorId
- const connectorStatus = stationTemplate.Connectors[templateConnectorId]
- checkStationInfoConnectorStatus(
- templateConnectorId,
- connectorStatus,
- this.logPrefix(),
- this.templateFile
- )
- this.connectors.set(connectorId, clone<ConnectorStatus>(connectorStatus))
- }
- initializeConnectorsMapStatus(this.connectors, this.logPrefix())
- this.saveConnectorsStatus()
- } else {
- logger.warn(
- `${this.logPrefix()} Charging station information from template ${
- this.templateFile
- } with no connectors configuration defined, cannot create connectors`
- )
- }
- }
- } else {
- logger.warn(
- `${this.logPrefix()} Charging station information from template ${
- this.templateFile
- } with no connectors configuration defined, using already defined connectors`
- )
- }
- }
-
private initializeEvsesFromTemplate (stationTemplate: ChargingStationTemplate): void {
- if (stationTemplate.Evses == null && this.evses.size === 0) {
+ if (stationTemplate.Evses == null && isEmpty(this.evses)) {
const errorMsg = `No already defined evses and charging station information from template ${this.templateFile} with no evses configuration defined`
logger.error(`${this.logPrefix()} ${errorMsg}`)
throw new BaseError(errorMsg)
)
}
if (stationTemplate.Evses != null) {
- const evsesConfigHash = createHash(Constants.DEFAULT_HASH_ALGORITHM)
- .update(JSON.stringify(stationTemplate.Evses))
- .digest('hex')
+ const evsesConfigHash = hash(
+ Constants.DEFAULT_HASH_ALGORITHM,
+ JSON.stringify(stationTemplate.Evses),
+ 'hex'
+ )
const evsesConfigChanged =
this.evses.size !== 0 && this.evsesConfigurationHash !== evsesConfigHash
- if (this.evses.size === 0 || evsesConfigChanged) {
+ if (isEmpty(this.evses) || evsesConfigChanged) {
evsesConfigChanged && this.evses.clear()
this.evsesConfigurationHash = evsesConfigHash
const templateMaxEvses = getMaxNumberOfEvses(stationTemplate.Evses)
for (const evseKey in stationTemplate.Evses) {
const evseId = convertToInt(evseKey)
this.evses.set(evseId, {
+ availability: AvailabilityType.Operative,
connectors: buildConnectorsMap(
stationTemplate.Evses[evseKey].Connectors,
this.logPrefix(),
this.templateFile
),
- availability: AvailabilityType.Operative
})
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
initializeConnectorsMapStatus(this.evses.get(evseId)!.connectors, this.logPrefix())
}
}
- private getConfigurationFromFile (): ChargingStationConfiguration | undefined {
- let configuration: ChargingStationConfiguration | undefined
- if (isNotEmptyString(this.configurationFile) && existsSync(this.configurationFile)) {
- try {
- if (this.sharedLRUCache.hasChargingStationConfiguration(this.configurationFileHash)) {
- configuration = this.sharedLRUCache.getChargingStationConfiguration(
- this.configurationFileHash
- )
- } else {
- const measureId = `${FileType.ChargingStationConfiguration} read`
- const beginId = PerformanceStatistics.beginMeasure(measureId)
- configuration = JSON.parse(
- readFileSync(this.configurationFile, 'utf8')
- ) as ChargingStationConfiguration
- PerformanceStatistics.endMeasure(measureId, beginId)
- this.sharedLRUCache.setChargingStationConfiguration(configuration)
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.configurationFileHash = configuration.configurationHash!
- }
- } catch (error) {
- handleFileException(
- this.configurationFile,
- FileType.ChargingStationConfiguration,
- error as NodeJS.ErrnoException,
- this.logPrefix()
- )
- }
+ private initializeOcppConfiguration (): void {
+ if (getConfigurationKey(this, StandardParametersKey.HeartbeatInterval) == null) {
+ addConfigurationKey(this, StandardParametersKey.HeartbeatInterval, '0')
}
- return configuration
- }
-
- private saveAutomaticTransactionGeneratorConfiguration (): void {
- if (this.stationInfo?.automaticTransactionGeneratorPersistentConfiguration === true) {
- this.saveConfiguration()
+ if (getConfigurationKey(this, StandardParametersKey.HeartBeatInterval) == null) {
+ addConfigurationKey(this, StandardParametersKey.HeartBeatInterval, '0', {
+ visible: false,
+ })
}
- }
-
- private saveConnectorsStatus (): void {
- this.saveConfiguration()
- }
-
- private saveEvsesStatus (): void {
- this.saveConfiguration()
- }
-
- private saveConfiguration (): void {
- if (isNotEmptyString(this.configurationFile)) {
- try {
- if (!existsSync(dirname(this.configurationFile))) {
- mkdirSync(dirname(this.configurationFile), { recursive: true })
- }
- const configurationFromFile = this.getConfigurationFromFile()
- let configurationData: ChargingStationConfiguration =
- configurationFromFile != null
- ? clone<ChargingStationConfiguration>(configurationFromFile)
- : {}
- if (this.stationInfo?.stationInfoPersistentConfiguration === true) {
- configurationData.stationInfo = this.stationInfo
- } else {
- delete configurationData.stationInfo
- }
- if (
- this.stationInfo?.ocppPersistentConfiguration === true &&
- Array.isArray(this.ocppConfiguration?.configurationKey)
- ) {
- configurationData.configurationKey = this.ocppConfiguration.configurationKey
- } else {
- delete configurationData.configurationKey
- }
- configurationData = mergeDeepRight(
- configurationData,
- buildChargingStationAutomaticTransactionGeneratorConfiguration(this)
- )
- if (this.stationInfo?.automaticTransactionGeneratorPersistentConfiguration !== true) {
- delete configurationData.automaticTransactionGenerator
- }
- if (this.connectors.size > 0) {
- configurationData.connectorsStatus = buildConnectorsStatus(this)
- } else {
- delete configurationData.connectorsStatus
- }
- if (this.evses.size > 0) {
- configurationData.evsesStatus = buildEvsesStatus(this)
- } else {
- delete configurationData.evsesStatus
- }
- delete configurationData.configurationHash
- const configurationHash = createHash(Constants.DEFAULT_HASH_ALGORITHM)
- .update(
- JSON.stringify({
- stationInfo: configurationData.stationInfo,
- configurationKey: configurationData.configurationKey,
- automaticTransactionGenerator: configurationData.automaticTransactionGenerator,
- ...(this.connectors.size > 0 && {
- connectorsStatus: configurationData.connectorsStatus
- }),
- ...(this.evses.size > 0 && { evsesStatus: configurationData.evsesStatus })
- } satisfies ChargingStationConfiguration)
- )
- .digest('hex')
- if (this.configurationFileHash !== configurationHash) {
- AsyncLock.runExclusive(AsyncLockType.configuration, () => {
- configurationData.configurationHash = configurationHash
- const measureId = `${FileType.ChargingStationConfiguration} write`
- const beginId = PerformanceStatistics.beginMeasure(measureId)
- writeFileSync(
- this.configurationFile,
- JSON.stringify(configurationData, undefined, 2),
- 'utf8'
- )
- PerformanceStatistics.endMeasure(measureId, beginId)
- this.sharedLRUCache.deleteChargingStationConfiguration(this.configurationFileHash)
- this.sharedLRUCache.setChargingStationConfiguration(configurationData)
- this.configurationFileHash = configurationHash
- }).catch((error: unknown) => {
- handleFileException(
- this.configurationFile,
- FileType.ChargingStationConfiguration,
- error as NodeJS.ErrnoException,
- this.logPrefix()
- )
- })
- } else {
- logger.debug(
- `${this.logPrefix()} Not saving unchanged charging station configuration file ${
- this.configurationFile
- }`
- )
- }
- } catch (error) {
- handleFileException(
- this.configurationFile,
- FileType.ChargingStationConfiguration,
- error as NodeJS.ErrnoException,
- this.logPrefix()
- )
- }
- } else {
- logger.error(
- `${this.logPrefix()} Trying to save charging station configuration to undefined configuration file`
+ if (
+ this.stationInfo?.supervisionUrlOcppConfiguration === true &&
+ isNotEmptyString(this.stationInfo.supervisionUrlOcppKey) &&
+ getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey) == null
+ ) {
+ addConfigurationKey(
+ this,
+ this.stationInfo.supervisionUrlOcppKey,
+ this.configuredSupervisionUrl.href,
+ { reboot: true }
)
+ } else if (
+ this.stationInfo?.supervisionUrlOcppConfiguration === false &&
+ isNotEmptyString(this.stationInfo.supervisionUrlOcppKey) &&
+ getConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey) != null
+ ) {
+ deleteConfigurationKey(this, this.stationInfo.supervisionUrlOcppKey, {
+ save: false,
+ })
}
- }
-
- private getOcppConfigurationFromTemplate (): ChargingStationOcppConfiguration | undefined {
- return this.getTemplateFromFile()?.Configuration
- }
-
- private getOcppConfigurationFromFile (
- ocppPersistentConfiguration?: boolean
- ): ChargingStationOcppConfiguration | undefined {
- const configurationKey = this.getConfigurationFromFile()?.configurationKey
- if (ocppPersistentConfiguration === true && Array.isArray(configurationKey)) {
- return { configurationKey }
+ if (
+ isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
+ getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey) == null
+ ) {
+ addConfigurationKey(
+ this,
+ this.stationInfo.amperageLimitationOcppKey,
+ // prettier-ignore
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ (this.stationInfo.maximumAmperage! * getAmperageLimitationUnitDivider(this.stationInfo)).toString()
+ )
}
- return undefined
- }
-
- private getOcppConfiguration (
- ocppPersistentConfiguration: boolean | undefined = this.stationInfo?.ocppPersistentConfiguration
- ): ChargingStationOcppConfiguration | undefined {
- let ocppConfiguration: ChargingStationOcppConfiguration | undefined =
- this.getOcppConfigurationFromFile(ocppPersistentConfiguration)
- if (ocppConfiguration == null) {
- ocppConfiguration = this.getOcppConfigurationFromTemplate()
+ if (getConfigurationKey(this, StandardParametersKey.SupportedFeatureProfiles) == null) {
+ addConfigurationKey(
+ this,
+ StandardParametersKey.SupportedFeatureProfiles,
+ `${SupportedFeatureProfiles.Core},${SupportedFeatureProfiles.FirmwareManagement},${SupportedFeatureProfiles.LocalAuthListManagement},${SupportedFeatureProfiles.SmartCharging},${SupportedFeatureProfiles.RemoteTrigger}`
+ )
}
- return ocppConfiguration
- }
-
- private async onOpen (): Promise<void> {
- if (this.isWebSocketConnectionOpened()) {
- this.emit(ChargingStationEvents.updated)
- logger.info(
- `${this.logPrefix()} Connection to OCPP server through ${this.wsConnectionUrl.href} succeeded`
+ addConfigurationKey(
+ this,
+ StandardParametersKey.NumberOfConnectors,
+ this.getNumberOfConnectors().toString(),
+ { readonly: true },
+ { overwrite: true }
+ )
+ if (getConfigurationKey(this, StandardParametersKey.MeterValuesSampledData) == null) {
+ addConfigurationKey(
+ this,
+ StandardParametersKey.MeterValuesSampledData,
+ MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
)
- let registrationRetryCount = 0
- if (!this.isRegistered()) {
- // Send BootNotification
- do {
- this.bootNotificationResponse = await this.ocppRequestService.requestHandler<
- BootNotificationRequest,
- BootNotificationResponse
- >(this, RequestCommand.BOOT_NOTIFICATION, this.bootNotificationRequest, {
- skipBufferingOnError: true
- })
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
- if (this.bootNotificationResponse?.currentTime != null) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.bootNotificationResponse.currentTime = convertToDate(
- this.bootNotificationResponse.currentTime
- )!
- }
- if (!this.isRegistered()) {
- this.stationInfo?.registrationMaxRetries !== -1 && ++registrationRetryCount
- await sleep(
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
- this.bootNotificationResponse?.interval != null
- ? secondsToMilliseconds(this.bootNotificationResponse.interval)
- : Constants.DEFAULT_BOOT_NOTIFICATION_INTERVAL
+ }
+ if (getConfigurationKey(this, StandardParametersKey.ConnectorPhaseRotation) == null) {
+ const connectorsPhaseRotation: string[] = []
+ if (this.hasEvses) {
+ for (const evseStatus of this.evses.values()) {
+ for (const connectorId of evseStatus.connectors.keys()) {
+ connectorsPhaseRotation.push(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ getPhaseRotationValue(connectorId, this.getNumberOfPhases())!
)
}
- } while (
- !this.isRegistered() &&
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- (registrationRetryCount <= this.stationInfo!.registrationMaxRetries! ||
- this.stationInfo?.registrationMaxRetries === -1)
- )
- }
- if (this.isRegistered()) {
- this.emit(ChargingStationEvents.registered)
- if (this.inAcceptedState()) {
- this.emit(ChargingStationEvents.accepted)
}
} else {
- if (this.inRejectedState()) {
- this.emit(ChargingStationEvents.rejected)
+ for (const connectorId of this.connectors.keys()) {
+ connectorsPhaseRotation.push(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ getPhaseRotationValue(connectorId, this.getNumberOfPhases())!
+ )
}
- logger.error(
- `${this.logPrefix()} Registration failure: maximum retries reached (${registrationRetryCount}) or retry disabled (${
- this.stationInfo?.registrationMaxRetries
- })`
- )
}
- this.wsConnectionRetryCount = 0
- this.emit(ChargingStationEvents.updated)
- } else {
- logger.warn(
- `${this.logPrefix()} Connection to OCPP server through ${this.wsConnectionUrl.href} failed`
+ addConfigurationKey(
+ this,
+ StandardParametersKey.ConnectorPhaseRotation,
+ connectorsPhaseRotation.toString()
)
}
+ if (getConfigurationKey(this, StandardParametersKey.AuthorizeRemoteTxRequests) == null) {
+ addConfigurationKey(this, StandardParametersKey.AuthorizeRemoteTxRequests, 'true')
+ }
+ if (
+ getConfigurationKey(this, StandardParametersKey.LocalAuthListEnabled) == null &&
+ hasFeatureProfile(this, SupportedFeatureProfiles.LocalAuthListManagement) === true
+ ) {
+ addConfigurationKey(this, StandardParametersKey.LocalAuthListEnabled, 'false')
+ }
+ if (getConfigurationKey(this, StandardParametersKey.ConnectionTimeOut) == null) {
+ addConfigurationKey(
+ this,
+ StandardParametersKey.ConnectionTimeOut,
+ Constants.DEFAULT_CONNECTION_TIMEOUT.toString()
+ )
+ }
+ this.saveOcppConfiguration()
+ }
+
+ private initializeOcppServices (): void {
+ const ocppVersion = this.stationInfo?.ocppVersion
+ switch (ocppVersion) {
+ case OCPPVersion.VERSION_16:
+ this.ocppIncomingRequestService =
+ OCPP16IncomingRequestService.getInstance<OCPP16IncomingRequestService>()
+ this.ocppRequestService = OCPP16RequestService.getInstance<OCPP16RequestService>(
+ OCPP16ResponseService.getInstance<OCPP16ResponseService>()
+ )
+ break
+ case OCPPVersion.VERSION_20:
+ case OCPPVersion.VERSION_201:
+ this.ocppIncomingRequestService =
+ OCPP20IncomingRequestService.getInstance<OCPP20IncomingRequestService>()
+ this.ocppRequestService = OCPP20RequestService.getInstance<OCPP20RequestService>(
+ OCPP20ResponseService.getInstance<OCPP20ResponseService>()
+ )
+ break
+ default:
+ this.handleUnsupportedVersion(ocppVersion)
+ break
+ }
+ }
+
+ private internalStopMessageSequence (): void {
+ // Stop WebSocket ping
+ this.stopWebSocketPing()
+ // Stop heartbeat
+ this.stopHeartbeat()
+ // Stop the ATG
+ if (this.automaticTransactionGenerator?.started === true) {
+ this.stopAutomaticTransactionGenerator()
+ }
}
private onClose (code: WebSocketCloseEventStatusCode, reason: Buffer): void {
this.emit(ChargingStationEvents.updated)
switch (code) {
// Normal close
- case WebSocketCloseEventStatusCode.CLOSE_NORMAL:
case WebSocketCloseEventStatusCode.CLOSE_NO_STATUS:
+ case WebSocketCloseEventStatusCode.CLOSE_NORMAL:
logger.info(
`${this.logPrefix()} WebSocket normally closed with status '${getWebSocketCloseEventStatusString(
code
this.reconnect()
.then(() => {
this.emit(ChargingStationEvents.updated)
+ return undefined
})
.catch((error: unknown) =>
logger.error(`${this.logPrefix()} Error while reconnecting:`, error)
}
}
- private getCachedRequest (
- messageType: MessageType | undefined,
- messageId: string
- ): CachedRequest | undefined {
- const cachedRequest = this.requests.get(messageId)
- if (Array.isArray(cachedRequest)) {
- return cachedRequest
- }
- throw new OCPPError(
- ErrorType.PROTOCOL_ERROR,
- `Cached request for message id ${messageId} ${getMessageTypeString(
- messageType
- )} is not an array`,
- undefined,
- cachedRequest
- )
- }
-
- private async handleIncomingMessage (request: IncomingRequest): Promise<void> {
- const [messageType, messageId, commandName, commandPayload] = request
- if (this.stationInfo?.enableStatistics === true) {
- this.performanceStatistics?.addRequestStatistic(commandName, messageType)
- }
- logger.debug(
- `${this.logPrefix()} << Command '${commandName}' received request payload: ${JSON.stringify(
- request
- )}`
- )
- // Process the message
- await this.ocppIncomingRequestService.incomingRequestHandler(
- this,
- messageId,
- commandName,
- commandPayload
- )
- this.emit(ChargingStationEvents.updated)
- }
-
- private handleResponseMessage (response: Response): void {
- const [messageType, messageId, commandPayload] = response
- if (!this.requests.has(messageId)) {
- // Error
- throw new OCPPError(
- ErrorType.INTERNAL_ERROR,
- `Response for unknown message id ${messageId}`,
- undefined,
- commandPayload
- )
- }
- // Respond
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const [responseCallback, , requestCommandName, requestPayload] = this.getCachedRequest(
- messageType,
- messageId
- )!
- logger.debug(
- `${this.logPrefix()} << Command '${requestCommandName}' received response payload: ${JSON.stringify(
- response
- )}`
- )
- responseCallback(commandPayload, requestPayload)
- }
-
- private handleErrorMessage (errorResponse: ErrorResponse): void {
- const [messageType, messageId, errorType, errorMessage, errorDetails] = errorResponse
- if (!this.requests.has(messageId)) {
- // Error
- throw new OCPPError(
- ErrorType.INTERNAL_ERROR,
- `Error response for unknown message id ${messageId}`,
- undefined,
- { errorType, errorMessage, errorDetails }
- )
- }
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const [, errorCallback, requestCommandName] = this.getCachedRequest(messageType, messageId)!
- logger.debug(
- `${this.logPrefix()} << Command '${requestCommandName}' received error response payload: ${JSON.stringify(
- errorResponse
- )}`
- )
- errorCallback(new OCPPError(errorType, errorMessage, requestCommandName, errorDetails))
+ private onError (error: WSError): void {
+ this.closeWSConnection()
+ logger.error(`${this.logPrefix()} WebSocket error:`, error)
}
private async onMessage (data: RawData): Promise<void> {
- let request: IncomingRequest | Response | ErrorResponse | undefined
+ let request: ErrorResponse | IncomingRequest | Response | undefined
let messageType: MessageType | undefined
let errorMsg: string
try {
// eslint-disable-next-line @typescript-eslint/no-base-to-string
- request = JSON.parse(data.toString()) as IncomingRequest | Response | ErrorResponse
+ request = JSON.parse(data.toString()) as ErrorResponse | IncomingRequest | Response
if (Array.isArray(request)) {
- [messageType] = request
+ ;[messageType] = request
// Check the type of message
switch (messageType) {
+ // Error Message
+ case MessageType.CALL_ERROR_MESSAGE:
+ this.handleErrorMessage(request as ErrorResponse)
+ break
// Incoming Message
case MessageType.CALL_MESSAGE:
await this.handleIncomingMessage(request as IncomingRequest)
case MessageType.CALL_RESULT_MESSAGE:
this.handleResponseMessage(request as Response)
break
- // Error Message
- case MessageType.CALL_ERROR_MESSAGE:
- this.handleErrorMessage(request as ErrorResponse)
- break
// Unknown Message
default:
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
'Incoming message is not an array',
undefined,
{
- request
+ request,
}
)
}
} catch (error) {
if (!Array.isArray(request)) {
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
logger.error(`${this.logPrefix()} Incoming message '${request}' parsing error:`, error)
return
}
let commandName: IncomingRequestCommand | undefined
- let requestCommandName: RequestCommand | IncomingRequestCommand | undefined
+ let requestCommandName: IncomingRequestCommand | RequestCommand | undefined
let errorCallback: ErrorCallback
const [, messageId] = request
switch (messageType) {
- case MessageType.CALL_MESSAGE:
- [, , commandName] = request as IncomingRequest
- // Send error
- await this.ocppRequestService.sendError(this, messageId, error as OCPPError, commandName)
- break
- case MessageType.CALL_RESULT_MESSAGE:
case MessageType.CALL_ERROR_MESSAGE:
+ case MessageType.CALL_RESULT_MESSAGE:
if (this.requests.has(messageId)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- [, errorCallback, requestCommandName] = this.getCachedRequest(messageType, messageId)!
+ ;[, errorCallback, requestCommandName] = this.getCachedRequest(messageType, messageId)!
// Reject the deferred promise in case of error at response handling (rejecting an already fulfilled promise is a no-op)
errorCallback(error as OCPPError, false)
} else {
this.requests.delete(messageId)
}
break
+ case MessageType.CALL_MESSAGE:
+ ;[, , commandName] = request as IncomingRequest
+ // Send error
+ await this.ocppRequestService.sendError(this, messageId, error as OCPPError, commandName)
+ break
}
if (!(error instanceof OCPPError)) {
logger.warn(
- `${this.logPrefix()} Error thrown at incoming OCPP command '${
+ `${this.logPrefix()} Error thrown at incoming OCPP command ${
commandName ?? requestCommandName ?? Constants.UNKNOWN_OCPP_COMMAND
// eslint-disable-next-line @typescript-eslint/no-base-to-string
- }' message '${data.toString()}' handling is not an OCPPError:`,
+ } message '${data.toString()}' handling is not an OCPPError:`,
error
)
}
// eslint-disable-next-line @typescript-eslint/no-base-to-string
}' message '${data.toString()}'${
this.requests.has(messageId)
- ? ` matching cached request '${JSON.stringify(this.getCachedRequest(messageType, messageId))}'`
+ ? ` matching cached request '${JSON.stringify(
+ this.getCachedRequest(messageType, messageId)
+ )}'`
: ''
} processing error:`,
error
}
}
+ private async onOpen (): Promise<void> {
+ if (this.isWebSocketConnectionOpened()) {
+ this.emit(ChargingStationEvents.connected)
+ this.emit(ChargingStationEvents.updated)
+ logger.info(
+ `${this.logPrefix()} Connection to OCPP server through ${
+ this.wsConnectionUrl.href
+ } succeeded`
+ )
+ let registrationRetryCount = 0
+ if (!this.inAcceptedState()) {
+ // Send BootNotification
+ do {
+ await this.ocppRequestService.requestHandler<
+ BootNotificationRequest,
+ BootNotificationResponse
+ >(this, RequestCommand.BOOT_NOTIFICATION, this.bootNotificationRequest, {
+ skipBufferingOnError: true,
+ })
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.bootNotificationResponse!.currentTime = convertToDate(
+ this.bootNotificationResponse?.currentTime
+ )!
+ if (!this.inAcceptedState()) {
+ ++registrationRetryCount
+ await sleep(
+ exponentialDelay(
+ registrationRetryCount,
+ this.bootNotificationResponse?.interval != null
+ ? secondsToMilliseconds(this.bootNotificationResponse.interval)
+ : Constants.DEFAULT_BOOT_NOTIFICATION_INTERVAL
+ )
+ )
+ }
+ } while (
+ !this.inAcceptedState() &&
+ (this.stationInfo?.registrationMaxRetries === -1 ||
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ registrationRetryCount <= this.stationInfo!.registrationMaxRetries!)
+ )
+ }
+ if (!this.inAcceptedState()) {
+ logger.error(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `${this.logPrefix()} Registration failure: maximum retries reached (${registrationRetryCount.toString()}) or retry disabled (${this.stationInfo?.registrationMaxRetries?.toString()})`
+ )
+ }
+ this.emit(ChargingStationEvents.updated)
+ } else {
+ logger.warn(
+ `${this.logPrefix()} Connection to OCPP server through ${this.wsConnectionUrl.href} failed`
+ )
+ }
+ }
+
private onPing (): void {
logger.debug(`${this.logPrefix()} Received a WS ping (rfc6455) from the server`)
}
logger.debug(`${this.logPrefix()} Received a WS pong (rfc6455) from the server`)
}
- private onError (error: WSError): void {
- this.closeWSConnection()
- logger.error(`${this.logPrefix()} WebSocket error:`, error)
- }
-
- private getEnergyActiveImportRegister (
- connectorStatus: ConnectorStatus | undefined,
- rounded = false
- ): number {
- if (this.stationInfo?.meteringPerTransaction === true) {
- return (
- (rounded
- ? connectorStatus?.transactionEnergyActiveImportRegisterValue != null
- ? Math.round(connectorStatus.transactionEnergyActiveImportRegisterValue)
- : undefined
- : connectorStatus?.transactionEnergyActiveImportRegisterValue) ?? 0
+ private async reconnect (): Promise<void> {
+ if (
+ this.stationInfo?.autoReconnectMaxRetries === -1 ||
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.wsConnectionRetryCount < this.stationInfo!.autoReconnectMaxRetries!
+ ) {
+ ++this.wsConnectionRetryCount
+ const reconnectDelay =
+ this.stationInfo?.reconnectExponentialDelay === true
+ ? exponentialDelay(this.wsConnectionRetryCount)
+ : secondsToMilliseconds(this.getConnectionTimeout())
+ const reconnectDelayWithdraw = 1000
+ const reconnectTimeout =
+ reconnectDelay - reconnectDelayWithdraw > 0 ? reconnectDelay - reconnectDelayWithdraw : 0
+ logger.error(
+ `${this.logPrefix()} WebSocket connection retry in ${roundTo(
+ reconnectDelay,
+ 2
+ ).toString()}ms, timeout ${reconnectTimeout.toString()}ms`
+ )
+ await sleep(reconnectDelay)
+ logger.error(
+ `${this.logPrefix()} WebSocket connection retry #${this.wsConnectionRetryCount.toString()}`
+ )
+ this.openWSConnection(
+ {
+ handshakeTimeout: reconnectTimeout,
+ },
+ { closeOpened: true }
+ )
+ } else if (this.stationInfo?.autoReconnectMaxRetries !== -1) {
+ logger.error(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `${this.logPrefix()} WebSocket connection retries failure: maximum retries reached (${this.wsConnectionRetryCount.toString()}) or retries disabled (${this.stationInfo?.autoReconnectMaxRetries?.toString()})`
)
}
- return (
- (rounded
- ? connectorStatus?.energyActiveImportRegisterValue != null
- ? Math.round(connectorStatus.energyActiveImportRegisterValue)
- : undefined
- : connectorStatus?.energyActiveImportRegisterValue) ?? 0
- )
}
- private getUseConnectorId0 (stationTemplate?: ChargingStationTemplate): boolean {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return stationTemplate?.useConnectorId0 ?? Constants.DEFAULT_STATION_INFO.useConnectorId0!
+ private saveAutomaticTransactionGeneratorConfiguration (): void {
+ if (this.stationInfo?.automaticTransactionGeneratorPersistentConfiguration === true) {
+ this.saveConfiguration()
+ }
}
- private async stopRunningTransactions (reason?: StopTransactionReason): Promise<void> {
- if (this.hasEvses) {
- for (const [evseId, evseStatus] of this.evses) {
- if (evseId === 0) {
- continue
+ private saveConfiguration (): void {
+ if (isNotEmptyString(this.configurationFile)) {
+ try {
+ if (!existsSync(dirname(this.configurationFile))) {
+ mkdirSync(dirname(this.configurationFile), { recursive: true })
}
- for (const [connectorId, connectorStatus] of evseStatus.connectors) {
- if (connectorStatus.transactionStarted === true) {
- await this.stopTransactionOnConnector(connectorId, reason)
- }
+ const configurationFromFile = this.getConfigurationFromFile()
+ let configurationData: ChargingStationConfiguration =
+ configurationFromFile != null
+ ? clone<ChargingStationConfiguration>(configurationFromFile)
+ : {}
+ if (this.stationInfo?.stationInfoPersistentConfiguration === true) {
+ configurationData.stationInfo = this.stationInfo
+ } else {
+ delete configurationData.stationInfo
+ }
+ if (
+ this.stationInfo?.ocppPersistentConfiguration === true &&
+ Array.isArray(this.ocppConfiguration?.configurationKey)
+ ) {
+ configurationData.configurationKey = this.ocppConfiguration.configurationKey
+ } else {
+ delete configurationData.configurationKey
+ }
+ configurationData = mergeDeepRight<ChargingStationConfiguration>(
+ configurationData,
+ buildChargingStationAutomaticTransactionGeneratorConfiguration(
+ this
+ ) as Partial<ChargingStationConfiguration>
+ )
+ if (this.stationInfo?.automaticTransactionGeneratorPersistentConfiguration !== true) {
+ delete configurationData.automaticTransactionGenerator
+ }
+ if (this.connectors.size > 0) {
+ configurationData.connectorsStatus = buildConnectorsStatus(this)
+ } else {
+ delete configurationData.connectorsStatus
+ }
+ if (this.evses.size > 0) {
+ configurationData.evsesStatus = buildEvsesStatus(this)
+ } else {
+ delete configurationData.evsesStatus
+ }
+ delete configurationData.configurationHash
+ const configurationHash = hash(
+ Constants.DEFAULT_HASH_ALGORITHM,
+ JSON.stringify({
+ automaticTransactionGenerator: configurationData.automaticTransactionGenerator,
+ configurationKey: configurationData.configurationKey,
+ stationInfo: configurationData.stationInfo,
+ ...(this.connectors.size > 0 && {
+ connectorsStatus: configurationData.connectorsStatus,
+ }),
+ ...(this.evses.size > 0 && {
+ evsesStatus: configurationData.evsesStatus,
+ }),
+ } satisfies ChargingStationConfiguration),
+ 'hex'
+ )
+ if (this.configurationFileHash !== configurationHash) {
+ AsyncLock.runExclusive(AsyncLockType.configuration, () => {
+ configurationData.configurationHash = configurationHash
+ const measureId = `${FileType.ChargingStationConfiguration} write`
+ const beginId = PerformanceStatistics.beginMeasure(measureId)
+ writeFileSync(
+ this.configurationFile,
+ JSON.stringify(configurationData, undefined, 2),
+ 'utf8'
+ )
+ PerformanceStatistics.endMeasure(measureId, beginId)
+ this.sharedLRUCache.deleteChargingStationConfiguration(this.configurationFileHash)
+ this.sharedLRUCache.setChargingStationConfiguration(configurationData)
+ this.configurationFileHash = configurationHash
+ }).catch((error: unknown) => {
+ handleFileException(
+ this.configurationFile,
+ FileType.ChargingStationConfiguration,
+ error as NodeJS.ErrnoException,
+ this.logPrefix()
+ )
+ })
+ } else {
+ logger.debug(
+ `${this.logPrefix()} Not saving unchanged charging station configuration file ${
+ this.configurationFile
+ }`
+ )
}
+ } catch (error) {
+ handleFileException(
+ this.configurationFile,
+ FileType.ChargingStationConfiguration,
+ error as NodeJS.ErrnoException,
+ this.logPrefix()
+ )
}
} else {
- for (const connectorId of this.connectors.keys()) {
- if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) {
- await this.stopTransactionOnConnector(connectorId, reason)
- }
- }
- }
- }
-
- // 0 for disabling
- private getConnectionTimeout (): number {
- if (getConfigurationKey(this, StandardParametersKey.ConnectionTimeOut) != null) {
- return convertToInt(
- getConfigurationKey(this, StandardParametersKey.ConnectionTimeOut)?.value ??
- Constants.DEFAULT_CONNECTION_TIMEOUT
+ logger.error(
+ `${this.logPrefix()} Trying to save charging station configuration to undefined configuration file`
)
}
- return Constants.DEFAULT_CONNECTION_TIMEOUT
}
- private getPowerDivider (): number {
- let powerDivider = this.hasEvses ? this.getNumberOfEvses() : this.getNumberOfConnectors()
- if (this.stationInfo?.powerSharedByConnectors === true) {
- powerDivider = this.getNumberOfRunningTransactions()
- }
- return powerDivider
+ private saveConnectorsStatus (): void {
+ this.saveConfiguration()
}
- private getMaximumAmperage (stationInfo?: ChargingStationInfo): number | undefined {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const maximumPower = (stationInfo ?? this.stationInfo!).maximumPower!
- switch (this.getCurrentOutType(stationInfo)) {
- case CurrentType.AC:
- return ACElectricUtils.amperagePerPhaseFromPower(
- this.getNumberOfPhases(stationInfo),
- maximumPower / (this.hasEvses ? this.getNumberOfEvses() : this.getNumberOfConnectors()),
- this.getVoltageOut(stationInfo)
- )
- case CurrentType.DC:
- return DCElectricUtils.amperage(maximumPower, this.getVoltageOut(stationInfo))
- }
+ private saveEvsesStatus (): void {
+ this.saveConfiguration()
}
- private getCurrentOutType (stationInfo?: ChargingStationInfo): CurrentType {
- return (
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- (stationInfo ?? this.stationInfo!).currentOutType ??
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- Constants.DEFAULT_STATION_INFO.currentOutType!
- )
+ private saveStationInfo (): void {
+ if (this.stationInfo?.stationInfoPersistentConfiguration === true) {
+ this.saveConfiguration()
+ }
}
- private getVoltageOut (stationInfo?: ChargingStationInfo): Voltage {
- return (
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- (stationInfo ?? this.stationInfo!).voltageOut ??
- getDefaultVoltageOut(this.getCurrentOutType(stationInfo), this.logPrefix(), this.templateFile)
- )
+ private readonly sendMessageBuffer = (
+ onCompleteCallback: () => void,
+ messageIdx?: number
+ ): void => {
+ if (this.messageQueue.length > 0) {
+ const message = this.messageQueue[0]
+ let beginId: string | undefined
+ let commandName: RequestCommand | undefined
+ let parsedMessage: ErrorResponse | OutgoingRequest | Response
+ messageIdx ??= 0
+ try {
+ parsedMessage = JSON.parse(message) as ErrorResponse | OutgoingRequest | Response
+ } catch (error) {
+ logger.error(
+ `${this.logPrefix()} Error while parsing buffered OCPP message '${message}' to JSON:`,
+ error
+ )
+ this.messageQueue.shift()
+ this.sendMessageBuffer(onCompleteCallback, messageIdx)
+ return
+ }
+ const [messageType] = parsedMessage
+ const isRequest = messageType === MessageType.CALL_MESSAGE
+ if (isRequest) {
+ ;[, , commandName] = parsedMessage as OutgoingRequest
+ beginId = PerformanceStatistics.beginMeasure(commandName)
+ }
+ this.wsConnection?.send(message, (error?: Error) => {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ isRequest && PerformanceStatistics.endMeasure(commandName!, beginId!)
+ if (error == null) {
+ logger.debug(
+ `${this.logPrefix()} >> Buffered ${getMessageTypeString(messageType)} OCPP message sent '${message}'`
+ )
+ this.messageQueue.shift()
+ } else {
+ logger.error(
+ `${this.logPrefix()} >> Buffered ${getMessageTypeString(messageType)} OCPP message '${message}' send failed:`,
+ error
+ )
+ }
+ // eslint-disable-next-line promise/catch-or-return, @typescript-eslint/no-floating-promises, promise/no-promise-in-callback
+ sleep(exponentialDelay(messageIdx))
+ // eslint-disable-next-line promise/always-return
+ .then(() => {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++messageIdx!
+ this.sendMessageBuffer(onCompleteCallback, messageIdx)
+ })
+ })
+ } else {
+ onCompleteCallback()
+ }
}
- private getAmperageLimitation (): number | undefined {
- if (
- isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
- getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey) != null
- ) {
- return (
- convertToInt(getConfigurationKey(this, this.stationInfo.amperageLimitationOcppKey)?.value) /
- getAmperageLimitationUnitDivider(this.stationInfo)
- )
- }
+ private setIntervalFlushMessageBuffer (): void {
+ this.flushMessageBufferSetInterval ??= setInterval(() => {
+ if (this.isWebSocketConnectionOpened() && this.inAcceptedState()) {
+ this.flushMessageBuffer()
+ }
+ if (!this.isWebSocketConnectionOpened() || isEmpty(this.messageQueue)) {
+ this.clearIntervalFlushMessageBuffer()
+ }
+ }, Constants.DEFAULT_MESSAGE_BUFFER_FLUSH_INTERVAL)
}
private async startMessageSequence (ATGStopAbsoluteDuration?: boolean): Promise<void> {
if (this.stationInfo?.autoRegister === true) {
await this.ocppRequestService.requestHandler<
- BootNotificationRequest,
- BootNotificationResponse
+ BootNotificationRequest,
+ BootNotificationResponse
>(this, RequestCommand.BOOT_NOTIFICATION, this.bootNotificationRequest, {
- skipBufferingOnError: true
+ skipBufferingOnError: true,
})
}
// Start WebSocket ping
- this.startWebSocketPing()
+ if (this.wsPingSetInterval == null) {
+ this.startWebSocketPing()
+ }
// Start heartbeat
- this.startHeartbeat()
+ if (this.heartbeatSetInterval == null) {
+ this.startHeartbeat()
+ }
// Initialize connectors status
if (this.hasEvses) {
for (const [evseId, evseStatus] of this.evses) {
}
if (this.stationInfo?.firmwareStatus === FirmwareStatus.Installing) {
await this.ocppRequestService.requestHandler<
- FirmwareStatusNotificationRequest,
- FirmwareStatusNotificationResponse
+ FirmwareStatusNotificationRequest,
+ FirmwareStatusNotificationResponse
>(this, RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
- status: FirmwareStatus.Installed
+ status: FirmwareStatus.Installed,
})
this.stationInfo.firmwareStatus = FirmwareStatus.Installed
}
this.flushMessageBuffer()
}
- private internalStopMessageSequence (): void {
- // Stop WebSocket ping
- this.stopWebSocketPing()
- // Stop heartbeat
- this.stopHeartbeat()
- // Stop the ATG
- if (this.automaticTransactionGenerator?.started === true) {
- this.stopAutomaticTransactionGenerator()
+ private startWebSocketPing (): void {
+ const webSocketPingInterval = this.getWebSocketPingInterval()
+ if (webSocketPingInterval > 0 && this.wsPingSetInterval == null) {
+ this.wsPingSetInterval = setInterval(() => {
+ if (this.isWebSocketConnectionOpened()) {
+ this.wsConnection?.ping()
+ }
+ }, secondsToMilliseconds(webSocketPingInterval))
+ logger.info(
+ `${this.logPrefix()} WebSocket ping started every ${formatDurationSeconds(
+ webSocketPingInterval
+ )}`
+ )
+ } else if (this.wsPingSetInterval != null) {
+ logger.info(
+ `${this.logPrefix()} WebSocket ping already started every ${formatDurationSeconds(
+ webSocketPingInterval
+ )}`
+ )
+ } else {
+ logger.error(
+ `${this.logPrefix()} WebSocket ping interval set to ${webSocketPingInterval.toString()}, not starting the WebSocket ping`
+ )
+ }
+ }
+
+ private stopHeartbeat (): void {
+ if (this.heartbeatSetInterval != null) {
+ clearInterval(this.heartbeatSetInterval)
+ delete this.heartbeatSetInterval
}
}
): Promise<void> {
this.internalStopMessageSequence()
// Stop ongoing transactions
- stopTransactions === true && (await this.stopRunningTransactions(reason))
+ stopTransactions && (await this.stopRunningTransactions(reason))
if (this.hasEvses) {
for (const [evseId, evseStatus] of this.evses) {
if (evseId > 0) {
}
}
- private startWebSocketPing (): void {
- const webSocketPingInterval =
- getConfigurationKey(this, StandardParametersKey.WebSocketPingInterval) != null
- ? convertToInt(
- getConfigurationKey(this, StandardParametersKey.WebSocketPingInterval)?.value
- )
- : 0
- if (webSocketPingInterval > 0 && this.wsPingSetInterval == null) {
- this.wsPingSetInterval = setInterval(() => {
- if (this.isWebSocketConnectionOpened()) {
- this.wsConnection?.ping()
+ private async stopRunningTransactions (reason?: StopTransactionReason): Promise<void> {
+ if (this.hasEvses) {
+ for (const [evseId, evseStatus] of this.evses) {
+ if (evseId === 0) {
+ continue
}
- }, secondsToMilliseconds(webSocketPingInterval))
- logger.info(
- `${this.logPrefix()} WebSocket ping started every ${formatDurationSeconds(
- webSocketPingInterval
- )}`
- )
- } else if (this.wsPingSetInterval != null) {
- logger.info(
- `${this.logPrefix()} WebSocket ping already started every ${formatDurationSeconds(
- webSocketPingInterval
- )}`
- )
+ for (const [connectorId, connectorStatus] of evseStatus.connectors) {
+ if (connectorStatus.transactionStarted === true) {
+ await this.stopTransactionOnConnector(connectorId, reason)
+ }
+ }
+ }
} else {
- logger.error(
- `${this.logPrefix()} WebSocket ping interval set to ${webSocketPingInterval}, not starting the WebSocket ping`
- )
+ for (const connectorId of this.connectors.keys()) {
+ if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) {
+ await this.stopTransactionOnConnector(connectorId, reason)
+ }
+ }
}
}
}
}
- private getConfiguredSupervisionUrl (): URL {
- let configuredSupervisionUrl: string
- const supervisionUrls = this.stationInfo?.supervisionUrls ?? Configuration.getSupervisionUrls()
- if (isNotEmptyArray(supervisionUrls)) {
- let configuredSupervisionUrlIndex: number
- switch (Configuration.getSupervisionUrlDistribution()) {
- case SupervisionUrlDistribution.RANDOM:
- configuredSupervisionUrlIndex = Math.floor(secureRandom() * supervisionUrls.length)
- break
- case SupervisionUrlDistribution.ROUND_ROBIN:
- case SupervisionUrlDistribution.CHARGING_STATION_AFFINITY:
- default:
- !Object.values(SupervisionUrlDistribution).includes(
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- Configuration.getSupervisionUrlDistribution()!
- ) &&
- logger.warn(
- // eslint-disable-next-line @typescript-eslint/no-base-to-string
- `${this.logPrefix()} Unknown supervision url distribution '${Configuration.getSupervisionUrlDistribution()}' in configuration from values '${SupervisionUrlDistribution.toString()}', defaulting to '${
- SupervisionUrlDistribution.CHARGING_STATION_AFFINITY
- }'`
- )
- configuredSupervisionUrlIndex = (this.index - 1) % supervisionUrls.length
- break
- }
- configuredSupervisionUrl = supervisionUrls[configuredSupervisionUrlIndex]
- } else {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- configuredSupervisionUrl = supervisionUrls!
- }
- if (isNotEmptyString(configuredSupervisionUrl)) {
- return new URL(configuredSupervisionUrl)
- }
- const errorMsg = 'No supervision url(s) configured'
- logger.error(`${this.logPrefix()} ${errorMsg}`)
- throw new BaseError(errorMsg)
- }
-
- private stopHeartbeat (): void {
- if (this.heartbeatSetInterval != null) {
- clearInterval(this.heartbeatSetInterval)
- delete this.heartbeatSetInterval
- }
- }
-
private terminateWSConnection (): void {
if (this.isWebSocketConnectionOpened()) {
this.wsConnection?.terminate()
this.wsConnection = null
}
}
-
- private async reconnect (): Promise<void> {
- if (
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.wsConnectionRetryCount < this.stationInfo!.autoReconnectMaxRetries! ||
- this.stationInfo?.autoReconnectMaxRetries === -1
- ) {
- this.wsConnectionRetried = true
- ++this.wsConnectionRetryCount
- const reconnectDelay =
- this.stationInfo?.reconnectExponentialDelay === true
- ? exponentialDelay(this.wsConnectionRetryCount)
- : secondsToMilliseconds(this.getConnectionTimeout())
- const reconnectDelayWithdraw = 1000
- const reconnectTimeout =
- reconnectDelay - reconnectDelayWithdraw > 0 ? reconnectDelay - reconnectDelayWithdraw : 0
- logger.error(
- `${this.logPrefix()} WebSocket connection retry in ${roundTo(
- reconnectDelay,
- 2
- )}ms, timeout ${reconnectTimeout}ms`
- )
- await sleep(reconnectDelay)
- logger.error(
- `${this.logPrefix()} WebSocket connection retry #${this.wsConnectionRetryCount.toString()}`
- )
- this.openWSConnection(
- {
- handshakeTimeout: reconnectTimeout
- },
- { closeOpened: true }
- )
- } else if (this.stationInfo?.autoReconnectMaxRetries !== -1) {
- logger.error(
- `${this.logPrefix()} WebSocket connection retries failure: maximum retries reached (${
- this.wsConnectionRetryCount
- }) or retries disabled (${this.stationInfo?.autoReconnectMaxRetries})`
- )
- }
- }
}
// Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
import { parentPort } from 'node:worker_threads'
-
import { ThreadWorker } from 'poolifier'
-import { BaseError } from '../exception/index.js'
import type { ChargingStationInfo, ChargingStationWorkerData } from '../types/index.js'
+
+import { BaseError } from '../exception/index.js'
import { Configuration } from '../utils/index.js'
import { type WorkerDataError, type WorkerMessage, WorkerMessageEvents } from '../worker/index.js'
import { ChargingStation } from './ChargingStation.js'
export let chargingStationWorker: object
if (Configuration.workerPoolInUse()) {
chargingStationWorker = new ThreadWorker<
- ChargingStationWorkerData,
- ChargingStationInfo | undefined
+ ChargingStationWorkerData,
+ ChargingStationInfo | undefined
>((data?: ChargingStationWorkerData): ChargingStationInfo | undefined => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const { index, templateFile, options } = data!
+ const { index, options, templateFile } = data!
return new ChargingStation(index, templateFile, options).stationInfo
})
} else {
class ChargingStationWorker<Data extends ChargingStationWorkerData> {
constructor () {
parentPort?.on('message', (message: WorkerMessage<Data>) => {
- const { uuid, event, data } = message
+ const { data, event, uuid } = message
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (uuid != null) {
switch (event) {
data.options
)
parentPort?.postMessage({
- uuid,
- event: WorkerMessageEvents.addedWorkerElement,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- data: chargingStation.stationInfo!
+ data: chargingStation.stationInfo!,
+ event: WorkerMessageEvents.addedWorkerElement,
+ uuid,
} satisfies WorkerMessage<ChargingStationInfo>)
} catch (error) {
parentPort?.postMessage({
- uuid,
- event: WorkerMessageEvents.workerElementError,
data: {
event,
- name: (error as Error).name,
message: (error as Error).message,
- stack: (error as Error).stack
- }
+ name: (error as Error).name,
+ stack: (error as Error).stack,
+ },
+ event: WorkerMessageEvents.workerElementError,
+ uuid,
} satisfies WorkerMessage<WorkerDataError>)
}
break
import type { ConfigurationKey, ConfigurationKeyType } from '../types/index.js'
-import { logger } from '../utils/index.js'
import type { ChargingStation } from './ChargingStation.js'
+import { logger } from '../utils/index.js'
+
+interface AddConfigurationKeyParams {
+ overwrite?: boolean
+ save?: boolean
+}
interface ConfigurationKeyOptions {
readonly?: boolean
- visible?: boolean
reboot?: boolean
+ visible?: boolean
}
interface DeleteConfigurationKeyParams {
- save?: boolean
caseInsensitive?: boolean
-}
-interface AddConfigurationKeyParams {
- overwrite?: boolean
save?: boolean
}
options = {
...{
readonly: false,
+ reboot: false,
visible: true,
- reboot: false
},
- ...options
+ ...options,
}
params = { ...{ overwrite: false, save: false }, ...params }
let keyFound = getConfigurationKey(chargingStation, key)
- if (keyFound != null && params.overwrite === true) {
+ if (keyFound != null && params.overwrite) {
deleteConfigurationKey(chargingStation, keyFound.key, {
- save: false
+ save: false,
})
keyFound = undefined
}
key,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
readonly: options.readonly!,
+ reboot: options.reboot,
value,
visible: options.visible,
- reboot: options.reboot
})
- params.save === true && chargingStation.saveOcppConfiguration()
+ params.save && chargingStation.saveOcppConfiguration()
} else {
logger.error(
`${chargingStation.logPrefix()} Trying to add an already existing configuration key: %j`,
key: ConfigurationKeyType,
params?: DeleteConfigurationKeyParams
): ConfigurationKey[] | undefined => {
- params = { ...{ save: true, caseInsensitive: false }, ...params }
+ params = { ...{ caseInsensitive: false, save: true }, ...params }
const keyFound = getConfigurationKey(chargingStation, key, params.caseInsensitive)
if (keyFound != null) {
const deletedConfigurationKey = chargingStation.ocppConfiguration?.configurationKey?.splice(
chargingStation.ocppConfiguration.configurationKey.indexOf(keyFound),
1
)
- params.save === true && chargingStation.saveOcppConfiguration()
+ params.save && chargingStation.saveOcppConfiguration()
return deletedConfigurationKey
}
}
-import { createHash, randomBytes } from 'node:crypto'
import type { EventEmitter } from 'node:events'
-import { basename, dirname, isAbsolute, join, parse, relative, resolve } from 'node:path'
-import { env } from 'node:process'
-import { fileURLToPath } from 'node:url'
import chalk from 'chalk'
import {
isDate,
isPast,
isWithinInterval,
- toDate
+ toDate,
} from 'date-fns'
import { maxTime } from 'date-fns/constants'
-import { isEmpty } from 'rambda'
+import { hash, randomBytes } from 'node:crypto'
+import { basename, dirname, isAbsolute, join, parse, relative, resolve } from 'node:path'
+import { env } from 'node:process'
+import { fileURLToPath } from 'node:url'
+
+import type { ChargingStation } from './ChargingStation.js'
import { BaseError } from '../exception/index.js'
import {
BootReasonEnumType,
type ChargingProfile,
ChargingProfileKindType,
+ ChargingProfilePurposeType,
ChargingRateUnitType,
type ChargingSchedulePeriod,
type ChargingStationConfiguration,
ReservationTerminationReason,
StandardParametersKey,
type SupportedFeatureProfiles,
- Voltage
+ Voltage,
} from '../types/index.js'
import {
ACElectricUtils,
convertToInt,
DCElectricUtils,
isArraySorted,
+ isEmpty,
isNotEmptyArray,
isNotEmptyString,
isValidDate,
logger,
- secureRandom
+ secureRandom,
} from '../utils/index.js'
-import type { ChargingStation } from './ChargingStation.js'
import { getConfigurationKey } from './ConfigurationKeyUtils.js'
const moduleName = 'Helpers'
chargePointModel: stationTemplate.chargePointModel,
chargePointVendor: stationTemplate.chargePointVendor,
...(stationTemplate.chargeBoxSerialNumberPrefix != null && {
- chargeBoxSerialNumber: stationTemplate.chargeBoxSerialNumberPrefix
+ chargeBoxSerialNumber: stationTemplate.chargeBoxSerialNumberPrefix,
}),
...(stationTemplate.chargePointSerialNumberPrefix != null && {
- chargePointSerialNumber: stationTemplate.chargePointSerialNumberPrefix
+ chargePointSerialNumber: stationTemplate.chargePointSerialNumberPrefix,
}),
...(stationTemplate.meterSerialNumberPrefix != null && {
- meterSerialNumber: stationTemplate.meterSerialNumberPrefix
+ meterSerialNumber: stationTemplate.meterSerialNumberPrefix,
}),
...(stationTemplate.meterType != null && {
- meterType: stationTemplate.meterType
- })
+ meterType: stationTemplate.meterType,
+ }),
+ }
+ return hash(
+ Constants.DEFAULT_HASH_ALGORITHM,
+ `${JSON.stringify(chargingStationInfo)}${getChargingStationId(index, stationTemplate)}`,
+ 'hex'
+ )
+}
+
+export const validateStationInfo = (chargingStation: ChargingStation): void => {
+ if (chargingStation.stationInfo == null || isEmpty(chargingStation.stationInfo)) {
+ throw new BaseError('Missing charging station information')
+ }
+ if (
+ chargingStation.stationInfo.chargingStationId == null ||
+ isEmpty(chargingStation.stationInfo.chargingStationId.trim())
+ ) {
+ throw new BaseError('Missing chargingStationId in stationInfo properties')
+ }
+ const chargingStationId = chargingStation.stationInfo.chargingStationId
+ if (
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ chargingStation.stationInfo.hashId == null ||
+ isEmpty(chargingStation.stationInfo.hashId.trim())
+ ) {
+ throw new BaseError(`${chargingStationId}: Missing hashId in stationInfo properties`)
+ }
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ if (chargingStation.stationInfo.templateIndex == null) {
+ throw new BaseError(`${chargingStationId}: Missing templateIndex in stationInfo properties`)
+ }
+ if (chargingStation.stationInfo.templateIndex <= 0) {
+ throw new BaseError(
+ `${chargingStationId}: Invalid templateIndex value in stationInfo properties`
+ )
+ }
+ if (
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ chargingStation.stationInfo.templateName == null ||
+ isEmpty(chargingStation.stationInfo.templateName.trim())
+ ) {
+ throw new BaseError(`${chargingStationId}: Missing templateName in stationInfo properties`)
+ }
+ if (chargingStation.stationInfo.maximumPower == null) {
+ throw new BaseError(`${chargingStationId}: Missing maximumPower in stationInfo properties`)
+ }
+ if (chargingStation.stationInfo.maximumPower <= 0) {
+ throw new RangeError(
+ `${chargingStationId}: Invalid maximumPower value in stationInfo properties`
+ )
+ }
+ if (chargingStation.stationInfo.maximumAmperage == null) {
+ throw new BaseError(`${chargingStationId}: Missing maximumAmperage in stationInfo properties`)
+ }
+ if (chargingStation.stationInfo.maximumAmperage <= 0) {
+ throw new RangeError(
+ `${chargingStationId}: Invalid maximumAmperage value in stationInfo properties`
+ )
+ }
+ switch (chargingStation.stationInfo.ocppVersion) {
+ case OCPPVersion.VERSION_20:
+ case OCPPVersion.VERSION_201:
+ if (isEmpty(chargingStation.evses)) {
+ throw new BaseError(
+ `${chargingStationId}: OCPP 2.0 or superior requires at least one EVSE defined in the charging station template/configuration`
+ )
+ }
}
- return createHash(Constants.DEFAULT_HASH_ALGORITHM)
- .update(`${JSON.stringify(chargingStationInfo)}${getChargingStationId(index, stationTemplate)}`)
- .digest('hex')
}
-export const checkChargingStation = (
+export const checkChargingStationState = (
chargingStation: ChargingStation,
logPrefix: string
): boolean => {
): string | undefined => {
// AC/DC
if (connectorId === 0 && numberOfPhases === 0) {
- return `${connectorId}.${ConnectorPhaseRotation.RST}`
+ return `${connectorId.toString()}.${ConnectorPhaseRotation.RST}`
} else if (connectorId > 0 && numberOfPhases === 0) {
- return `${connectorId}.${ConnectorPhaseRotation.NotApplicable}`
+ return `${connectorId.toString()}.${ConnectorPhaseRotation.NotApplicable}`
// AC
} else if (connectorId >= 0 && numberOfPhases === 1) {
- return `${connectorId}.${ConnectorPhaseRotation.NotApplicable}`
+ return `${connectorId.toString()}.${ConnectorPhaseRotation.NotApplicable}`
} else if (connectorId >= 0 && numberOfPhases === 3) {
- return `${connectorId}.${ConnectorPhaseRotation.RST}`
+ return `${connectorId.toString()}.${ConnectorPhaseRotation.RST}`
}
}
templateFile: string
): {
configuredMaxConnectors: number
- templateMaxConnectors: number
templateMaxAvailableConnectors: number
+ templateMaxConnectors: number
} => {
const configuredMaxConnectors = getConfiguredMaxNumberOfConnectors(stationTemplate)
checkConfiguredMaxConnectors(configuredMaxConnectors, logPrefix, templateFile)
)
stationTemplate.randomConnectors = true
}
- return { configuredMaxConnectors, templateMaxConnectors, templateMaxAvailableConnectors }
+ return {
+ configuredMaxConnectors,
+ templateMaxAvailableConnectors,
+ templateMaxConnectors,
+ }
}
export const checkStationInfoConnectorStatus = (
): void => {
if (connectorStatus.status != null) {
logger.warn(
- `${logPrefix} Charging station information from template ${templateFile} with connector id ${connectorId} status configuration defined, undefine it`
+ `${logPrefix} Charging station information from template ${templateFile} with connector id ${connectorId.toString()} status configuration defined, undefine it`
)
delete connectorStatus.status
}
}
-export const buildConnectorsMap = (
- connectors: Record<string, ConnectorStatus>,
- logPrefix: string,
- templateFile: string
-): Map<number, ConnectorStatus> => {
- const connectorsMap = new Map<number, ConnectorStatus>()
- if (getMaxNumberOfConnectors(connectors) > 0) {
- for (const connector in connectors) {
- const connectorStatus = connectors[connector]
- const connectorId = convertToInt(connector)
- checkStationInfoConnectorStatus(connectorId, connectorStatus, logPrefix, templateFile)
- connectorsMap.set(connectorId, clone<ConnectorStatus>(connectorStatus))
- }
- } else {
- logger.warn(
- `${logPrefix} Charging station information from template ${templateFile} with no connectors, cannot build connectors map`
- )
- }
- return connectorsMap
-}
-
export const setChargingStationOptions = (
stationInfo: ChargingStationInfo,
options?: ChargingStationOptions
return stationInfo
}
+export const buildConnectorsMap = (
+ connectors: Record<string, ConnectorStatus>,
+ logPrefix: string,
+ templateFile: string
+): Map<number, ConnectorStatus> => {
+ const connectorsMap = new Map<number, ConnectorStatus>()
+ if (getMaxNumberOfConnectors(connectors) > 0) {
+ for (const connector in connectors) {
+ const connectorStatus = connectors[connector]
+ const connectorId = convertToInt(connector)
+ checkStationInfoConnectorStatus(connectorId, connectorStatus, logPrefix, templateFile)
+ connectorsMap.set(connectorId, clone<ConnectorStatus>(connectorStatus))
+ }
+ } else {
+ logger.warn(
+ `${logPrefix} Charging station information from template ${templateFile} with no connectors, cannot build connectors map`
+ )
+ }
+ return connectorsMap
+}
+
export const initializeConnectorsMapStatus = (
connectors: Map<number, ConnectorStatus>,
logPrefix: string
for (const connectorId of connectors.keys()) {
if (connectorId > 0 && connectors.get(connectorId)?.transactionStarted === true) {
logger.warn(
- `${logPrefix} Connector id ${connectorId} at initialization has a transaction started with id ${
- connectors.get(connectorId)?.transactionId
- }`
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `${logPrefix} Connector id ${connectorId.toString()} at initialization has a transaction started with id ${connectors
+ .get(connectorId)
+ ?.transactionId?.toString()}`
)
}
if (connectorId === 0) {
}
}
+export const resetAuthorizeConnectorStatus = (connectorStatus: ConnectorStatus): void => {
+ connectorStatus.idTagLocalAuthorized = false
+ connectorStatus.idTagAuthorized = false
+ delete connectorStatus.localAuthorizeIdTag
+ delete connectorStatus.authorizeIdTag
+}
+
export const resetConnectorStatus = (connectorStatus: ConnectorStatus | undefined): void => {
if (connectorStatus == null) {
return
}
- connectorStatus.chargingProfiles =
- connectorStatus.transactionId != null && isNotEmptyArray(connectorStatus.chargingProfiles)
- ? connectorStatus.chargingProfiles.filter(
- chargingProfile => chargingProfile.transactionId !== connectorStatus.transactionId
- )
- : []
- connectorStatus.idTagLocalAuthorized = false
- connectorStatus.idTagAuthorized = false
+ if (isNotEmptyArray(connectorStatus.chargingProfiles)) {
+ connectorStatus.chargingProfiles = connectorStatus.chargingProfiles.filter(
+ chargingProfile =>
+ (chargingProfile.chargingProfilePurpose === ChargingProfilePurposeType.TX_PROFILE &&
+ chargingProfile.transactionId != null &&
+ connectorStatus.transactionId != null &&
+ chargingProfile.transactionId !== connectorStatus.transactionId) ||
+ chargingProfile.chargingProfilePurpose !== ChargingProfilePurposeType.TX_PROFILE
+ )
+ }
+ resetAuthorizeConnectorStatus(connectorStatus)
connectorStatus.transactionRemoteStarted = false
connectorStatus.transactionStarted = false
delete connectorStatus.transactionStart
delete connectorStatus.transactionId
- delete connectorStatus.localAuthorizeIdTag
- delete connectorStatus.authorizeIdTag
delete connectorStatus.transactionIdTag
connectorStatus.transactionEnergyActiveImportRegisterValue = 0
delete connectorStatus.transactionBeginMeterValue
}
+export const prepareConnectorStatus = (connectorStatus: ConnectorStatus): ConnectorStatus => {
+ if (connectorStatus.reservation != null) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ connectorStatus.reservation.expiryDate = convertToDate(connectorStatus.reservation.expiryDate)!
+ }
+ if (isNotEmptyArray(connectorStatus.chargingProfiles)) {
+ connectorStatus.chargingProfiles = connectorStatus.chargingProfiles
+ .filter(
+ chargingProfile =>
+ chargingProfile.chargingProfilePurpose !== ChargingProfilePurposeType.TX_PROFILE
+ )
+ .map(chargingProfile => {
+ chargingProfile.chargingSchedule.startSchedule = convertToDate(
+ chargingProfile.chargingSchedule.startSchedule
+ )
+ chargingProfile.validFrom = convertToDate(chargingProfile.validFrom)
+ chargingProfile.validTo = convertToDate(chargingProfile.validTo)
+ return chargingProfile
+ })
+ }
+ return connectorStatus
+}
+
export const createBootNotificationRequest = (
stationInfo: ChargingStationInfo,
bootReason: BootReasonEnumType = BootReasonEnumType.PowerUp
chargePointModel: stationInfo.chargePointModel,
chargePointVendor: stationInfo.chargePointVendor,
...(stationInfo.chargeBoxSerialNumber != null && {
- chargeBoxSerialNumber: stationInfo.chargeBoxSerialNumber
+ chargeBoxSerialNumber: stationInfo.chargeBoxSerialNumber,
}),
...(stationInfo.chargePointSerialNumber != null && {
- chargePointSerialNumber: stationInfo.chargePointSerialNumber
+ chargePointSerialNumber: stationInfo.chargePointSerialNumber,
}),
...(stationInfo.firmwareVersion != null && {
- firmwareVersion: stationInfo.firmwareVersion
+ firmwareVersion: stationInfo.firmwareVersion,
}),
...(stationInfo.iccid != null && { iccid: stationInfo.iccid }),
...(stationInfo.imsi != null && { imsi: stationInfo.imsi }),
...(stationInfo.meterSerialNumber != null && {
- meterSerialNumber: stationInfo.meterSerialNumber
+ meterSerialNumber: stationInfo.meterSerialNumber,
}),
...(stationInfo.meterType != null && {
- meterType: stationInfo.meterType
- })
+ meterType: stationInfo.meterType,
+ }),
} satisfies OCPP16BootNotificationRequest
case OCPPVersion.VERSION_20:
case OCPPVersion.VERSION_201:
return {
- reason: bootReason,
chargingStation: {
model: stationInfo.chargePointModel,
vendorName: stationInfo.chargePointVendor,
...(stationInfo.firmwareVersion != null && {
- firmwareVersion: stationInfo.firmwareVersion
+ firmwareVersion: stationInfo.firmwareVersion,
}),
...(stationInfo.chargeBoxSerialNumber != null && {
- serialNumber: stationInfo.chargeBoxSerialNumber
+ serialNumber: stationInfo.chargeBoxSerialNumber,
}),
...((stationInfo.iccid != null || stationInfo.imsi != null) && {
modem: {
...(stationInfo.iccid != null && { iccid: stationInfo.iccid }),
- ...(stationInfo.imsi != null && { imsi: stationInfo.imsi })
- }
- })
- }
+ ...(stationInfo.imsi != null && { imsi: stationInfo.imsi }),
+ },
+ }),
+ },
+ reason: bootReason,
} satisfies OCPP20BootNotificationRequest
}
}
logPrefix: string,
templateFile: string
): void => {
- const templateKeys: Array<{ deprecatedKey: string, key?: string }> = [
+ const templateKeys: { deprecatedKey: string; key?: string }[] = [
{ deprecatedKey: 'supervisionUrl', key: 'supervisionUrls' },
{ deprecatedKey: 'authorizationFile', key: 'idTagsFile' },
{ deprecatedKey: 'payloadSchemaValidation', key: 'ocppStrictCompliance' },
- { deprecatedKey: 'mustAuthorizeAtRemoteStart', key: 'remoteAuthorization' }
+ { deprecatedKey: 'mustAuthorizeAtRemoteStart', key: 'remoteAuthorization' },
]
for (const templateKey of templateKeys) {
warnDeprecatedTemplateKey(
stationTemplate: ChargingStationTemplate,
stationInfo: ChargingStationInfo,
params?: {
- randomSerialNumberUpperCase?: boolean
randomSerialNumber?: boolean
+ randomSerialNumberUpperCase?: boolean
}
): void => {
- params = { ...{ randomSerialNumberUpperCase: true, randomSerialNumber: true }, ...params }
- const serialNumberSuffix =
- params.randomSerialNumber === true
- ? getRandomSerialNumberSuffix({
- upperCase: params.randomSerialNumberUpperCase
- })
- : ''
+ params = {
+ ...{ randomSerialNumber: true, randomSerialNumberUpperCase: true },
+ ...params,
+ }
+ const serialNumberSuffix = params.randomSerialNumber
+ ? getRandomSerialNumberSuffix({
+ upperCase: params.randomSerialNumberUpperCase,
+ })
+ : ''
isNotEmptyString(stationTemplate.chargePointSerialNumberPrefix) &&
(stationInfo.chargePointSerialNumber = `${stationTemplate.chargePointSerialNumberPrefix}${serialNumberSuffix}`)
isNotEmptyString(stationTemplate.chargeBoxSerialNumberPrefix) &&
export const getAmperageLimitationUnitDivider = (stationInfo: ChargingStationInfo): number => {
let unitDivider = 1
switch (stationInfo.amperageLimitationUnit) {
- case AmpereUnits.DECI_AMPERE:
- unitDivider = 10
- break
case AmpereUnits.CENTI_AMPERE:
unitDivider = 100
break
+ case AmpereUnits.DECI_AMPERE:
+ unitDivider = 10
+ break
case AmpereUnits.MILLI_AMPERE:
unitDivider = 1000
break
return unitDivider
}
+const getChargingStationChargingProfiles = (
+ chargingStation: ChargingStation
+): ChargingProfile[] => {
+ return (chargingStation.getConnectorStatus(0)?.chargingProfiles ?? [])
+ .filter(
+ chargingProfile =>
+ chargingProfile.chargingProfilePurpose ===
+ ChargingProfilePurposeType.CHARGE_POINT_MAX_PROFILE
+ )
+ .sort((a, b) => b.stackLevel - a.stackLevel)
+}
+
+export const getChargingStationChargingProfilesLimit = (
+ chargingStation: ChargingStation
+): number | undefined => {
+ const chargingProfiles = getChargingStationChargingProfiles(chargingStation)
+ if (isNotEmptyArray(chargingProfiles)) {
+ const chargingProfilesLimit = getChargingProfilesLimit(chargingStation, 0, chargingProfiles)
+ if (chargingProfilesLimit != null) {
+ const limit = buildChargingProfilesLimit(chargingStation, chargingProfilesLimit)
+ const chargingStationMaximumPower =
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.stationInfo!.maximumPower!
+ if (limit > chargingStationMaximumPower) {
+ logger.error(
+ `${chargingStation.logPrefix()} ${moduleName}.getChargingStationChargingProfilesLimit: Charging profile id ${chargingProfilesLimit.chargingProfile.chargingProfileId.toString()} limit ${limit.toString()} is greater than charging station maximum ${chargingStationMaximumPower.toString()}: %j`,
+ chargingProfilesLimit
+ )
+ return chargingStationMaximumPower
+ }
+ return limit
+ }
+ }
+}
+
/**
- * Gets the connector cloned charging profiles applying a power limitation
- * and sorted by connector id descending then stack level descending
- *
- * @param chargingStation -
- * @param connectorId -
+ * Gets the connector charging profiles relevant for power limitation shallow cloned
+ * and sorted by priorities
+ * @param chargingStation - Charging station
+ * @param connectorId - Connector id
* @returns connector charging profiles array
*/
export const getConnectorChargingProfiles = (
chargingStation: ChargingStation,
connectorId: number
): ChargingProfile[] => {
- return clone<ChargingProfile[]>(
- (chargingStation.getConnectorStatus(connectorId)?.chargingProfiles ?? [])
- .sort((a, b) => b.stackLevel - a.stackLevel)
- .concat(
- (chargingStation.getConnectorStatus(0)?.chargingProfiles ?? []).sort(
- (a, b) => b.stackLevel - a.stackLevel
+ return (chargingStation.getConnectorStatus(connectorId)?.chargingProfiles ?? [])
+ .slice()
+ .sort((a, b) => {
+ if (
+ a.chargingProfilePurpose === ChargingProfilePurposeType.TX_PROFILE &&
+ b.chargingProfilePurpose === ChargingProfilePurposeType.TX_DEFAULT_PROFILE
+ ) {
+ return -1
+ } else if (
+ a.chargingProfilePurpose === ChargingProfilePurposeType.TX_DEFAULT_PROFILE &&
+ b.chargingProfilePurpose === ChargingProfilePurposeType.TX_PROFILE
+ ) {
+ return 1
+ }
+ return b.stackLevel - a.stackLevel
+ })
+ .concat(
+ (chargingStation.getConnectorStatus(0)?.chargingProfiles ?? [])
+ .filter(
+ chargingProfile =>
+ chargingProfile.chargingProfilePurpose === ChargingProfilePurposeType.TX_DEFAULT_PROFILE
)
- )
- )
+ .sort((a, b) => b.stackLevel - a.stackLevel)
+ )
}
-export const getChargingStationConnectorChargingProfilesPowerLimit = (
+export const getConnectorChargingProfilesLimit = (
chargingStation: ChargingStation,
connectorId: number
): number | undefined => {
- let limit: number | undefined, chargingProfile: ChargingProfile | undefined
- // Get charging profiles sorted by connector id then stack level
const chargingProfiles = getConnectorChargingProfiles(chargingStation, connectorId)
if (isNotEmptyArray(chargingProfiles)) {
- const result = getLimitFromChargingProfiles(
+ const chargingProfilesLimit = getChargingProfilesLimit(
chargingStation,
connectorId,
- chargingProfiles,
- chargingStation.logPrefix()
+ chargingProfiles
)
- if (result != null) {
- limit = result.limit
- chargingProfile = result.chargingProfile
- switch (chargingStation.stationInfo?.currentOutType) {
- case CurrentType.AC:
- limit =
- chargingProfile.chargingSchedule.chargingRateUnit === ChargingRateUnitType.WATT
- ? limit
- : ACElectricUtils.powerTotal(
- chargingStation.getNumberOfPhases(),
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- chargingStation.stationInfo.voltageOut!,
- limit
- )
- break
- case CurrentType.DC:
- limit =
- chargingProfile.chargingSchedule.chargingRateUnit === ChargingRateUnitType.WATT
- ? limit
- : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- DCElectricUtils.power(chargingStation.stationInfo.voltageOut!, limit)
- }
+ if (chargingProfilesLimit != null) {
+ const limit = buildChargingProfilesLimit(chargingStation, chargingProfilesLimit)
const connectorMaximumPower =
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
chargingStation.stationInfo!.maximumPower! / chargingStation.powerDivider!
if (limit > connectorMaximumPower) {
logger.error(
- `${chargingStation.logPrefix()} ${moduleName}.getChargingStationConnectorChargingProfilesPowerLimit: Charging profile id ${
- chargingProfile.chargingProfileId
- } limit ${limit} is greater than connector id ${connectorId} maximum ${connectorMaximumPower}: %j`,
- result
+ `${chargingStation.logPrefix()} ${moduleName}.getConnectorChargingProfilesLimit: Charging profile id ${chargingProfilesLimit.chargingProfile.chargingProfileId.toString()} limit ${limit.toString()} is greater than connector ${connectorId.toString()} maximum ${connectorMaximumPower.toString()}: %j`,
+ chargingProfilesLimit
)
- limit = connectorMaximumPower
+ return connectorMaximumPower
}
+ return limit
}
}
- return limit
+}
+
+const buildChargingProfilesLimit = (
+ chargingStation: ChargingStation,
+ chargingProfilesLimit: ChargingProfilesLimit
+): number => {
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ const errorMsg = `Unknown ${chargingStation.stationInfo?.currentOutType} currentOutType in charging station information, cannot build charging profiles limit`
+ const { chargingProfile, limit } = chargingProfilesLimit
+ switch (chargingStation.stationInfo?.currentOutType) {
+ case CurrentType.AC:
+ return chargingProfile.chargingSchedule.chargingRateUnit === ChargingRateUnitType.WATT
+ ? limit
+ : ACElectricUtils.powerTotal(
+ chargingStation.getNumberOfPhases(),
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.stationInfo.voltageOut!,
+ limit
+ )
+ case CurrentType.DC:
+ return chargingProfile.chargingSchedule.chargingRateUnit === ChargingRateUnitType.WATT
+ ? limit
+ : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ DCElectricUtils.power(chargingStation.stationInfo.voltageOut!, limit)
+ default:
+ logger.error(
+ `${chargingStation.logPrefix()} ${moduleName}.buildChargingProfilesLimit: ${errorMsg}`
+ )
+ throw new BaseError(errorMsg)
+ }
}
export const getDefaultVoltageOut = (
const getConfiguredMaxNumberOfConnectors = (stationTemplate: ChargingStationTemplate): number => {
let configuredMaxNumberOfConnectors = 0
- if (isNotEmptyArray(stationTemplate.numberOfConnectors)) {
+ if (isNotEmptyArray<number>(stationTemplate.numberOfConnectors)) {
const numberOfConnectors = stationTemplate.numberOfConnectors
configuredMaxNumberOfConnectors =
numberOfConnectors[Math.floor(secureRandom() * numberOfConnectors.length)]
- } else if (stationTemplate.numberOfConnectors != null) {
+ } else if (typeof stationTemplate.numberOfConnectors === 'number') {
configuredMaxNumberOfConnectors = stationTemplate.numberOfConnectors
} else if (stationTemplate.Connectors != null && stationTemplate.Evses == null) {
configuredMaxNumberOfConnectors =
): void => {
if (configuredMaxConnectors <= 0) {
logger.warn(
- `${logPrefix} Charging station information from template ${templateFile} with ${configuredMaxConnectors} connectors`
+ `${logPrefix} Charging station information from template ${templateFile} with ${configuredMaxConnectors.toString()} connectors`
)
}
}
connectorStatus.transactionStarted = false
connectorStatus.energyActiveImportRegisterValue = 0
connectorStatus.transactionEnergyActiveImportRegisterValue = 0
- if (connectorStatus.chargingProfiles == null) {
- connectorStatus.chargingProfiles = []
- }
+ connectorStatus.chargingProfiles ??= []
}
const warnDeprecatedTemplateKey = (
): void => {
if (template[deprecatedKey as keyof ChargingStationTemplate] != null) {
if (key != null) {
- (template as unknown as Record<string, unknown>)[key] =
+ ;(template as unknown as Record<string, unknown>)[key] =
template[deprecatedKey as keyof ChargingStationTemplate]
}
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
}
interface ChargingProfilesLimit {
- limit: number
chargingProfile: ChargingProfile
+ limit: number
}
/**
- * Charging profiles shall already be sorted by connector id descending then stack level descending
- *
+ * Get the charging profiles limit for a connector
+ * Charging profiles shall already be sorted by priorities
* @param chargingStation -
* @param connectorId -
* @param chargingProfiles -
- * @param logPrefix -
* @returns ChargingProfilesLimit
*/
-const getLimitFromChargingProfiles = (
+const getChargingProfilesLimit = (
chargingStation: ChargingStation,
connectorId: number,
- chargingProfiles: ChargingProfile[],
- logPrefix: string
+ chargingProfiles: ChargingProfile[]
): ChargingProfilesLimit | undefined => {
- const debugLogMsg = `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Matching charging profile found for power limitation: %j`
+ const debugLogMsg = `${chargingStation.logPrefix()} ${moduleName}.getChargingProfilesLimit: Charging profiles limit found: %j`
const currentDate = new Date()
const connectorStatus = chargingStation.getConnectorStatus(connectorId)
+ let previousActiveChargingProfile: ChargingProfile | undefined
for (const chargingProfile of chargingProfiles) {
const chargingSchedule = chargingProfile.chargingSchedule
if (chargingSchedule.startSchedule == null) {
logger.debug(
- `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} has no startSchedule defined. Trying to set it to the connector current transaction start date`
+ `${chargingStation.logPrefix()} ${moduleName}.getChargingProfilesLimit: Charging profile id ${chargingProfile.chargingProfileId.toString()} has no startSchedule defined. Trying to set it to the connector current transaction start date`
)
// OCPP specifies that if startSchedule is not defined, it should be relative to start of the connector transaction
chargingSchedule.startSchedule = connectorStatus?.transactionStart
}
if (!isDate(chargingSchedule.startSchedule)) {
logger.warn(
- `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} startSchedule property is not a Date instance. Trying to convert it to a Date instance`
+ `${chargingStation.logPrefix()} ${moduleName}.getChargingProfilesLimit: Charging profile id ${chargingProfile.chargingProfileId.toString()} startSchedule property is not a Date instance. Trying to convert it to a Date instance`
)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
chargingSchedule.startSchedule = convertToDate(chargingSchedule.startSchedule)!
}
if (chargingSchedule.duration == null) {
logger.debug(
- `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} has no duration defined and will be set to the maximum time allowed`
+ `${chargingStation.logPrefix()} ${moduleName}.getChargingProfilesLimit: Charging profile id ${chargingProfile.chargingProfileId.toString()} has no duration defined and will be set to the maximum time allowed`
)
// OCPP specifies that if duration is not defined, it should be infinite
chargingSchedule.duration = differenceInSeconds(maxTime, chargingSchedule.startSchedule)
}
- if (!prepareChargingProfileKind(connectorStatus, chargingProfile, currentDate, logPrefix)) {
+ if (
+ !prepareChargingProfileKind(
+ connectorStatus,
+ chargingProfile,
+ currentDate,
+ chargingStation.logPrefix()
+ )
+ ) {
continue
}
- if (!canProceedChargingProfile(chargingProfile, currentDate, logPrefix)) {
+ if (!canProceedChargingProfile(chargingProfile, currentDate, chargingStation.logPrefix())) {
continue
}
// Check if the charging profile is active
if (
isWithinInterval(currentDate, {
+ end: addSeconds(chargingSchedule.startSchedule, chargingSchedule.duration),
start: chargingSchedule.startSchedule,
- end: addSeconds(chargingSchedule.startSchedule, chargingSchedule.duration)
})
) {
- if (isNotEmptyArray(chargingSchedule.chargingSchedulePeriod)) {
+ if (isNotEmptyArray<ChargingSchedulePeriod>(chargingSchedule.chargingSchedulePeriod)) {
const chargingSchedulePeriodCompareFn = (
a: ChargingSchedulePeriod,
b: ChargingSchedulePeriod
)
) {
logger.warn(
- `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} schedule periods are not sorted by start period`
+ `${chargingStation.logPrefix()} ${moduleName}.getChargingProfilesLimit: Charging profile id ${chargingProfile.chargingProfileId.toString()} schedule periods are not sorted by start period`
)
chargingSchedule.chargingSchedulePeriod.sort(chargingSchedulePeriodCompareFn)
}
// Check if the first schedule period startPeriod property is equal to 0
if (chargingSchedule.chargingSchedulePeriod[0].startPeriod !== 0) {
logger.error(
- `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} first schedule period start period ${chargingSchedule.chargingSchedulePeriod[0].startPeriod} is not equal to 0`
+ `${chargingStation.logPrefix()} ${moduleName}.getChargingProfilesLimit: Charging profile id ${chargingProfile.chargingProfileId.toString()} first schedule period start period ${chargingSchedule.chargingSchedulePeriod[0].startPeriod.toString()} is not equal to 0`
)
continue
}
// Handle only one schedule period
if (chargingSchedule.chargingSchedulePeriod.length === 1) {
- const result: ChargingProfilesLimit = {
+ const chargingProfilesLimit: ChargingProfilesLimit = {
+ chargingProfile,
limit: chargingSchedule.chargingSchedulePeriod[0].limit,
- chargingProfile
}
- logger.debug(debugLogMsg, result)
- return result
+ logger.debug(debugLogMsg, chargingProfilesLimit)
+ return chargingProfilesLimit
}
let previousChargingSchedulePeriod: ChargingSchedulePeriod | undefined
// Search for the right schedule period
for (const [
index,
- chargingSchedulePeriod
+ chargingSchedulePeriod,
] of chargingSchedule.chargingSchedulePeriod.entries()) {
// Find the right schedule period
if (
)
) {
// Found the schedule period: previous is the correct one
- const result: ChargingProfilesLimit = {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- limit: previousChargingSchedulePeriod!.limit,
- chargingProfile
+ const chargingProfilesLimit: ChargingProfilesLimit = {
+ chargingProfile: previousActiveChargingProfile ?? chargingProfile,
+ limit: previousChargingSchedulePeriod?.limit ?? chargingSchedulePeriod.limit,
}
- logger.debug(debugLogMsg, result)
- return result
+ logger.debug(debugLogMsg, chargingProfilesLimit)
+ return chargingProfilesLimit
}
- // Keep a reference to previous one
- previousChargingSchedulePeriod = chargingSchedulePeriod
// Handle the last schedule period within the charging profile duration
if (
index === chargingSchedule.chargingSchedulePeriod.length - 1 ||
chargingSchedule.startSchedule
) > chargingSchedule.duration)
) {
- const result: ChargingProfilesLimit = {
- limit: previousChargingSchedulePeriod.limit,
- chargingProfile
+ const chargingProfilesLimit: ChargingProfilesLimit = {
+ chargingProfile,
+ limit: chargingSchedulePeriod.limit,
}
- logger.debug(debugLogMsg, result)
- return result
+ logger.debug(debugLogMsg, chargingProfilesLimit)
+ return chargingProfilesLimit
}
+ // Keep a reference to previous charging schedule period
+ previousChargingSchedulePeriod = chargingSchedulePeriod
}
}
+ // Keep a reference to previous active charging profile
+ previousActiveChargingProfile = chargingProfile
}
}
}
export const prepareChargingProfileKind = (
connectorStatus: ConnectorStatus | undefined,
chargingProfile: ChargingProfile,
- currentDate: string | number | Date,
+ currentDate: Date | number | string,
logPrefix: string
): boolean => {
switch (chargingProfile.chargingProfileKind) {
case ChargingProfileKindType.RELATIVE:
if (chargingProfile.chargingSchedule.startSchedule != null) {
logger.warn(
- `${logPrefix} ${moduleName}.prepareChargingProfileKind: Relative charging profile id ${chargingProfile.chargingProfileId} has a startSchedule property defined. It will be ignored or used if the connector has a transaction started`
+ `${logPrefix} ${moduleName}.prepareChargingProfileKind: Relative charging profile id ${chargingProfile.chargingProfileId.toString()} has a startSchedule property defined. It will be ignored or used if the connector has a transaction started`
)
delete chargingProfile.chargingSchedule.startSchedule
}
export const canProceedChargingProfile = (
chargingProfile: ChargingProfile,
- currentDate: string | number | Date,
+ currentDate: Date | number | string,
logPrefix: string
): boolean => {
if (
(isValidDate(chargingProfile.validTo) && isAfter(currentDate, chargingProfile.validTo))
) {
logger.debug(
- `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${
- chargingProfile.chargingProfileId
- } is not valid for the current date ${
- isDate(currentDate) ? currentDate.toISOString() : currentDate
+ `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId.toString()} is not valid for the current date ${
+ isDate(currentDate) ? currentDate.toISOString() : currentDate.toString()
}`
)
return false
chargingProfile.chargingSchedule.duration == null
) {
logger.error(
- `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has no startSchedule or duration defined`
+ `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId.toString()} has no startSchedule or duration defined`
)
return false
}
if (!isValidDate(chargingProfile.chargingSchedule.startSchedule)) {
logger.error(
- `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has an invalid startSchedule date defined`
+ `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId.toString()} has an invalid startSchedule date defined`
)
return false
}
if (!Number.isSafeInteger(chargingProfile.chargingSchedule.duration)) {
logger.error(
- `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has non integer duration defined`
+ `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId.toString()} has non integer duration defined`
)
return false
}
chargingProfile.recurrencyKind == null
) {
logger.error(
- `${logPrefix} ${moduleName}.canProceedRecurringChargingProfile: Recurring charging profile id ${chargingProfile.chargingProfileId} has no recurrencyKind defined`
+ `${logPrefix} ${moduleName}.canProceedRecurringChargingProfile: Recurring charging profile id ${chargingProfile.chargingProfileId.toString()} has no recurrencyKind defined`
)
return false
}
chargingProfile.chargingSchedule.startSchedule == null
) {
logger.error(
- `${logPrefix} ${moduleName}.canProceedRecurringChargingProfile: Recurring charging profile id ${chargingProfile.chargingProfileId} has no startSchedule defined`
+ `${logPrefix} ${moduleName}.canProceedRecurringChargingProfile: Recurring charging profile id ${chargingProfile.chargingProfileId.toString()} has no startSchedule defined`
)
return false
}
/**
* Adjust recurring charging profile startSchedule to the current recurrency time interval if needed
- *
* @param chargingProfile -
* @param currentDate -
* @param logPrefix -
+ * @returns boolean
*/
const prepareRecurringChargingProfile = (
chargingProfile: ChargingProfile,
- currentDate: string | number | Date,
+ currentDate: Date | number | string,
logPrefix: string
): boolean => {
const chargingSchedule = chargingProfile.chargingSchedule
case RecurrencyKindType.DAILY:
recurringInterval = {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- start: chargingSchedule.startSchedule!,
+ end: addDays(chargingSchedule.startSchedule!, 1),
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- end: addDays(chargingSchedule.startSchedule!, 1)
+ start: chargingSchedule.startSchedule!,
}
checkRecurringChargingProfileDuration(chargingProfile, recurringInterval, logPrefix)
if (
differenceInDays(currentDate, recurringInterval.start)
)
recurringInterval = {
+ end: addDays(chargingSchedule.startSchedule, 1),
start: chargingSchedule.startSchedule,
- end: addDays(chargingSchedule.startSchedule, 1)
}
recurringIntervalTranslated = true
}
case RecurrencyKindType.WEEKLY:
recurringInterval = {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- start: chargingSchedule.startSchedule!,
+ end: addWeeks(chargingSchedule.startSchedule!, 1),
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- end: addWeeks(chargingSchedule.startSchedule!, 1)
+ start: chargingSchedule.startSchedule!,
}
checkRecurringChargingProfileDuration(chargingProfile, recurringInterval, logPrefix)
if (
differenceInWeeks(currentDate, recurringInterval.start)
)
recurringInterval = {
+ end: addWeeks(chargingSchedule.startSchedule, 1),
start: chargingSchedule.startSchedule,
- end: addWeeks(chargingSchedule.startSchedule, 1)
}
recurringIntervalTranslated = true
}
break
default:
logger.error(
- `${logPrefix} ${moduleName}.prepareRecurringChargingProfile: Recurring ${chargingProfile.recurrencyKind} charging profile id ${chargingProfile.chargingProfileId} is not supported`
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `${logPrefix} ${moduleName}.prepareRecurringChargingProfile: Recurring ${chargingProfile.recurrencyKind} charging profile id ${chargingProfile.chargingProfileId.toString()} is not supported`
)
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (recurringIntervalTranslated && !isWithinInterval(currentDate, recurringInterval!)) {
logger.error(
`${logPrefix} ${moduleName}.prepareRecurringChargingProfile: Recurring ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
chargingProfile.recurrencyKind
- } charging profile id ${chargingProfile.chargingProfileId} recurrency time interval [${toDate(
+ } charging profile id ${chargingProfile.chargingProfileId.toString()} recurrency time interval [${toDate(
recurringInterval?.start as Date
).toISOString()}, ${toDate(
recurringInterval?.end as Date
).toISOString()}] has not been properly translated to current date ${
- isDate(currentDate) ? currentDate.toISOString() : currentDate
+ isDate(currentDate) ? currentDate.toISOString() : currentDate.toString()
} `
)
}
logger.warn(
`${logPrefix} ${moduleName}.checkRecurringChargingProfileDuration: Recurring ${
chargingProfile.chargingProfileKind
- } charging profile id ${
- chargingProfile.chargingProfileId
- } duration is not defined, set it to the recurrency time interval duration ${differenceInSeconds(
+ } charging profile id ${chargingProfile.chargingProfileId.toString()} duration is not defined, set it to the recurrency time interval duration ${differenceInSeconds(
interval.end,
interval.start
- )}`
+ ).toString()}`
)
chargingProfile.chargingSchedule.duration = differenceInSeconds(interval.end, interval.start)
} else if (
logger.warn(
`${logPrefix} ${moduleName}.checkRecurringChargingProfileDuration: Recurring ${
chargingProfile.chargingProfileKind
- } charging profile id ${chargingProfile.chargingProfileId} duration ${
- chargingProfile.chargingSchedule.duration
- } is greater than the recurrency time interval duration ${differenceInSeconds(
+ } charging profile id ${chargingProfile.chargingProfileId.toString()} duration ${chargingProfile.chargingSchedule.duration.toString()} is greater than the recurrency time interval duration ${differenceInSeconds(
interval.end,
interval.start
- )}`
+ ).toString()}`
)
chargingProfile.chargingSchedule.duration = differenceInSeconds(interval.end, interval.start)
}
upperCase?: boolean
}): string => {
const randomSerialNumberSuffix = randomBytes(params?.randomBytesLength ?? 16).toString('hex')
- if (params?.upperCase === true) {
+ if (params?.upperCase) {
return randomSerialNumberSuffix.toUpperCase()
}
return randomSerialNumberSuffix
import { type FSWatcher, readFileSync } from 'node:fs'
+import type { ChargingStation } from './ChargingStation.js'
+
import { FileType, IdTagDistribution } from '../types/index.js'
import {
handleFileException,
logger,
logPrefix,
secureRandom,
- watchJsonFile
+ watchJsonFile,
} from '../utils/index.js'
-import type { ChargingStation } from './ChargingStation.js'
import { getIdTagsFile } from './Helpers.js'
interface IdTagsCacheValueType {
}
public static getInstance (): IdTagsCache {
- if (IdTagsCache.instance === null) {
- IdTagsCache.instance = new IdTagsCache()
- }
+ IdTagsCache.instance ??= new IdTagsCache()
return IdTagsCache.instance
}
+ public deleteIdTags (file: string): boolean {
+ return this.deleteIdTagsCache(file) && this.deleteIdTagsCacheIndexes(file)
+ }
+
/**
* Gets one idtag from the cache given the distribution
* Must be called after checking the cache is not an empty array
- *
* @param distribution -
* @param chargingStation -
* @param connectorId -
- * @returns
+ * @returns string
*/
public getIdTag (
distribution: IdTagDistribution,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const idTagsFile = getIdTagsFile(chargingStation.stationInfo!)!
switch (distribution) {
+ case IdTagDistribution.CONNECTOR_AFFINITY:
+ return this.getConnectorAffinityIdTag(chargingStation, connectorId)
case IdTagDistribution.RANDOM:
return this.getRandomIdTag(hashId, idTagsFile)
case IdTagDistribution.ROUND_ROBIN:
return this.getRoundRobinIdTag(hashId, idTagsFile)
- case IdTagDistribution.CONNECTOR_AFFINITY:
- return this.getConnectorAffinityIdTag(chargingStation, connectorId)
default:
return this.getRoundRobinIdTag(hashId, idTagsFile)
}
/**
* Gets all idtags from the cache
* Must be called after checking the cache is not an empty array
- *
* @param file -
- * @returns
+ * @returns string[] | undefined
*/
public getIdTags (file: string): string[] | undefined {
if (!this.hasIdTagsCache(file)) {
return this.getIdTagsCache(file)
}
- public deleteIdTags (file: string): boolean {
- return this.deleteIdTagsCache(file) && this.deleteIdTagsCacheIndexes(file)
+ private deleteIdTagsCache (file: string): boolean {
+ this.idTagsCaches.get(file)?.idTagsFileWatcher?.close()
+ return this.idTagsCaches.delete(file)
+ }
+
+ private deleteIdTagsCacheIndexes (file: string): boolean {
+ const deleted: boolean[] = []
+ for (const [key] of this.idTagsCachesAddressableIndexes) {
+ if (key.startsWith(file)) {
+ deleted.push(this.idTagsCachesAddressableIndexes.delete(key))
+ }
+ }
+ return !deleted.some(value => !value)
+ }
+
+ private getConnectorAffinityIdTag (chargingStation: ChargingStation, connectorId: number): string {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const file = getIdTagsFile(chargingStation.stationInfo!)!
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const idTags = this.getIdTags(file)!
+ const addressableKey = this.getIdTagsCacheIndexesAddressableKey(
+ file,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.stationInfo!.hashId
+ )
+ this.idTagsCachesAddressableIndexes.set(
+ addressableKey,
+ (chargingStation.index - 1 + (connectorId - 1)) % idTags.length
+ )
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return idTags[this.idTagsCachesAddressableIndexes.get(addressableKey)!]
+ }
+
+ private getIdTagsCache (file: string): string[] | undefined {
+ return this.idTagsCaches.get(file)?.idTags
+ }
+
+ private getIdTagsCacheIndexesAddressableKey (prefix: string, uid: string): string {
+ return `${prefix}${uid}`
+ }
+
+ private getIdTagsFromFile (file: string): string[] {
+ if (isNotEmptyString(file)) {
+ try {
+ return JSON.parse(readFileSync(file, 'utf8')) as string[]
+ } catch (error) {
+ handleFileException(
+ file,
+ FileType.Authorization,
+ error as NodeJS.ErrnoException,
+ this.logPrefix(file)
+ )
+ }
+ }
+ return []
}
private getRandomIdTag (hashId: string, file: string): string {
return idTag
}
- private getConnectorAffinityIdTag (chargingStation: ChargingStation, connectorId: number): string {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const file = getIdTagsFile(chargingStation.stationInfo!)!
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const idTags = this.getIdTags(file)!
- const addressableKey = this.getIdTagsCacheIndexesAddressableKey(
- file,
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- chargingStation.stationInfo!.hashId
- )
- this.idTagsCachesAddressableIndexes.set(
- addressableKey,
- (chargingStation.index - 1 + (connectorId - 1)) % idTags.length
- )
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return idTags[this.idTagsCachesAddressableIndexes.get(addressableKey)!]
- }
-
private hasIdTagsCache (file: string): boolean {
return this.idTagsCaches.has(file)
}
+ private readonly logPrefix = (file: string): string => {
+ return logPrefix(` Id tags cache for id tags file '${file}' |`)
+ }
+
private setIdTagsCache (file: string, idTags: string[]): Map<string, IdTagsCacheValueType> {
return this.idTagsCaches.set(file, {
idTags,
error as NodeJS.ErrnoException,
this.logPrefix(file),
{
- throwError: false
+ throwError: false,
}
)
}
}
}
- )
+ ),
})
}
-
- private getIdTagsCache (file: string): string[] | undefined {
- return this.idTagsCaches.get(file)?.idTags
- }
-
- private deleteIdTagsCache (file: string): boolean {
- this.idTagsCaches.get(file)?.idTagsFileWatcher?.close()
- return this.idTagsCaches.delete(file)
- }
-
- private deleteIdTagsCacheIndexes (file: string): boolean {
- const deleted: boolean[] = []
- for (const [key] of this.idTagsCachesAddressableIndexes) {
- if (key.startsWith(file)) {
- deleted.push(this.idTagsCachesAddressableIndexes.delete(key))
- }
- }
- return !deleted.some(value => !value)
- }
-
- private getIdTagsCacheIndexesAddressableKey (prefix: string, uid: string): string {
- return `${prefix}${uid}`
- }
-
- private getIdTagsFromFile (file: string): string[] {
- if (isNotEmptyString(file)) {
- try {
- return JSON.parse(readFileSync(file, 'utf8')) as string[]
- } catch (error) {
- handleFileException(
- file,
- FileType.Authorization,
- error as NodeJS.ErrnoException,
- this.logPrefix(file)
- )
- }
- }
- return []
- }
-
- private readonly logPrefix = (file: string): string => {
- return logPrefix(` Id tags cache for id tags file '${file}' |`)
- }
}
import { LRUMapWithDelete as LRUCache } from 'mnemonist'
-import { isEmpty } from 'rambda'
import type { ChargingStationConfiguration, ChargingStationTemplate } from '../types/index.js'
-import { isNotEmptyArray, isNotEmptyString } from '../utils/index.js'
+
+import { isEmpty, isNotEmptyArray, isNotEmptyString } from '../utils/index.js'
import { Bootstrap } from './Bootstrap.js'
enum CacheType {
+ chargingStationConfiguration = 'chargingStationConfiguration',
chargingStationTemplate = 'chargingStationTemplate',
- chargingStationConfiguration = 'chargingStationConfiguration'
}
-type CacheValueType = ChargingStationTemplate | ChargingStationConfiguration
+type CacheValueType = ChargingStationConfiguration | ChargingStationTemplate
export class SharedLRUCache {
- private static instance: SharedLRUCache | null = null
+ private static instance: null | SharedLRUCache = null
private readonly lruCache: LRUCache<string, CacheValueType>
private constructor () {
}
public static getInstance (): SharedLRUCache {
- if (SharedLRUCache.instance === null) {
- SharedLRUCache.instance = new SharedLRUCache()
- }
+ SharedLRUCache.instance ??= new SharedLRUCache()
return SharedLRUCache.instance
}
- public hasChargingStationConfiguration (chargingStationConfigurationHash: string): boolean {
- return this.has(this.getChargingStationConfigurationKey(chargingStationConfigurationHash))
+ public clear (): void {
+ this.lruCache.clear()
}
- public setChargingStationConfiguration (
- chargingStationConfiguration: ChargingStationConfiguration
- ): void {
- if (this.isChargingStationConfigurationCacheable(chargingStationConfiguration)) {
- this.set(
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.getChargingStationConfigurationKey(chargingStationConfiguration.configurationHash!),
- chargingStationConfiguration
- )
- }
+ public deleteChargingStationConfiguration (chargingStationConfigurationHash: string): void {
+ this.delete(this.getChargingStationConfigurationKey(chargingStationConfigurationHash))
+ }
+
+ public deleteChargingStationTemplate (chargingStationTemplateHash: string): void {
+ this.delete(this.getChargingStationTemplateKey(chargingStationTemplateHash))
}
public getChargingStationConfiguration (
) as ChargingStationConfiguration
}
- public deleteChargingStationConfiguration (chargingStationConfigurationHash: string): void {
- this.delete(this.getChargingStationConfigurationKey(chargingStationConfigurationHash))
+ public getChargingStationTemplate (chargingStationTemplateHash: string): ChargingStationTemplate {
+ return this.get(
+ this.getChargingStationTemplateKey(chargingStationTemplateHash)
+ ) as ChargingStationTemplate
+ }
+
+ public hasChargingStationConfiguration (chargingStationConfigurationHash: string): boolean {
+ return this.has(this.getChargingStationConfigurationKey(chargingStationConfigurationHash))
}
public hasChargingStationTemplate (chargingStationTemplateHash: string): boolean {
return this.has(this.getChargingStationTemplateKey(chargingStationTemplateHash))
}
+ public setChargingStationConfiguration (
+ chargingStationConfiguration: ChargingStationConfiguration
+ ): void {
+ if (this.isChargingStationConfigurationCacheable(chargingStationConfiguration)) {
+ this.set(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.getChargingStationConfigurationKey(chargingStationConfiguration.configurationHash!),
+ chargingStationConfiguration
+ )
+ }
+ }
+
public setChargingStationTemplate (chargingStationTemplate: ChargingStationTemplate): void {
this.set(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
)
}
- public getChargingStationTemplate (chargingStationTemplateHash: string): ChargingStationTemplate {
- return this.get(
- this.getChargingStationTemplateKey(chargingStationTemplateHash)
- ) as ChargingStationTemplate
- }
-
- public deleteChargingStationTemplate (chargingStationTemplateHash: string): void {
- this.delete(this.getChargingStationTemplateKey(chargingStationTemplateHash))
+ private delete (key: string): void {
+ this.lruCache.delete(key)
}
- public clear (): void {
- this.lruCache.clear()
+ private get (key: string): CacheValueType | undefined {
+ return this.lruCache.get(key)
}
private getChargingStationConfigurationKey (hash: string): string {
return this.lruCache.has(key)
}
- private get (key: string): CacheValueType | undefined {
- return this.lruCache.get(key)
- }
-
- private set (key: string, value: CacheValueType): void {
- this.lruCache.set(key, value)
- }
-
- private delete (key: string): void {
- this.lruCache.delete(key)
- }
-
private isChargingStationConfigurationCacheable (
chargingStationConfiguration: ChargingStationConfiguration
): boolean {
isNotEmptyString(chargingStationConfiguration.configurationHash)
)
}
+
+ private set (key: string, value: CacheValueType): void {
+ this.lruCache.set(key, value)
+ }
}
import { secondsToMilliseconds } from 'date-fns'
-import { isEmpty } from 'rambda'
+
+import type { ChargingStation } from '../ChargingStation.js'
import { BaseError, type OCPPError } from '../../exception/index.js'
import {
type StatusNotificationRequest,
type StatusNotificationResponse,
type StopTransactionRequest,
- type StopTransactionResponse
+ type StopTransactionResponse,
} from '../../types/index.js'
-import { Constants, convertToInt, isAsyncFunction, logger } from '../../utils/index.js'
-import type { ChargingStation } from '../ChargingStation.js'
+import { Constants, convertToInt, isAsyncFunction, isEmpty, logger } from '../../utils/index.js'
import { getConfigurationKey } from '../ConfigurationKeyUtils.js'
import { buildMeterValue } from '../ocpp/index.js'
import { WorkerBroadcastChannel } from './WorkerBroadcastChannel.js'
const moduleName = 'ChargingStationWorkerBroadcastChannel'
+type CommandHandler = (
+ requestPayload?: BroadcastChannelRequestPayload
+ // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
+) => CommandResponse | Promise<CommandResponse | void> | void
+
type CommandResponse =
- | EmptyObject
- | StartTransactionResponse
- | StopTransactionResponse
| AuthorizeResponse
| BootNotificationResponse
- | HeartbeatResponse
| DataTransferResponse
-
-type CommandHandler = (
- requestPayload?: BroadcastChannelRequestPayload
- // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
-) => Promise<CommandResponse | void> | CommandResponse | void
+ | EmptyObject
+ | HeartbeatResponse
+ | StartTransactionResponse
+ | StopTransactionResponse
export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChannel {
- private readonly commandHandlers: Map<BroadcastChannelProcedureName, CommandHandler>
private readonly chargingStation: ChargingStation
+ private readonly commandHandlers: Map<BroadcastChannelProcedureName, CommandHandler>
constructor (chargingStation: ChargingStation) {
super()
const requestParams: RequestParams = {
- throwError: true
+ throwError: true,
}
this.commandHandlers = new Map<BroadcastChannelProcedureName, CommandHandler>([
[
- BroadcastChannelProcedureName.START_CHARGING_STATION,
- () => {
- this.chargingStation.start()
- }
- ],
- [
- BroadcastChannelProcedureName.STOP_CHARGING_STATION,
- async () => {
- await this.chargingStation.stop()
- }
+ BroadcastChannelProcedureName.AUTHORIZE,
+ async (requestPayload?: BroadcastChannelRequestPayload) =>
+ await this.chargingStation.ocppRequestService.requestHandler<
+ AuthorizeRequest,
+ AuthorizeResponse
+ >(
+ this.chargingStation,
+ RequestCommand.AUTHORIZE,
+ requestPayload as AuthorizeRequest,
+ requestParams
+ ),
],
[
- BroadcastChannelProcedureName.DELETE_CHARGING_STATIONS,
+ BroadcastChannelProcedureName.BOOT_NOTIFICATION,
async (requestPayload?: BroadcastChannelRequestPayload) => {
- await this.chargingStation.delete(requestPayload?.deleteConfiguration as boolean)
- }
- ],
- [
- BroadcastChannelProcedureName.OPEN_CONNECTION,
- () => {
- this.chargingStation.openWSConnection()
- }
+ return await this.chargingStation.ocppRequestService.requestHandler<
+ BootNotificationRequest,
+ BootNotificationResponse
+ >(
+ this.chargingStation,
+ RequestCommand.BOOT_NOTIFICATION,
+ {
+ ...this.chargingStation.bootNotificationRequest,
+ ...requestPayload,
+ } as BootNotificationRequest,
+ {
+ skipBufferingOnError: true,
+ throwError: true,
+ }
+ )
+ },
],
[
BroadcastChannelProcedureName.CLOSE_CONNECTION,
() => {
this.chargingStation.closeWSConnection()
- }
- ],
- [
- BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
- (requestPayload?: BroadcastChannelRequestPayload) => {
- this.chargingStation.startAutomaticTransactionGenerator(requestPayload?.connectorIds)
- }
+ },
],
[
- BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
- (requestPayload?: BroadcastChannelRequestPayload) => {
- this.chargingStation.stopAutomaticTransactionGenerator(requestPayload?.connectorIds)
- }
- ],
- [
- BroadcastChannelProcedureName.SET_SUPERVISION_URL,
- (requestPayload?: BroadcastChannelRequestPayload) => {
- this.chargingStation.setSupervisionUrl(requestPayload?.url as string)
- }
- ],
- [
- BroadcastChannelProcedureName.START_TRANSACTION,
- async (requestPayload?: BroadcastChannelRequestPayload) =>
- await this.chargingStation.ocppRequestService.requestHandler<
- StartTransactionRequest,
- StartTransactionResponse
- >(this.chargingStation, RequestCommand.START_TRANSACTION, requestPayload, requestParams)
- ],
- [
- BroadcastChannelProcedureName.STOP_TRANSACTION,
+ BroadcastChannelProcedureName.DATA_TRANSFER,
async (requestPayload?: BroadcastChannelRequestPayload) =>
await this.chargingStation.ocppRequestService.requestHandler<
- StopTransactionRequest,
- StartTransactionResponse
+ DataTransferRequest,
+ DataTransferResponse
>(
this.chargingStation,
- RequestCommand.STOP_TRANSACTION,
- {
- meterStop: this.chargingStation.getEnergyActiveImportRegisterByTransactionId(
- requestPayload?.transactionId,
- true
- ),
- ...requestPayload
- },
+ RequestCommand.DATA_TRANSFER,
+ requestPayload as DataTransferRequest,
requestParams
- )
+ ),
],
[
- BroadcastChannelProcedureName.AUTHORIZE,
- async (requestPayload?: BroadcastChannelRequestPayload) =>
- await this.chargingStation.ocppRequestService.requestHandler<
- AuthorizeRequest,
- AuthorizeResponse
- >(this.chargingStation, RequestCommand.AUTHORIZE, requestPayload, requestParams)
+ BroadcastChannelProcedureName.DELETE_CHARGING_STATIONS,
+ async (requestPayload?: BroadcastChannelRequestPayload) => {
+ await this.chargingStation.delete(requestPayload?.deleteConfiguration as boolean)
+ },
],
[
- BroadcastChannelProcedureName.BOOT_NOTIFICATION,
- async (requestPayload?: BroadcastChannelRequestPayload) => {
- this.chargingStation.bootNotificationResponse =
- await this.chargingStation.ocppRequestService.requestHandler<
- BootNotificationRequest,
- BootNotificationResponse
- >(
- this.chargingStation,
- RequestCommand.BOOT_NOTIFICATION,
- {
- ...this.chargingStation.bootNotificationRequest,
- ...requestPayload
- },
- {
- skipBufferingOnError: true,
- throwError: true
- }
- )
- return this.chargingStation.bootNotificationResponse
- }
+ BroadcastChannelProcedureName.DIAGNOSTICS_STATUS_NOTIFICATION,
+ async (requestPayload?: BroadcastChannelRequestPayload) =>
+ await this.chargingStation.ocppRequestService.requestHandler<
+ DiagnosticsStatusNotificationRequest,
+ DiagnosticsStatusNotificationResponse
+ >(
+ this.chargingStation,
+ RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
+ requestPayload as DiagnosticsStatusNotificationRequest,
+ requestParams
+ ),
],
[
- BroadcastChannelProcedureName.STATUS_NOTIFICATION,
+ BroadcastChannelProcedureName.FIRMWARE_STATUS_NOTIFICATION,
async (requestPayload?: BroadcastChannelRequestPayload) =>
await this.chargingStation.ocppRequestService.requestHandler<
- StatusNotificationRequest,
- StatusNotificationResponse
- >(this.chargingStation, RequestCommand.STATUS_NOTIFICATION, requestPayload, requestParams)
+ FirmwareStatusNotificationRequest,
+ FirmwareStatusNotificationResponse
+ >(
+ this.chargingStation,
+ RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
+ requestPayload as FirmwareStatusNotificationRequest,
+ requestParams
+ ),
],
[
BroadcastChannelProcedureName.HEARTBEAT,
async (requestPayload?: BroadcastChannelRequestPayload) =>
await this.chargingStation.ocppRequestService.requestHandler<
- HeartbeatRequest,
- HeartbeatResponse
- >(this.chargingStation, RequestCommand.HEARTBEAT, requestPayload, requestParams)
+ HeartbeatRequest,
+ HeartbeatResponse
+ >(
+ this.chargingStation,
+ RequestCommand.HEARTBEAT,
+ requestPayload as HeartbeatRequest,
+ requestParams
+ ),
],
[
BroadcastChannelProcedureName.METER_VALUES,
StandardParametersKey.MeterValueSampleInterval
)
return await this.chargingStation.ocppRequestService.requestHandler<
- MeterValuesRequest,
- MeterValuesResponse
+ MeterValuesRequest,
+ MeterValuesResponse
>(
this.chargingStation,
RequestCommand.METER_VALUES,
configuredMeterValueSampleInterval != null
? secondsToMilliseconds(convertToInt(configuredMeterValueSampleInterval.value))
: Constants.DEFAULT_METER_VALUES_INTERVAL
- )
+ ),
],
- ...requestPayload
- },
+ ...requestPayload,
+ } as MeterValuesRequest,
requestParams
)
- }
+ },
],
[
- BroadcastChannelProcedureName.DATA_TRANSFER,
+ BroadcastChannelProcedureName.OPEN_CONNECTION,
+ () => {
+ this.chargingStation.openWSConnection()
+ },
+ ],
+ [
+ BroadcastChannelProcedureName.SET_SUPERVISION_URL,
+ (requestPayload?: BroadcastChannelRequestPayload) => {
+ this.chargingStation.setSupervisionUrl(requestPayload?.url as string)
+ },
+ ],
+ [
+ BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
+ (requestPayload?: BroadcastChannelRequestPayload) => {
+ this.chargingStation.startAutomaticTransactionGenerator(requestPayload?.connectorIds)
+ },
+ ],
+ [
+ BroadcastChannelProcedureName.START_CHARGING_STATION,
+ () => {
+ this.chargingStation.start()
+ },
+ ],
+ [
+ BroadcastChannelProcedureName.START_TRANSACTION,
async (requestPayload?: BroadcastChannelRequestPayload) =>
await this.chargingStation.ocppRequestService.requestHandler<
- DataTransferRequest,
- DataTransferResponse
- >(this.chargingStation, RequestCommand.DATA_TRANSFER, requestPayload, requestParams)
+ StartTransactionRequest,
+ StartTransactionResponse
+ >(
+ this.chargingStation,
+ RequestCommand.START_TRANSACTION,
+ requestPayload as StartTransactionRequest,
+ requestParams
+ ),
],
[
- BroadcastChannelProcedureName.DIAGNOSTICS_STATUS_NOTIFICATION,
+ BroadcastChannelProcedureName.STATUS_NOTIFICATION,
async (requestPayload?: BroadcastChannelRequestPayload) =>
await this.chargingStation.ocppRequestService.requestHandler<
- DiagnosticsStatusNotificationRequest,
- DiagnosticsStatusNotificationResponse
+ StatusNotificationRequest,
+ StatusNotificationResponse
>(
this.chargingStation,
- RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
- requestPayload,
+ RequestCommand.STATUS_NOTIFICATION,
+ requestPayload as StatusNotificationRequest,
requestParams
- )
+ ),
],
[
- BroadcastChannelProcedureName.FIRMWARE_STATUS_NOTIFICATION,
+ BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
+ (requestPayload?: BroadcastChannelRequestPayload) => {
+ this.chargingStation.stopAutomaticTransactionGenerator(requestPayload?.connectorIds)
+ },
+ ],
+ [
+ BroadcastChannelProcedureName.STOP_CHARGING_STATION,
+ async () => {
+ await this.chargingStation.stop()
+ },
+ ],
+ [
+ BroadcastChannelProcedureName.STOP_TRANSACTION,
async (requestPayload?: BroadcastChannelRequestPayload) =>
await this.chargingStation.ocppRequestService.requestHandler<
- FirmwareStatusNotificationRequest,
- FirmwareStatusNotificationResponse
+ StopTransactionRequest,
+ StartTransactionResponse
>(
this.chargingStation,
- RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
- requestPayload,
+ RequestCommand.STOP_TRANSACTION,
+ {
+ meterStop: this.chargingStation.getEnergyActiveImportRegisterByTransactionId(
+ requestPayload?.transactionId,
+ true
+ ),
+ ...requestPayload,
+ } as StopTransactionRequest,
requestParams
- )
- ]
+ ),
+ ],
])
this.chargingStation = chargingStation
this.onmessage = this.requestHandler.bind(this) as (message: unknown) => void
this.onmessageerror = this.messageErrorHandler.bind(this) as (message: unknown) => void
}
- private requestHandler (messageEvent: MessageEvent): void {
- const validatedMessageEvent = this.validateMessageEvent(messageEvent)
- if (validatedMessageEvent === false) {
- return
- }
- if (this.isResponse(validatedMessageEvent.data)) {
- return
- }
- const [uuid, command, requestPayload] = validatedMessageEvent.data as BroadcastChannelRequest
- if (
- requestPayload.hashIds != null &&
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- !requestPayload.hashIds.includes(this.chargingStation.stationInfo!.hashId)
- ) {
- return
- }
- if (requestPayload.hashId != null) {
- logger.error(
- `${this.chargingStation.logPrefix()} ${moduleName}.requestHandler: 'hashId' field usage in PDU is deprecated, use 'hashIds' array instead`
- )
- return
- }
- let responsePayload: BroadcastChannelResponsePayload | undefined
- this.commandHandler(command, requestPayload)
- .then(commandResponse => {
- if (commandResponse == null || isEmpty(commandResponse)) {
- responsePayload = {
- hashId: this.chargingStation.stationInfo?.hashId,
- status: ResponseStatus.SUCCESS
- }
- } else {
- responsePayload = this.commandResponseToResponsePayload(
- command,
- requestPayload,
- commandResponse
- )
- }
- })
- .catch((error: unknown) => {
- logger.error(
- `${this.chargingStation.logPrefix()} ${moduleName}.requestHandler: Handle request error:`,
- error
- )
- responsePayload = {
- hashId: this.chargingStation.stationInfo?.hashId,
- status: ResponseStatus.FAILURE,
- command,
- requestPayload,
- errorMessage: (error as OCPPError).message,
- errorStack: (error as OCPPError).stack,
- errorDetails: (error as OCPPError).details
- } satisfies BroadcastChannelResponsePayload
- })
- .finally(() => {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.sendResponse([uuid, responsePayload!])
- })
- }
-
- private messageErrorHandler (messageEvent: MessageEvent): void {
- logger.error(
- `${this.chargingStation.logPrefix()} ${moduleName}.messageErrorHandler: Error at handling message:`,
- messageEvent
- )
+ private cleanRequestPayload (
+ command: BroadcastChannelProcedureName,
+ requestPayload: BroadcastChannelRequestPayload
+ ): void {
+ delete requestPayload.hashId
+ delete requestPayload.hashIds
+ ![
+ BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
+ BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
+ ].includes(command) && delete requestPayload.connectorIds
}
private async commandHandler (
throw new BaseError(`Unknown worker broadcast channel command: '${command}'`)
}
- private cleanRequestPayload (
- command: BroadcastChannelProcedureName,
- requestPayload: BroadcastChannelRequestPayload
- ): void {
- delete requestPayload.hashId
- delete requestPayload.hashIds
- ![
- BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
- BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR
- ].includes(command) && delete requestPayload.connectorIds
- }
-
private commandResponseToResponsePayload (
command: BroadcastChannelProcedureName,
requestPayload: BroadcastChannelRequestPayload,
if (responseStatus === ResponseStatus.SUCCESS) {
return {
hashId: this.chargingStation.stationInfo?.hashId,
- status: responseStatus
+ status: responseStatus,
}
}
return {
- hashId: this.chargingStation.stationInfo?.hashId,
- status: responseStatus,
command,
+ commandResponse,
+ hashId: this.chargingStation.stationInfo?.hashId,
requestPayload,
- commandResponse
+ status: responseStatus,
}
}
commandResponse: CommandResponse
): ResponseStatus {
switch (command) {
+ case BroadcastChannelProcedureName.AUTHORIZE:
case BroadcastChannelProcedureName.START_TRANSACTION:
case BroadcastChannelProcedureName.STOP_TRANSACTION:
- case BroadcastChannelProcedureName.AUTHORIZE:
if (
(
commandResponse as
+ | AuthorizeResponse
| StartTransactionResponse
| StopTransactionResponse
- | AuthorizeResponse
).idTagInfo?.status === AuthorizationStatus.ACCEPTED
) {
return ResponseStatus.SUCCESS
return ResponseStatus.SUCCESS
}
return ResponseStatus.FAILURE
- case BroadcastChannelProcedureName.STATUS_NOTIFICATION:
- case BroadcastChannelProcedureName.METER_VALUES:
- if (isEmpty(commandResponse)) {
+ case BroadcastChannelProcedureName.HEARTBEAT:
+ if ('currentTime' in commandResponse) {
return ResponseStatus.SUCCESS
}
return ResponseStatus.FAILURE
- case BroadcastChannelProcedureName.HEARTBEAT:
- if ('currentTime' in commandResponse) {
+ case BroadcastChannelProcedureName.METER_VALUES:
+ case BroadcastChannelProcedureName.STATUS_NOTIFICATION:
+ if (isEmpty(commandResponse)) {
return ResponseStatus.SUCCESS
}
return ResponseStatus.FAILURE
return ResponseStatus.FAILURE
}
}
+
+ private messageErrorHandler (messageEvent: MessageEvent): void {
+ logger.error(
+ `${this.chargingStation.logPrefix()} ${moduleName}.messageErrorHandler: Error at handling message:`,
+ messageEvent
+ )
+ }
+
+ private requestHandler (messageEvent: MessageEvent): void {
+ const validatedMessageEvent = this.validateMessageEvent(messageEvent)
+ if (validatedMessageEvent === false) {
+ return
+ }
+ if (this.isResponse(validatedMessageEvent.data)) {
+ return
+ }
+ const [uuid, command, requestPayload] = validatedMessageEvent.data as BroadcastChannelRequest
+ if (
+ requestPayload.hashIds != null &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ !requestPayload.hashIds.includes(this.chargingStation.stationInfo!.hashId)
+ ) {
+ return
+ }
+ if (requestPayload.hashId != null) {
+ logger.error(
+ `${this.chargingStation.logPrefix()} ${moduleName}.requestHandler: 'hashId' field usage in PDU is deprecated, use 'hashIds' array instead`
+ )
+ return
+ }
+ let responsePayload: BroadcastChannelResponsePayload | undefined
+ this.commandHandler(command, requestPayload)
+ .then(commandResponse => {
+ if (commandResponse == null || isEmpty(commandResponse)) {
+ responsePayload = {
+ hashId: this.chargingStation.stationInfo?.hashId,
+ status: ResponseStatus.SUCCESS,
+ }
+ } else {
+ responsePayload = this.commandResponseToResponsePayload(
+ command,
+ requestPayload,
+ commandResponse
+ )
+ }
+ return undefined
+ })
+ .finally(() => {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.sendResponse([uuid, responsePayload!])
+ })
+ .catch((error: unknown) => {
+ logger.error(
+ `${this.chargingStation.logPrefix()} ${moduleName}.requestHandler: Handle request error:`,
+ error
+ )
+ responsePayload = {
+ command,
+ errorDetails: (error as OCPPError).details,
+ errorMessage: (error as OCPPError).message,
+ errorStack: (error as OCPPError).stack,
+ hashId: this.chargingStation.stationInfo?.hashId,
+ requestPayload,
+ status: ResponseStatus.FAILURE,
+ } satisfies BroadcastChannelResponsePayload
+ })
+ }
}
+import type { AbstractUIService } from '../ui-server/ui-services/AbstractUIService.js'
+
import {
type BroadcastChannelResponse,
type BroadcastChannelResponsePayload,
type MessageEvent,
type ResponsePayload,
- ResponseStatus
+ ResponseStatus,
} from '../../types/index.js'
import { logger } from '../../utils/index.js'
-import type { AbstractUIService } from '../ui-server/ui-services/AbstractUIService.js'
import { WorkerBroadcastChannel } from './WorkerBroadcastChannel.js'
const moduleName = 'UIServiceWorkerBroadcastChannel'
interface Responses {
+ responses: BroadcastChannelResponsePayload[]
responsesExpected: number
responsesReceived: number
- responses: BroadcastChannelResponsePayload[]
}
export class UIServiceWorkerBroadcastChannel extends WorkerBroadcastChannel {
- private readonly uiService: AbstractUIService
private readonly responses: Map<string, Responses>
+ private readonly uiService: AbstractUIService
constructor (uiService: AbstractUIService) {
super()
this.responses = new Map<string, Responses>()
}
- private responseHandler (messageEvent: MessageEvent): void {
- const validatedMessageEvent = this.validateMessageEvent(messageEvent)
- if (validatedMessageEvent === false) {
- return
- }
- if (this.isRequest(validatedMessageEvent.data)) {
- return
- }
- const [uuid, responsePayload] = validatedMessageEvent.data as BroadcastChannelResponse
- if (!this.responses.has(uuid)) {
- this.responses.set(uuid, {
- responsesExpected: this.uiService.getBroadcastChannelExpectedResponses(uuid),
- responsesReceived: 1,
- responses: [responsePayload]
- })
- } else if (
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.responses.get(uuid)!.responsesReceived <= this.responses.get(uuid)!.responsesExpected
- ) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- ++this.responses.get(uuid)!.responsesReceived
- this.responses.get(uuid)?.responses.push(responsePayload)
- }
- if (
- this.responses.get(uuid)?.responsesReceived === this.responses.get(uuid)?.responsesExpected
- ) {
- this.uiService.sendResponse(uuid, this.buildResponsePayload(uuid))
- this.responses.delete(uuid)
- this.uiService.deleteBroadcastChannelRequest(uuid)
- }
- }
-
private buildResponsePayload (uuid: string): ResponsePayload {
const responsesStatus =
this.responses
? ResponseStatus.SUCCESS
: ResponseStatus.FAILURE
return {
- status: responsesStatus,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-non-null-asserted-optional-chain
hashIdsSucceeded: this.responses
.get(uuid)
- ?.responses.map(({ status, hashId }) => {
+ ?.responses.map(({ hashId, status }) => {
if (hashId != null && status === ResponseStatus.SUCCESS) {
return hashId
}
return undefined
})
- .filter(hashId => hashId != null) as string[],
+ .filter(hashId => hashId != null)!,
+ status: responsesStatus,
...(responsesStatus === ResponseStatus.FAILURE && {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-non-null-asserted-optional-chain
hashIdsFailed: this.responses
.get(uuid)
- ?.responses.map(({ status, hashId }) => {
+ ?.responses.map(({ hashId, status }) => {
if (hashId != null && status === ResponseStatus.FAILURE) {
return hashId
}
return undefined
})
- .filter(hashId => hashId != null) as string[]
+ .filter(hashId => hashId != null)!,
}),
...(responsesStatus === ResponseStatus.FAILURE && {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-non-null-asserted-optional-chain
responsesFailed: this.responses
.get(uuid)
?.responses.map(response => {
}
return undefined
})
- .filter(response => response != null) as BroadcastChannelResponsePayload[]
- })
+ .filter(response => response != null)!,
+ }),
}
}
messageEvent
)
}
+
+ private responseHandler (messageEvent: MessageEvent): void {
+ const validatedMessageEvent = this.validateMessageEvent(messageEvent)
+ if (validatedMessageEvent === false) {
+ return
+ }
+ if (this.isRequest(validatedMessageEvent.data)) {
+ return
+ }
+ const [uuid, responsePayload] = validatedMessageEvent.data as BroadcastChannelResponse
+ if (!this.responses.has(uuid)) {
+ this.responses.set(uuid, {
+ responses: [responsePayload],
+ responsesExpected: this.uiService.getBroadcastChannelExpectedResponses(uuid),
+ responsesReceived: 1,
+ })
+ } else if (
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.responses.get(uuid)!.responsesReceived <= this.responses.get(uuid)!.responsesExpected
+ ) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ++this.responses.get(uuid)!.responsesReceived
+ this.responses.get(uuid)?.responses.push(responsePayload)
+ }
+ if (
+ this.responses.get(uuid)?.responsesReceived === this.responses.get(uuid)?.responsesExpected
+ ) {
+ this.uiService.sendResponse(uuid, this.buildResponsePayload(uuid))
+ this.responses.delete(uuid)
+ this.uiService.deleteBroadcastChannelRequest(uuid)
+ }
+ }
}
BroadcastChannelRequest,
BroadcastChannelResponse,
JsonType,
- MessageEvent
+ MessageEvent,
} from '../../types/index.js'
+
import { logger, logPrefix, validateUUID } from '../../utils/index.js'
const moduleName = 'WorkerBroadcastChannel'
this.postMessage(request)
}
- protected sendResponse (response: BroadcastChannelResponse): void {
- this.postMessage(response)
- }
-
protected isRequest (message: JsonType[]): boolean {
return Array.isArray(message) && message.length === 3
}
return Array.isArray(message) && message.length === 2
}
- protected validateMessageEvent (messageEvent: MessageEvent): MessageEvent | false {
+ protected sendResponse (response: BroadcastChannelResponse): void {
+ this.postMessage(response)
+ }
+
+ protected validateMessageEvent (messageEvent: MessageEvent): false | MessageEvent {
if (!Array.isArray(messageEvent.data)) {
logger.error(
`${this.logPrefix(
export {
addConfigurationKey,
getConfigurationKey,
- setConfigurationKeyValue
+ setConfigurationKeyValue,
} from './ConfigurationKeyUtils.js'
export {
canProceedChargingProfile,
- checkChargingStation,
+ checkChargingStationState,
getConnectorChargingProfiles,
getIdTagsFile,
hasFeatureProfile,
hasReservationExpired,
prepareChargingProfileKind,
removeExpiredReservations,
- resetConnectorStatus
+ resetAuthorizeConnectorStatus,
+ resetConnectorStatus,
} from './Helpers.js'
import { OCPPConstants } from '../OCPPConstants.js'
export class OCPP16Constants extends OCPPConstants {
- static readonly ChargePointStatusChargingStationTransitions: Readonly<
- ConnectorStatusTransition[]
- > = Object.freeze([
+ static readonly ChargePointStatusChargingStationTransitions: readonly ConnectorStatusTransition[] =
+ Object.freeze([
{ to: OCPP16ChargePointStatus.Available },
// { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.Available },
- { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.Unavailable },
- { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.Faulted },
+ {
+ from: OCPP16ChargePointStatus.Available,
+ to: OCPP16ChargePointStatus.Unavailable,
+ },
+ {
+ from: OCPP16ChargePointStatus.Available,
+ to: OCPP16ChargePointStatus.Faulted,
+ },
{ to: OCPP16ChargePointStatus.Unavailable },
- { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.Available },
+ {
+ from: OCPP16ChargePointStatus.Unavailable,
+ to: OCPP16ChargePointStatus.Available,
+ },
// { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.Unavailable },
- { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.Faulted },
+ {
+ from: OCPP16ChargePointStatus.Unavailable,
+ to: OCPP16ChargePointStatus.Faulted,
+ },
{ to: OCPP16ChargePointStatus.Faulted },
- { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Available },
- { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Unavailable }
- // { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Faulted }
+ {
+ from: OCPP16ChargePointStatus.Faulted,
+ to: OCPP16ChargePointStatus.Available,
+ },
+ {
+ from: OCPP16ChargePointStatus.Faulted,
+ to: OCPP16ChargePointStatus.Unavailable,
+ },
+ // { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Faulted }
])
- static readonly ChargePointStatusConnectorTransitions: Readonly<ConnectorStatusTransition[]> =
+ static readonly ChargePointStatusConnectorTransitions: readonly ConnectorStatusTransition[] =
Object.freeze([
{ to: OCPP16ChargePointStatus.Available },
// { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.Available },
- { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.Preparing },
- { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.Charging },
- { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.SuspendedEV },
- { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.SuspendedEVSE },
+ {
+ from: OCPP16ChargePointStatus.Available,
+ to: OCPP16ChargePointStatus.Preparing,
+ },
+ {
+ from: OCPP16ChargePointStatus.Available,
+ to: OCPP16ChargePointStatus.Charging,
+ },
+ {
+ from: OCPP16ChargePointStatus.Available,
+ to: OCPP16ChargePointStatus.SuspendedEV,
+ },
+ {
+ from: OCPP16ChargePointStatus.Available,
+ to: OCPP16ChargePointStatus.SuspendedEVSE,
+ },
// { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.Finishing },
- { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.Reserved },
- { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.Unavailable },
- { from: OCPP16ChargePointStatus.Available, to: OCPP16ChargePointStatus.Faulted },
+ {
+ from: OCPP16ChargePointStatus.Available,
+ to: OCPP16ChargePointStatus.Reserved,
+ },
+ {
+ from: OCPP16ChargePointStatus.Available,
+ to: OCPP16ChargePointStatus.Unavailable,
+ },
+ {
+ from: OCPP16ChargePointStatus.Available,
+ to: OCPP16ChargePointStatus.Faulted,
+ },
// { to: OCPP16ChargePointStatus.Preparing },
- { from: OCPP16ChargePointStatus.Preparing, to: OCPP16ChargePointStatus.Available },
+ {
+ from: OCPP16ChargePointStatus.Preparing,
+ to: OCPP16ChargePointStatus.Available,
+ },
// { from: OCPP16ChargePointStatus.Preparing, to: OCPP16ChargePointStatus.Preparing },
- { from: OCPP16ChargePointStatus.Preparing, to: OCPP16ChargePointStatus.Charging },
- { from: OCPP16ChargePointStatus.Preparing, to: OCPP16ChargePointStatus.SuspendedEV },
- { from: OCPP16ChargePointStatus.Preparing, to: OCPP16ChargePointStatus.SuspendedEVSE },
- { from: OCPP16ChargePointStatus.Preparing, to: OCPP16ChargePointStatus.Finishing },
+ {
+ from: OCPP16ChargePointStatus.Preparing,
+ to: OCPP16ChargePointStatus.Charging,
+ },
+ {
+ from: OCPP16ChargePointStatus.Preparing,
+ to: OCPP16ChargePointStatus.SuspendedEV,
+ },
+ {
+ from: OCPP16ChargePointStatus.Preparing,
+ to: OCPP16ChargePointStatus.SuspendedEVSE,
+ },
+ {
+ from: OCPP16ChargePointStatus.Preparing,
+ to: OCPP16ChargePointStatus.Finishing,
+ },
// { from: OCPP16ChargePointStatus.Preparing, to: OCPP16ChargePointStatus.Reserved },
// { from: OCPP16ChargePointStatus.Preparing, to: OCPP16ChargePointStatus.Unavailable },
- { from: OCPP16ChargePointStatus.Preparing, to: OCPP16ChargePointStatus.Faulted },
+ {
+ from: OCPP16ChargePointStatus.Preparing,
+ to: OCPP16ChargePointStatus.Faulted,
+ },
// { to: OCPP16ChargePointStatus.Charging },
- { from: OCPP16ChargePointStatus.Charging, to: OCPP16ChargePointStatus.Available },
+ {
+ from: OCPP16ChargePointStatus.Charging,
+ to: OCPP16ChargePointStatus.Available,
+ },
// { from: OCPP16ChargePointStatus.Charging, to: OCPP16ChargePointStatus.Preparing },
// { from: OCPP16ChargePointStatus.Charging, to: OCPP16ChargePointStatus.Charging },
- { from: OCPP16ChargePointStatus.Charging, to: OCPP16ChargePointStatus.SuspendedEV },
- { from: OCPP16ChargePointStatus.Charging, to: OCPP16ChargePointStatus.SuspendedEVSE },
- { from: OCPP16ChargePointStatus.Charging, to: OCPP16ChargePointStatus.Finishing },
+ {
+ from: OCPP16ChargePointStatus.Charging,
+ to: OCPP16ChargePointStatus.SuspendedEV,
+ },
+ {
+ from: OCPP16ChargePointStatus.Charging,
+ to: OCPP16ChargePointStatus.SuspendedEVSE,
+ },
+ {
+ from: OCPP16ChargePointStatus.Charging,
+ to: OCPP16ChargePointStatus.Finishing,
+ },
// { from: OCPP16ChargePointStatus.Charging, to: OCPP16ChargePointStatus.Reserved },
- { from: OCPP16ChargePointStatus.Charging, to: OCPP16ChargePointStatus.Unavailable },
- { from: OCPP16ChargePointStatus.Charging, to: OCPP16ChargePointStatus.Faulted },
+ {
+ from: OCPP16ChargePointStatus.Charging,
+ to: OCPP16ChargePointStatus.Unavailable,
+ },
+ {
+ from: OCPP16ChargePointStatus.Charging,
+ to: OCPP16ChargePointStatus.Faulted,
+ },
// { to: OCPP16ChargePointStatus.SuspendedEV },
- { from: OCPP16ChargePointStatus.SuspendedEV, to: OCPP16ChargePointStatus.Available },
+ {
+ from: OCPP16ChargePointStatus.SuspendedEV,
+ to: OCPP16ChargePointStatus.Available,
+ },
// { from: OCPP16ChargePointStatus.SuspendedEV, to: OCPP16ChargePointStatus.Preparing },
- { from: OCPP16ChargePointStatus.SuspendedEV, to: OCPP16ChargePointStatus.Charging },
+ {
+ from: OCPP16ChargePointStatus.SuspendedEV,
+ to: OCPP16ChargePointStatus.Charging,
+ },
// { from: OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.SuspendedEV },
- { from: OCPP16ChargePointStatus.SuspendedEV, to: OCPP16ChargePointStatus.SuspendedEVSE },
- { from: OCPP16ChargePointStatus.SuspendedEV, to: OCPP16ChargePointStatus.Finishing },
+ {
+ from: OCPP16ChargePointStatus.SuspendedEV,
+ to: OCPP16ChargePointStatus.SuspendedEVSE,
+ },
+ {
+ from: OCPP16ChargePointStatus.SuspendedEV,
+ to: OCPP16ChargePointStatus.Finishing,
+ },
// { from: OCPP16ChargePointStatus.SuspendedEV, to: OCPP16ChargePointStatus.Reserved },
- { from: OCPP16ChargePointStatus.SuspendedEV, to: OCPP16ChargePointStatus.Unavailable },
- { from: OCPP16ChargePointStatus.SuspendedEV, to: OCPP16ChargePointStatus.Faulted },
+ {
+ from: OCPP16ChargePointStatus.SuspendedEV,
+ to: OCPP16ChargePointStatus.Unavailable,
+ },
+ {
+ from: OCPP16ChargePointStatus.SuspendedEV,
+ to: OCPP16ChargePointStatus.Faulted,
+ },
// { to: OCPP16ChargePointStatus.SuspendedEVSE },
- { from: OCPP16ChargePointStatus.SuspendedEVSE, to: OCPP16ChargePointStatus.Available },
+ {
+ from: OCPP16ChargePointStatus.SuspendedEVSE,
+ to: OCPP16ChargePointStatus.Available,
+ },
// { from: OCPP16ChargePointStatus.SuspendedEVSE, to: OCPP16ChargePointStatus.Preparing },
- { from: OCPP16ChargePointStatus.SuspendedEVSE, to: OCPP16ChargePointStatus.Charging },
- { from: OCPP16ChargePointStatus.SuspendedEVSE, to: OCPP16ChargePointStatus.SuspendedEV },
+ {
+ from: OCPP16ChargePointStatus.SuspendedEVSE,
+ to: OCPP16ChargePointStatus.Charging,
+ },
+ {
+ from: OCPP16ChargePointStatus.SuspendedEVSE,
+ to: OCPP16ChargePointStatus.SuspendedEV,
+ },
// { from: OCPP16ChargePointStatus.SuspendedEVSE, to: OCPP16ChargePointStatus.SuspendedEVSE },
- { from: OCPP16ChargePointStatus.SuspendedEVSE, to: OCPP16ChargePointStatus.Finishing },
+ {
+ from: OCPP16ChargePointStatus.SuspendedEVSE,
+ to: OCPP16ChargePointStatus.Finishing,
+ },
// { from: OCPP16ChargePointStatus.SuspendedEVSE, to: OCPP16ChargePointStatus.Reserved },
- { from: OCPP16ChargePointStatus.SuspendedEVSE, to: OCPP16ChargePointStatus.Unavailable },
- { from: OCPP16ChargePointStatus.SuspendedEVSE, to: OCPP16ChargePointStatus.Faulted },
+ {
+ from: OCPP16ChargePointStatus.SuspendedEVSE,
+ to: OCPP16ChargePointStatus.Unavailable,
+ },
+ {
+ from: OCPP16ChargePointStatus.SuspendedEVSE,
+ to: OCPP16ChargePointStatus.Faulted,
+ },
// { to: OCPP16ChargePointStatus.Finishing},
- { from: OCPP16ChargePointStatus.Finishing, to: OCPP16ChargePointStatus.Available },
- { from: OCPP16ChargePointStatus.Finishing, to: OCPP16ChargePointStatus.Preparing },
+ {
+ from: OCPP16ChargePointStatus.Finishing,
+ to: OCPP16ChargePointStatus.Available,
+ },
+ {
+ from: OCPP16ChargePointStatus.Finishing,
+ to: OCPP16ChargePointStatus.Preparing,
+ },
// { from: OCPP16ChargePointStatus.Finishing, to: OCPP16ChargePointStatus.Charging },
// { from: OCPP16ChargePointStatus.Finishing, to: OCPP16ChargePointStatus.SuspendedEV },
// { from: OCPP16ChargePointStatus.Finishing, to: OCPP16ChargePointStatus.SuspendedEVSE },
// { from: OCPP16ChargePointStatus.Finishing, to: OCPP16ChargePointStatus.Finishing },
// { from: OCPP16ChargePointStatus.Finishing, to: OCPP16ChargePointStatus.Reserved },
- { from: OCPP16ChargePointStatus.Finishing, to: OCPP16ChargePointStatus.Unavailable },
- { from: OCPP16ChargePointStatus.Finishing, to: OCPP16ChargePointStatus.Faulted },
+ {
+ from: OCPP16ChargePointStatus.Finishing,
+ to: OCPP16ChargePointStatus.Unavailable,
+ },
+ {
+ from: OCPP16ChargePointStatus.Finishing,
+ to: OCPP16ChargePointStatus.Faulted,
+ },
// { to: OCPP16ChargePointStatus.Reserved },
- { from: OCPP16ChargePointStatus.Reserved, to: OCPP16ChargePointStatus.Available },
- { from: OCPP16ChargePointStatus.Reserved, to: OCPP16ChargePointStatus.Preparing },
+ {
+ from: OCPP16ChargePointStatus.Reserved,
+ to: OCPP16ChargePointStatus.Available,
+ },
+ {
+ from: OCPP16ChargePointStatus.Reserved,
+ to: OCPP16ChargePointStatus.Preparing,
+ },
// { from: OCPP16ChargePointStatus.Reserved, to: OCPP16ChargePointStatus.Charging },
// { from: OCPP16ChargePointStatus.Reserved, to: OCPP16ChargePointStatus.SuspendedEV },
// { from: OCPP16ChargePointStatus.Reserved, to: OCPP16ChargePointStatus.SuspendedEVSE },
// { from: OCPP16ChargePointStatus.Reserved, to: OCPP16ChargePointStatus.Finishing },
// { from: OCPP16ChargePointStatus.Reserved, to: OCPP16ChargePointStatus.Reserved },
- { from: OCPP16ChargePointStatus.Reserved, to: OCPP16ChargePointStatus.Unavailable },
- { from: OCPP16ChargePointStatus.Reserved, to: OCPP16ChargePointStatus.Faulted },
+ {
+ from: OCPP16ChargePointStatus.Reserved,
+ to: OCPP16ChargePointStatus.Unavailable,
+ },
+ {
+ from: OCPP16ChargePointStatus.Reserved,
+ to: OCPP16ChargePointStatus.Faulted,
+ },
{ to: OCPP16ChargePointStatus.Unavailable },
- { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.Available },
- { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.Preparing },
- { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.Charging },
- { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.SuspendedEV },
- { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.SuspendedEVSE },
+ {
+ from: OCPP16ChargePointStatus.Unavailable,
+ to: OCPP16ChargePointStatus.Available,
+ },
+ {
+ from: OCPP16ChargePointStatus.Unavailable,
+ to: OCPP16ChargePointStatus.Preparing,
+ },
+ {
+ from: OCPP16ChargePointStatus.Unavailable,
+ to: OCPP16ChargePointStatus.Charging,
+ },
+ {
+ from: OCPP16ChargePointStatus.Unavailable,
+ to: OCPP16ChargePointStatus.SuspendedEV,
+ },
+ {
+ from: OCPP16ChargePointStatus.Unavailable,
+ to: OCPP16ChargePointStatus.SuspendedEVSE,
+ },
// { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.Finishing },
// { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.Reserved },
// { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.Unavailable },
- { from: OCPP16ChargePointStatus.Unavailable, to: OCPP16ChargePointStatus.Faulted },
+ {
+ from: OCPP16ChargePointStatus.Unavailable,
+ to: OCPP16ChargePointStatus.Faulted,
+ },
{ to: OCPP16ChargePointStatus.Faulted },
- { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Available },
- { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Preparing },
- { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Charging },
- { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.SuspendedEV },
- { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.SuspendedEVSE },
- { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Finishing },
- { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Reserved },
- { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Unavailable }
+ {
+ from: OCPP16ChargePointStatus.Faulted,
+ to: OCPP16ChargePointStatus.Available,
+ },
+ {
+ from: OCPP16ChargePointStatus.Faulted,
+ to: OCPP16ChargePointStatus.Preparing,
+ },
+ {
+ from: OCPP16ChargePointStatus.Faulted,
+ to: OCPP16ChargePointStatus.Charging,
+ },
+ {
+ from: OCPP16ChargePointStatus.Faulted,
+ to: OCPP16ChargePointStatus.SuspendedEV,
+ },
+ {
+ from: OCPP16ChargePointStatus.Faulted,
+ to: OCPP16ChargePointStatus.SuspendedEVSE,
+ },
+ {
+ from: OCPP16ChargePointStatus.Faulted,
+ to: OCPP16ChargePointStatus.Finishing,
+ },
+ {
+ from: OCPP16ChargePointStatus.Faulted,
+ to: OCPP16ChargePointStatus.Reserved,
+ },
+ {
+ from: OCPP16ChargePointStatus.Faulted,
+ to: OCPP16ChargePointStatus.Unavailable,
+ },
// { from: OCPP16ChargePointStatus.Faulted, to: OCPP16ChargePointStatus.Faulted }
])
}
// Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
-import { randomInt } from 'node:crypto'
-import { createWriteStream, readdirSync } from 'node:fs'
-import { dirname, extname, join, resolve } from 'node:path'
-import { fileURLToPath, URL } from 'node:url'
-
import type { ValidateFunction } from 'ajv'
+
import { Client, type FTPResponse } from 'basic-ftp'
import {
addSeconds,
differenceInSeconds,
type Interval,
isDate,
- secondsToMilliseconds
+ secondsToMilliseconds,
} from 'date-fns'
import { maxTime } from 'date-fns/constants'
-import { isEmpty } from 'rambda'
+import { randomInt } from 'node:crypto'
+import { createWriteStream, readdirSync } from 'node:fs'
+import { dirname, extname, join, resolve } from 'node:path'
+import { fileURLToPath, URL } from 'node:url'
import { create } from 'tar'
import {
canProceedChargingProfile,
type ChargingStation,
- checkChargingStation,
+ checkChargingStationState,
getConfigurationKey,
getConnectorChargingProfiles,
prepareChargingProfileKind,
removeExpiredReservations,
- setConfigurationKeyValue
+ resetAuthorizeConnectorStatus,
+ setConfigurationKeyValue,
} from '../../../charging-station/index.js'
import { OCPPError } from '../../../exception/index.js'
import {
type OCPP16ClearChargingProfileResponse,
type OCPP16DataTransferRequest,
type OCPP16DataTransferResponse,
- OCPP16DataTransferVendorId,
OCPP16DiagnosticsStatus,
type OCPP16DiagnosticsStatusNotificationRequest,
type OCPP16DiagnosticsStatusNotificationResponse,
type SetChargingProfileRequest,
type SetChargingProfileResponse,
type UnlockConnectorRequest,
- type UnlockConnectorResponse
+ type UnlockConnectorResponse,
} from '../../../types/index.js'
import {
Configuration,
convertToDate,
convertToInt,
formatDurationMilliSeconds,
+ handleIncomingRequestError,
isAsyncFunction,
+ isEmpty,
isNotEmptyArray,
isNotEmptyString,
logger,
- sleep
+ sleep,
} from '../../../utils/index.js'
import { OCPPIncomingRequestService } from '../OCPPIncomingRequestService.js'
import { OCPP16Constants } from './OCPP16Constants.js'
protected payloadValidateFunctions: Map<OCPP16IncomingRequestCommand, ValidateFunction<JsonType>>
private readonly incomingRequestHandlers: Map<
- OCPP16IncomingRequestCommand,
- IncomingRequestHandler
+ OCPP16IncomingRequestCommand,
+ IncomingRequestHandler
>
public constructor () {
super(OCPPVersion.VERSION_16)
this.incomingRequestHandlers = new Map<OCPP16IncomingRequestCommand, IncomingRequestHandler>([
[
- OCPP16IncomingRequestCommand.RESET,
- this.handleRequestReset.bind(this) as unknown as IncomingRequestHandler
+ OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
+ this.handleRequestCancelReservation.bind(this) as unknown as IncomingRequestHandler,
],
[
- OCPP16IncomingRequestCommand.CLEAR_CACHE,
- this.handleRequestClearCache.bind(this) as IncomingRequestHandler
+ OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY,
+ this.handleRequestChangeAvailability.bind(this) as unknown as IncomingRequestHandler,
],
[
- OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR,
- this.handleRequestUnlockConnector.bind(this) as unknown as IncomingRequestHandler
+ OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION,
+ this.handleRequestChangeConfiguration.bind(this) as unknown as IncomingRequestHandler,
],
[
- OCPP16IncomingRequestCommand.GET_CONFIGURATION,
- this.handleRequestGetConfiguration.bind(this) as IncomingRequestHandler
+ OCPP16IncomingRequestCommand.CLEAR_CACHE,
+ this.handleRequestClearCache.bind(this) as IncomingRequestHandler,
],
[
- OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION,
- this.handleRequestChangeConfiguration.bind(this) as unknown as IncomingRequestHandler
+ OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
+ this.handleRequestClearChargingProfile.bind(this) as IncomingRequestHandler,
],
[
- OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE,
- this.handleRequestGetCompositeSchedule.bind(this) as unknown as IncomingRequestHandler
+ OCPP16IncomingRequestCommand.DATA_TRANSFER,
+ this.handleRequestDataTransfer.bind(this) as unknown as IncomingRequestHandler,
],
[
- OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
- this.handleRequestSetChargingProfile.bind(this) as unknown as IncomingRequestHandler
+ OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE,
+ this.handleRequestGetCompositeSchedule.bind(this) as unknown as IncomingRequestHandler,
],
[
- OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
- this.handleRequestClearChargingProfile.bind(this) as IncomingRequestHandler
+ OCPP16IncomingRequestCommand.GET_CONFIGURATION,
+ this.handleRequestGetConfiguration.bind(this) as IncomingRequestHandler,
],
[
- OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY,
- this.handleRequestChangeAvailability.bind(this) as unknown as IncomingRequestHandler
+ OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
+ this.handleRequestGetDiagnostics.bind(this) as IncomingRequestHandler,
],
[
OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION,
- this.handleRequestRemoteStartTransaction.bind(this) as unknown as IncomingRequestHandler
+ this.handleRequestRemoteStartTransaction.bind(this) as unknown as IncomingRequestHandler,
],
[
OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION,
- this.handleRequestRemoteStopTransaction.bind(this) as unknown as IncomingRequestHandler
+ this.handleRequestRemoteStopTransaction.bind(this) as unknown as IncomingRequestHandler,
],
[
- OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
- this.handleRequestGetDiagnostics.bind(this) as IncomingRequestHandler
+ OCPP16IncomingRequestCommand.RESERVE_NOW,
+ this.handleRequestReserveNow.bind(this) as unknown as IncomingRequestHandler,
],
[
- OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
- this.handleRequestTriggerMessage.bind(this) as unknown as IncomingRequestHandler
+ OCPP16IncomingRequestCommand.RESET,
+ this.handleRequestReset.bind(this) as unknown as IncomingRequestHandler,
],
[
- OCPP16IncomingRequestCommand.DATA_TRANSFER,
- this.handleRequestDataTransfer.bind(this) as unknown as IncomingRequestHandler
+ OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
+ this.handleRequestSetChargingProfile.bind(this) as unknown as IncomingRequestHandler,
],
[
- OCPP16IncomingRequestCommand.UPDATE_FIRMWARE,
- this.handleRequestUpdateFirmware.bind(this) as unknown as IncomingRequestHandler
+ OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
+ this.handleRequestTriggerMessage.bind(this) as unknown as IncomingRequestHandler,
],
[
- OCPP16IncomingRequestCommand.RESERVE_NOW,
- this.handleRequestReserveNow.bind(this) as unknown as IncomingRequestHandler
+ OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR,
+ this.handleRequestUnlockConnector.bind(this) as unknown as IncomingRequestHandler,
],
[
- OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
- this.handleRequestCancelReservation.bind(this) as unknown as IncomingRequestHandler
- ]
+ OCPP16IncomingRequestCommand.UPDATE_FIRMWARE,
+ this.handleRequestUpdateFirmware.bind(this) as unknown as IncomingRequestHandler,
+ ],
])
this.payloadValidateFunctions = new Map<
- OCPP16IncomingRequestCommand,
- ValidateFunction<JsonType>
+ OCPP16IncomingRequestCommand,
+ ValidateFunction<JsonType>
>([
[
- OCPP16IncomingRequestCommand.RESET,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<ResetRequest>(
- 'assets/json-schemas/ocpp/1.6/Reset.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16CancelReservationRequest>(
+ 'assets/json-schemas/ocpp/1.6/CancelReservation.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.CLEAR_CACHE,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ClearCacheRequest>(
- 'assets/json-schemas/ocpp/1.6/ClearCache.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ChangeAvailabilityRequest>(
+ 'assets/json-schemas/ocpp/1.6/ChangeAvailability.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<UnlockConnectorRequest>(
- 'assets/json-schemas/ocpp/1.6/UnlockConnector.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<ChangeConfigurationRequest>(
+ 'assets/json-schemas/ocpp/1.6/ChangeConfiguration.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.GET_CONFIGURATION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<GetConfigurationRequest>(
- 'assets/json-schemas/ocpp/1.6/GetConfiguration.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.CLEAR_CACHE,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ClearCacheRequest>(
+ 'assets/json-schemas/ocpp/1.6/ClearCache.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<ChangeConfigurationRequest>(
- 'assets/json-schemas/ocpp/1.6/ChangeConfiguration.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ClearChargingProfileRequest>(
+ 'assets/json-schemas/ocpp/1.6/ClearChargingProfile.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<GetDiagnosticsRequest>(
- 'assets/json-schemas/ocpp/1.6/GetDiagnostics.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.DATA_TRANSFER,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferRequest>(
+ 'assets/json-schemas/ocpp/1.6/DataTransfer.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16GetCompositeScheduleRequest>(
- 'assets/json-schemas/ocpp/1.6/GetCompositeSchedule.json',
- moduleName,
- 'constructor'
- )
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16GetCompositeScheduleRequest>(
+ 'assets/json-schemas/ocpp/1.6/GetCompositeSchedule.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<SetChargingProfileRequest>(
- 'assets/json-schemas/ocpp/1.6/SetChargingProfile.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.GET_CONFIGURATION,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<GetConfigurationRequest>(
+ 'assets/json-schemas/ocpp/1.6/GetConfiguration.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ClearChargingProfileRequest>(
- 'assets/json-schemas/ocpp/1.6/ClearChargingProfile.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<GetDiagnosticsRequest>(
+ 'assets/json-schemas/ocpp/1.6/GetDiagnostics.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ChangeAvailabilityRequest>(
- 'assets/json-schemas/ocpp/1.6/ChangeAvailability.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<RemoteStartTransactionRequest>(
+ 'assets/json-schemas/ocpp/1.6/RemoteStartTransaction.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<RemoteStartTransactionRequest>(
- 'assets/json-schemas/ocpp/1.6/RemoteStartTransaction.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<RemoteStopTransactionRequest>(
+ 'assets/json-schemas/ocpp/1.6/RemoteStopTransaction.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<RemoteStopTransactionRequest>(
- 'assets/json-schemas/ocpp/1.6/RemoteStopTransaction.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.RESERVE_NOW,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ReserveNowRequest>(
+ 'assets/json-schemas/ocpp/1.6/ReserveNow.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16TriggerMessageRequest>(
- 'assets/json-schemas/ocpp/1.6/TriggerMessage.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.RESET,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<ResetRequest>(
+ 'assets/json-schemas/ocpp/1.6/Reset.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.DATA_TRANSFER,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferRequest>(
- 'assets/json-schemas/ocpp/1.6/DataTransfer.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<SetChargingProfileRequest>(
+ 'assets/json-schemas/ocpp/1.6/SetChargingProfile.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.UPDATE_FIRMWARE,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16UpdateFirmwareRequest>(
- 'assets/json-schemas/ocpp/1.6/UpdateFirmware.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16TriggerMessageRequest>(
+ 'assets/json-schemas/ocpp/1.6/TriggerMessage.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.RESERVE_NOW,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ReserveNowRequest>(
- 'assets/json-schemas/ocpp/1.6/ReserveNow.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<UnlockConnectorRequest>(
+ 'assets/json-schemas/ocpp/1.6/UnlockConnector.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16CancelReservationRequest>(
- 'assets/json-schemas/ocpp/1.6/CancelReservation.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.UPDATE_FIRMWARE,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16UpdateFirmwareRequest>(
+ 'assets/json-schemas/ocpp/1.6/UpdateFirmware.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
- ]
+ ),
+ ],
])
// Handle incoming request events
this.on(
if (response.status === GenericStatus.Accepted) {
const { connectorId, idTag } = request
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- chargingStation.getConnectorStatus(connectorId)!.transactionRemoteStarted = true
+ chargingStation.getConnectorStatus(connectorId!)!.transactionRemoteStarted = true
chargingStation.ocppRequestService
.requestHandler<Partial<OCPP16StartTransactionRequest>, OCPP16StartTransactionResponse>(
- chargingStation,
- OCPP16RequestCommand.START_TRANSACTION,
- {
- connectorId,
- idTag
- }
- )
+ chargingStation,
+ OCPP16RequestCommand.START_TRANSACTION,
+ {
+ connectorId,
+ idTag,
+ }
+ )
.then(response => {
- if (response.status === OCPP16AuthorizationStatus.ACCEPTED) {
+ if (response.idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED) {
logger.debug(
- `${chargingStation.logPrefix()} Remote start transaction ACCEPTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId} for idTag '${idTag}'`
+ `${chargingStation.logPrefix()} Remote start transaction ACCEPTED on ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ chargingStation.stationInfo?.chargingStationId
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ }#${connectorId?.toString()} for idTag '${idTag}'`
)
} else {
logger.debug(
- `${chargingStation.logPrefix()} Remote start transaction REJECTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId} for idTag '${idTag}'`
+ `${chargingStation.logPrefix()} Remote start transaction REJECTED on ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ chargingStation.stationInfo?.chargingStationId
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ }#${connectorId?.toString()} for idTag '${idTag}'`
)
}
+ return undefined
})
.catch((error: unknown) => {
logger.error(
.then(response => {
if (response.status === GenericStatus.Accepted) {
logger.debug(
- `${chargingStation.logPrefix()} Remote stop transaction ACCEPTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId} for transaction '${transactionId}'`
+ `${chargingStation.logPrefix()} Remote stop transaction ACCEPTED on ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ chargingStation.stationInfo?.chargingStationId
+ }#${connectorId.toString()} for transaction '${transactionId.toString()}'`
)
} else {
logger.debug(
- `${chargingStation.logPrefix()} Remote stop transaction REJECTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId} for transaction '${transactionId}'`
+ `${chargingStation.logPrefix()} Remote stop transaction REJECTED on ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ chargingStation.stationInfo?.chargingStationId
+ }#${connectorId.toString()} for transaction '${transactionId.toString()}'`
)
}
+ return undefined
})
.catch((error: unknown) => {
logger.error(
if (response.status !== OCPP16TriggerMessageStatus.ACCEPTED) {
return
}
- const { requestedMessage, connectorId } = request
+ const { connectorId, requestedMessage } = request
const errorHandler = (error: unknown): void => {
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.constructor: Trigger ${requestedMessage} error:`,
switch (requestedMessage) {
case OCPP16MessageTrigger.BootNotification:
chargingStation.ocppRequestService
- .requestHandler<OCPP16BootNotificationRequest, OCPP16BootNotificationResponse>(
- chargingStation,
- OCPP16RequestCommand.BOOT_NOTIFICATION,
- chargingStation.bootNotificationRequest as OCPP16BootNotificationRequest,
- { skipBufferingOnError: true, triggerMessage: true }
- )
- .then(response => {
- chargingStation.bootNotificationResponse = response
- })
+ .requestHandler<
+ OCPP16BootNotificationRequest,
+ OCPP16BootNotificationResponse
+ >(chargingStation, OCPP16RequestCommand.BOOT_NOTIFICATION, chargingStation.bootNotificationRequest as OCPP16BootNotificationRequest, { skipBufferingOnError: true, triggerMessage: true })
.catch(errorHandler)
break
case OCPP16MessageTrigger.Heartbeat:
chargingStation.ocppRequestService
.requestHandler<OCPP16HeartbeatRequest, OCPP16HeartbeatResponse>(
- chargingStation,
- OCPP16RequestCommand.HEARTBEAT,
- undefined,
- {
- triggerMessage: true
- }
- )
+ chargingStation,
+ OCPP16RequestCommand.HEARTBEAT,
+ undefined,
+ {
+ triggerMessage: true,
+ }
+ )
.catch(errorHandler)
break
case OCPP16MessageTrigger.StatusNotification:
if (connectorId != null) {
chargingStation.ocppRequestService
.requestHandler<OCPP16StatusNotificationRequest, OCPP16StatusNotificationResponse>(
- chargingStation,
- OCPP16RequestCommand.STATUS_NOTIFICATION,
- {
- connectorId,
- errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
- status: chargingStation.getConnectorStatus(connectorId)
- ?.status as OCPP16ChargePointStatus
- },
- {
- triggerMessage: true
- }
- )
+ chargingStation,
+ OCPP16RequestCommand.STATUS_NOTIFICATION,
+ {
+ connectorId,
+ errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
+ status: chargingStation.getConnectorStatus(connectorId)
+ ?.status as OCPP16ChargePointStatus,
+ },
+ {
+ triggerMessage: true,
+ }
+ )
.catch(errorHandler)
} else if (chargingStation.hasEvses) {
for (const evseStatus of chargingStation.evses.values()) {
for (const [id, connectorStatus] of evseStatus.connectors) {
chargingStation.ocppRequestService
.requestHandler<
- OCPP16StatusNotificationRequest,
- OCPP16StatusNotificationResponse
+ OCPP16StatusNotificationRequest,
+ OCPP16StatusNotificationResponse
+ >(
+ chargingStation,
+ OCPP16RequestCommand.STATUS_NOTIFICATION,
+ {
+ connectorId: id,
+ errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
+ status: connectorStatus.status as OCPP16ChargePointStatus,
+ },
+ {
+ triggerMessage: true,
+ }
+ )
+ .catch(errorHandler)
+ }
+ }
+ } else {
+ for (const [id, connectorStatus] of chargingStation.connectors) {
+ chargingStation.ocppRequestService
+ .requestHandler<
+ OCPP16StatusNotificationRequest,
+ OCPP16StatusNotificationResponse
>(
chargingStation,
OCPP16RequestCommand.STATUS_NOTIFICATION,
{
connectorId: id,
errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
- status: connectorStatus.status as OCPP16ChargePointStatus
+ status: connectorStatus.status as OCPP16ChargePointStatus,
},
{
- triggerMessage: true
+ triggerMessage: true,
}
)
- .catch(errorHandler)
- }
- }
- } else {
- for (const [id, connectorStatus] of chargingStation.connectors) {
- chargingStation.ocppRequestService
- .requestHandler<
- OCPP16StatusNotificationRequest,
- OCPP16StatusNotificationResponse
- >(
- chargingStation,
- OCPP16RequestCommand.STATUS_NOTIFICATION,
- {
- connectorId: id,
- errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
- status: connectorStatus.status as OCPP16ChargePointStatus
- },
- {
- triggerMessage: true
- }
- )
.catch(errorHandler)
}
}
this.validatePayload = this.validatePayload.bind(this)
}
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
public async incomingRequestHandler<ReqType extends JsonType, ResType extends JsonType>(
chargingStation: ChargingStation,
messageId: string,
)
}
if (
- chargingStation.isRegistered() ||
+ chargingStation.inAcceptedState() ||
+ chargingStation.inPendingState() ||
(chargingStation.stationInfo?.ocppStrictCompliance === false &&
chargingStation.inUnknownState())
) {
// Throw exception
throw new OCPPError(
ErrorType.NOT_IMPLEMENTED,
- `'${commandName}' is not implemented to handle request PDU ${JSON.stringify(
+ `${commandName} is not implemented to handle request PDU ${JSON.stringify(
commandPayload,
undefined,
2
this.emit(commandName, chargingStation, commandPayload, response)
}
- private validatePayload (
+ private async handleRequestCancelReservation (
chargingStation: ChargingStation,
- commandName: OCPP16IncomingRequestCommand,
- commandPayload: JsonType
- ): boolean {
- if (this.payloadValidateFunctions.has(commandName)) {
- return this.validateIncomingRequestPayload(chargingStation, commandName, commandPayload)
+ commandPayload: OCPP16CancelReservationRequest
+ ): Promise<GenericResponse> {
+ if (
+ !OCPP16ServiceUtils.checkFeatureProfile(
+ chargingStation,
+ OCPP16SupportedFeatureProfiles.Reservation,
+ OCPP16IncomingRequestCommand.CANCEL_RESERVATION
+ )
+ ) {
+ return OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED
+ }
+ try {
+ const { reservationId } = commandPayload
+ const reservation = chargingStation.getReservationBy('reservationId', reservationId)
+ if (reservation == null) {
+ logger.debug(
+ `${chargingStation.logPrefix()} Reservation with id ${reservationId.toString()} does not exist on charging station`
+ )
+ return OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED
+ }
+ await chargingStation.removeReservation(
+ reservation,
+ ReservationTerminationReason.RESERVATION_CANCELED
+ )
+ return OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_ACCEPTED
+ } catch (error) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return handleIncomingRequestError<GenericResponse>(
+ chargingStation,
+ OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
+ error as Error,
+ {
+ errorResponse: OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED,
+ }
+ )!
}
- logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema validation function found for command '${commandName}' PDU validation`
- )
- return false
- }
-
- // Simulate charging station restart
- private handleRequestReset (
- chargingStation: ChargingStation,
- commandPayload: ResetRequest
- ): GenericResponse {
- const { type } = commandPayload
- chargingStation
- .reset(`${type}Reset` as OCPP16StopTransactionReason)
- .catch(Constants.EMPTY_FUNCTION)
- logger.info(
- `${chargingStation.logPrefix()} ${type} reset command received, simulating it. The station will be back online in ${formatDurationMilliSeconds(
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- chargingStation.stationInfo!.resetTime!
- )}`
- )
- return OCPP16Constants.OCPP_RESPONSE_ACCEPTED
}
- private async handleRequestUnlockConnector (
+ private async handleRequestChangeAvailability (
chargingStation: ChargingStation,
- commandPayload: UnlockConnectorRequest
- ): Promise<UnlockConnectorResponse> {
- const { connectorId } = commandPayload
+ commandPayload: OCPP16ChangeAvailabilityRequest
+ ): Promise<OCPP16ChangeAvailabilityResponse> {
+ const { connectorId, type } = commandPayload
if (!chargingStation.hasConnector(connectorId)) {
logger.error(
- `${chargingStation.logPrefix()} Trying to unlock a non existing connector id ${connectorId}`
+ `${chargingStation.logPrefix()} Trying to change the availability of a non existing connector id ${connectorId.toString()}`
)
- return OCPP16Constants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED
+ return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_REJECTED
}
+ const chargePointStatus: OCPP16ChargePointStatus =
+ type === OCPP16AvailabilityType.Operative
+ ? OCPP16ChargePointStatus.Available
+ : OCPP16ChargePointStatus.Unavailable
if (connectorId === 0) {
- logger.error(`${chargingStation.logPrefix()} Trying to unlock connector id ${connectorId}`)
- return OCPP16Constants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED
- }
- if (chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
- const stopResponse = await chargingStation.stopTransactionOnConnector(
- connectorId,
- OCPP16StopTransactionReason.UNLOCK_COMMAND
- )
- if (stopResponse.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
- return OCPP16Constants.OCPP_RESPONSE_UNLOCKED
+ let response: OCPP16ChangeAvailabilityResponse | undefined
+ if (chargingStation.hasEvses) {
+ for (const evseStatus of chargingStation.evses.values()) {
+ response = await OCPP16ServiceUtils.changeAvailability(
+ chargingStation,
+ [...evseStatus.connectors.keys()],
+ chargePointStatus,
+ type
+ )
+ }
+ } else {
+ response = await OCPP16ServiceUtils.changeAvailability(
+ chargingStation,
+ [...chargingStation.connectors.keys()],
+ chargePointStatus,
+ type
+ )
}
- return OCPP16Constants.OCPP_RESPONSE_UNLOCK_FAILED
- }
- await OCPP16ServiceUtils.sendAndSetConnectorStatus(
- chargingStation,
- connectorId,
- OCPP16ChargePointStatus.Available
- )
- return OCPP16Constants.OCPP_RESPONSE_UNLOCKED
- }
-
- private handleRequestGetConfiguration (
- chargingStation: ChargingStation,
- commandPayload: GetConfigurationRequest
- ): GetConfigurationResponse {
- const { key } = commandPayload
- const configurationKey: OCPPConfigurationKey[] = []
- const unknownKey: string[] = []
- if (key == null) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- for (const configKey of chargingStation.ocppConfiguration!.configurationKey!) {
- if (!OCPP16ServiceUtils.isConfigurationKeyVisible(configKey)) {
- continue
- }
- configurationKey.push({
- key: configKey.key,
- readonly: configKey.readonly,
- value: configKey.value
- })
- }
- } else if (isNotEmptyArray(key)) {
- for (const k of key) {
- const keyFound = getConfigurationKey(chargingStation, k, true)
- if (keyFound != null) {
- if (!OCPP16ServiceUtils.isConfigurationKeyVisible(keyFound)) {
- continue
- }
- configurationKey.push({
- key: keyFound.key,
- readonly: keyFound.readonly,
- value: keyFound.value
- })
- } else {
- unknownKey.push(k)
- }
+ return response!
+ } else if (
+ connectorId > 0 &&
+ (chargingStation.isChargingStationAvailable() ||
+ (!chargingStation.isChargingStationAvailable() &&
+ type === OCPP16AvailabilityType.Inoperative))
+ ) {
+ if (chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.getConnectorStatus(connectorId)!.availability = type
+ return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED
}
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.getConnectorStatus(connectorId)!.availability = type
+ await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+ chargingStation,
+ connectorId,
+ chargePointStatus
+ )
+ return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED
}
- return {
- configurationKey,
- unknownKey
- }
+ return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_REJECTED
}
private handleRequestChangeConfiguration (
) {
chargingStation.restartWebSocketPing()
}
+ if (
+ (keyToChange.key as OCPP16StandardParametersKey) ===
+ OCPP16StandardParametersKey.MeterValueSampleInterval &&
+ chargingStation.getNumberOfRunningTransactions() > 0 &&
+ valueChanged
+ ) {
+ for (
+ let connectorId = 1;
+ connectorId <= chargingStation.getNumberOfConnectors();
+ connectorId++
+ ) {
+ if (chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
+ chargingStation.restartMeterValues(
+ connectorId,
+ secondsToMilliseconds(convertToInt(value))
+ )
+ }
+ }
+ }
if (keyToChange.reboot === true) {
return OCPP16Constants.OCPP_CONFIGURATION_RESPONSE_REBOOT_REQUIRED
}
return OCPP16Constants.OCPP_CONFIGURATION_RESPONSE_NOT_SUPPORTED
}
- private handleRequestSetChargingProfile (
+ private handleRequestClearChargingProfile (
chargingStation: ChargingStation,
- commandPayload: SetChargingProfileRequest
- ): SetChargingProfileResponse {
+ commandPayload: OCPP16ClearChargingProfileRequest
+ ): OCPP16ClearChargingProfileResponse {
if (
!OCPP16ServiceUtils.checkFeatureProfile(
chargingStation,
OCPP16SupportedFeatureProfiles.SmartCharging,
- OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE
- )
- ) {
- return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_NOT_SUPPORTED
- }
- const { connectorId, csChargingProfiles } = commandPayload
- if (!chargingStation.hasConnector(connectorId)) {
- logger.error(
- `${chargingStation.logPrefix()} Trying to set charging profile(s) to a non existing connector id ${connectorId}`
+ OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE
)
- return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED
- }
- if (
- csChargingProfiles.chargingProfilePurpose ===
- OCPP16ChargingProfilePurposeType.CHARGE_POINT_MAX_PROFILE &&
- connectorId !== 0
- ) {
- return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED
- }
- if (
- csChargingProfiles.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE &&
- connectorId === 0
) {
- logger.error(
- `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${connectorId}`
- )
- return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED
+ return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN
}
- const connectorStatus = chargingStation.getConnectorStatus(connectorId)
- if (
- csChargingProfiles.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE &&
- connectorId > 0 &&
- connectorStatus?.transactionStarted === false
- ) {
- logger.error(
- `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${connectorId} without a started transaction`
- )
- return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED
+ const { connectorId } = commandPayload
+ if (connectorId != null) {
+ if (!chargingStation.hasConnector(connectorId)) {
+ logger.error(
+ `${chargingStation.logPrefix()} Trying to clear a charging profile(s) to a non existing connector id ${connectorId.toString()}`
+ )
+ return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN
+ }
+ const connectorStatus = chargingStation.getConnectorStatus(connectorId)
+ if (isNotEmptyArray(connectorStatus?.chargingProfiles)) {
+ connectorStatus.chargingProfiles = []
+ logger.debug(
+ `${chargingStation.logPrefix()} Charging profile(s) cleared on connector id ${connectorId.toString()}`
+ )
+ return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED
+ }
+ } else {
+ let clearedCP = false
+ if (chargingStation.hasEvses) {
+ for (const evseStatus of chargingStation.evses.values()) {
+ for (const status of evseStatus.connectors.values()) {
+ const clearedConnectorCP = OCPP16ServiceUtils.clearChargingProfiles(
+ chargingStation,
+ commandPayload,
+ status.chargingProfiles
+ )
+ if (clearedConnectorCP && !clearedCP) {
+ clearedCP = true
+ }
+ }
+ }
+ } else {
+ for (const id of chargingStation.connectors.keys()) {
+ const clearedConnectorCP = OCPP16ServiceUtils.clearChargingProfiles(
+ chargingStation,
+ commandPayload,
+ chargingStation.getConnectorStatus(id)?.chargingProfiles
+ )
+ if (clearedConnectorCP && !clearedCP) {
+ clearedCP = true
+ }
+ }
+ }
+ if (clearedCP) {
+ return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED
+ }
}
- if (
- csChargingProfiles.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE &&
- connectorId > 0 &&
- connectorStatus?.transactionStarted === true &&
- csChargingProfiles.transactionId !== connectorStatus.transactionId
- ) {
- logger.error(
- `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${connectorId} with a different transaction id ${
- csChargingProfiles.transactionId
- } than the started transaction id ${connectorStatus.transactionId}`
- )
- return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED
+ return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN
+ }
+
+ private handleRequestDataTransfer (
+ chargingStation: ChargingStation,
+ commandPayload: OCPP16DataTransferRequest
+ ): OCPP16DataTransferResponse {
+ const { vendorId } = commandPayload
+ try {
+ if (vendorId === chargingStation.stationInfo?.chargePointVendor) {
+ return OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_ACCEPTED
+ }
+ return OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_UNKNOWN_VENDOR_ID
+ } catch (error) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return handleIncomingRequestError<OCPP16DataTransferResponse>(
+ chargingStation,
+ OCPP16IncomingRequestCommand.DATA_TRANSFER,
+ error as Error,
+ { errorResponse: OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_REJECTED }
+ )!
}
- OCPP16ServiceUtils.setChargingProfile(chargingStation, connectorId, csChargingProfiles)
- logger.debug(
- `${chargingStation.logPrefix()} Charging profile(s) set on connector id ${connectorId}: %j`,
- csChargingProfiles
- )
- return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_ACCEPTED
}
private handleRequestGetCompositeSchedule (
) {
return OCPP16Constants.OCPP_RESPONSE_REJECTED
}
- const { connectorId, duration, chargingRateUnit } = commandPayload
+ const { chargingRateUnit, connectorId, duration } = commandPayload
if (!chargingStation.hasConnector(connectorId)) {
logger.error(
- `${chargingStation.logPrefix()} Trying to get composite schedule to a non existing connector id ${connectorId}`
+ `${chargingStation.logPrefix()} Trying to get composite schedule to a non existing connector id ${connectorId.toString()}`
)
return OCPP16Constants.OCPP_RESPONSE_REJECTED
}
if (connectorId === 0) {
logger.error(
- `${chargingStation.logPrefix()} Get composite schedule on connector id ${connectorId} is not yet supported`
+ `${chargingStation.logPrefix()} Get composite schedule on connector id ${connectorId.toString()} is not yet supported`
)
return OCPP16Constants.OCPP_RESPONSE_REJECTED
}
}
const currentDate = new Date()
const compositeScheduleInterval: Interval = {
+ end: addSeconds(currentDate, duration),
start: currentDate,
- end: addSeconds(currentDate, duration)
}
- // Get charging profiles sorted by connector id then stack level
+ // FIXME: add and handle charging station charging profiles
const chargingProfiles: OCPP16ChargingProfile[] = getConnectorChargingProfiles(
chargingStation,
connectorId
for (const chargingProfile of chargingProfiles) {
if (chargingProfile.chargingSchedule.startSchedule == null) {
logger.debug(
- `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${
- chargingProfile.chargingProfileId
- } has no startSchedule defined. Trying to set it to the connector current transaction start date`
+ `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${chargingProfile.chargingProfileId.toString()} has no startSchedule defined. Trying to set it to the connector current transaction start date`
)
// OCPP specifies that if startSchedule is not defined, it should be relative to start of the connector transaction
chargingProfile.chargingSchedule.startSchedule = connectorStatus?.transactionStart
}
if (!isDate(chargingProfile.chargingSchedule.startSchedule)) {
logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${
- chargingProfile.chargingProfileId
- } startSchedule property is not a Date instance. Trying to convert it to a Date instance`
+ `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${chargingProfile.chargingProfileId.toString()} startSchedule property is not a Date instance. Trying to convert it to a Date instance`
)
chargingProfile.chargingSchedule.startSchedule = convertToDate(
chargingProfile.chargingSchedule.startSchedule
}
if (chargingProfile.chargingSchedule.duration == null) {
logger.debug(
- `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${
- chargingProfile.chargingProfileId
- } has no duration defined and will be set to the maximum time allowed`
+ `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${chargingProfile.chargingProfileId.toString()} has no duration defined and will be set to the maximum time allowed`
)
// OCPP specifies that if duration is not defined, it should be infinite
chargingProfile.chargingSchedule.duration = differenceInSeconds(
}
if (compositeSchedule != null) {
return {
- status: GenericStatus.Accepted,
- scheduleStart: compositeSchedule.startSchedule,
+ chargingSchedule: compositeSchedule,
connectorId,
- chargingSchedule: compositeSchedule
+ scheduleStart: compositeSchedule.startSchedule,
+ status: GenericStatus.Accepted,
}
}
return OCPP16Constants.OCPP_RESPONSE_REJECTED
}
- private handleRequestClearChargingProfile (
+ private handleRequestGetConfiguration (
chargingStation: ChargingStation,
- commandPayload: OCPP16ClearChargingProfileRequest
- ): OCPP16ClearChargingProfileResponse {
- if (
- !OCPP16ServiceUtils.checkFeatureProfile(
- chargingStation,
- OCPP16SupportedFeatureProfiles.SmartCharging,
- OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE
- )
- ) {
- return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN
- }
- const { connectorId } = commandPayload
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- if (!chargingStation.hasConnector(connectorId!)) {
- logger.error(
- `${chargingStation.logPrefix()} Trying to clear a charging profile(s) to a non existing connector id ${connectorId}`
- )
- return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN
- }
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const connectorStatus = chargingStation.getConnectorStatus(connectorId!)
- if (connectorId != null && isNotEmptyArray(connectorStatus?.chargingProfiles)) {
- connectorStatus.chargingProfiles = []
- logger.debug(
- `${chargingStation.logPrefix()} Charging profile(s) cleared on connector id ${connectorId}`
- )
- return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED
- }
- if (connectorId == null) {
- let clearedCP = false
- if (chargingStation.hasEvses) {
- for (const evseStatus of chargingStation.evses.values()) {
- for (const status of evseStatus.connectors.values()) {
- clearedCP = OCPP16ServiceUtils.clearChargingProfiles(
- chargingStation,
- commandPayload,
- status.chargingProfiles
- )
- }
- }
- } else {
- for (const id of chargingStation.connectors.keys()) {
- clearedCP = OCPP16ServiceUtils.clearChargingProfiles(
- chargingStation,
- commandPayload,
- chargingStation.getConnectorStatus(id)?.chargingProfiles
- )
+ commandPayload: GetConfigurationRequest
+ ): GetConfigurationResponse {
+ const { key } = commandPayload
+ const configurationKey: OCPPConfigurationKey[] = []
+ const unknownKey: string[] = []
+ if (key == null || isEmpty(key)) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ for (const configKey of chargingStation.ocppConfiguration!.configurationKey!) {
+ if (!OCPP16ServiceUtils.isConfigurationKeyVisible(configKey)) {
+ continue
}
+ configurationKey.push({
+ key: configKey.key,
+ readonly: configKey.readonly,
+ value: configKey.value,
+ })
}
- if (clearedCP) {
- return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED
+ } else if (isNotEmptyArray(key)) {
+ for (const k of key) {
+ const keyFound = getConfigurationKey(chargingStation, k, true)
+ if (keyFound != null) {
+ if (!OCPP16ServiceUtils.isConfigurationKeyVisible(keyFound)) {
+ continue
+ }
+ configurationKey.push({
+ key: keyFound.key,
+ readonly: keyFound.readonly,
+ value: keyFound.value,
+ })
+ } else {
+ unknownKey.push(k)
+ }
}
}
- return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN
+ return {
+ configurationKey,
+ unknownKey,
+ }
}
- private async handleRequestChangeAvailability (
+ private async handleRequestGetDiagnostics (
chargingStation: ChargingStation,
- commandPayload: OCPP16ChangeAvailabilityRequest
- ): Promise<OCPP16ChangeAvailabilityResponse> {
- const { connectorId, type } = commandPayload
- if (!chargingStation.hasConnector(connectorId)) {
- logger.error(
- `${chargingStation.logPrefix()} Trying to change the availability of a non existing connector id ${connectorId}`
- )
- return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_REJECTED
+ commandPayload: GetDiagnosticsRequest
+ ): Promise<GetDiagnosticsResponse> {
+ if (
+ !OCPP16ServiceUtils.checkFeatureProfile(
+ chargingStation,
+ OCPP16SupportedFeatureProfiles.FirmwareManagement,
+ OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
+ )
+ ) {
+ logger.warn(
+ `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: Cannot get diagnostics: feature profile not supported`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_EMPTY
}
- const chargePointStatus: OCPP16ChargePointStatus =
- type === OCPP16AvailabilityType.Operative
- ? OCPP16ChargePointStatus.Available
- : OCPP16ChargePointStatus.Unavailable
- if (connectorId === 0) {
- let response: OCPP16ChangeAvailabilityResponse | undefined
- if (chargingStation.hasEvses) {
- for (const evseStatus of chargingStation.evses.values()) {
- response = await OCPP16ServiceUtils.changeAvailability(
- chargingStation,
- [...evseStatus.connectors.keys()],
- chargePointStatus,
- type
+ const { location } = commandPayload
+ const uri = new URL(location)
+ if (uri.protocol.startsWith('ftp:')) {
+ let ftpClient: Client | undefined
+ try {
+ const logConfiguration = Configuration.getConfigurationSection<LogConfiguration>(
+ ConfigurationSection.log
+ )
+ const logFiles = readdirSync(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ resolve((fileURLToPath(import.meta.url), '../', dirname(logConfiguration.file!)))
+ )
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ .filter(file => file.endsWith(extname(logConfiguration.file!)))
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ .map(file => join(dirname(logConfiguration.file!), file))
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ const diagnosticsArchive = `${chargingStation.stationInfo?.chargingStationId}_logs.tar.gz`
+ create({ gzip: true }, logFiles).pipe(createWriteStream(diagnosticsArchive))
+ ftpClient = new Client()
+ const accessResponse = await ftpClient.access({
+ host: uri.hostname,
+ ...(isNotEmptyString(uri.port) && { port: convertToInt(uri.port) }),
+ ...(isNotEmptyString(uri.username) && { user: uri.username }),
+ ...(isNotEmptyString(uri.password) && { password: uri.password }),
+ })
+ let uploadResponse: FTPResponse | undefined
+ if (accessResponse.code === 220) {
+ ftpClient.trackProgress(info => {
+ logger.info(
+ `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: ${(
+ info.bytes / 1024
+ ).toString()} bytes transferred from diagnostics archive ${info.name}`
+ )
+ chargingStation.ocppRequestService
+ .requestHandler<
+ OCPP16DiagnosticsStatusNotificationRequest,
+ OCPP16DiagnosticsStatusNotificationResponse
+ >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
+ status: OCPP16DiagnosticsStatus.Uploading,
+ })
+ .catch((error: unknown) => {
+ logger.error(
+ `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: Error while sending '${
+ OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION
+ }'`,
+ error
+ )
+ })
+ })
+ uploadResponse = await ftpClient.uploadFrom(
+ join(resolve(dirname(fileURLToPath(import.meta.url)), '../'), diagnosticsArchive),
+ `${uri.pathname}${diagnosticsArchive}`
+ )
+ if (uploadResponse.code === 226) {
+ await chargingStation.ocppRequestService.requestHandler<
+ OCPP16DiagnosticsStatusNotificationRequest,
+ OCPP16DiagnosticsStatusNotificationResponse
+ >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
+ status: OCPP16DiagnosticsStatus.Uploaded,
+ })
+ ftpClient.close()
+ return { fileName: diagnosticsArchive }
+ }
+ throw new OCPPError(
+ ErrorType.GENERIC_ERROR,
+ `Diagnostics transfer failed with error code ${accessResponse.code.toString()}|${uploadResponse.code.toString()}`,
+ OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
)
}
- } else {
- response = await OCPP16ServiceUtils.changeAvailability(
- chargingStation,
- [...chargingStation.connectors.keys()],
- chargePointStatus,
- type
+ throw new OCPPError(
+ ErrorType.GENERIC_ERROR,
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `Diagnostics transfer failed with error code ${accessResponse.code.toString()}|${uploadResponse?.code.toString()}`,
+ OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
)
- }
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return response!
- } else if (
- connectorId > 0 &&
- (chargingStation.isChargingStationAvailable() ||
- (!chargingStation.isChargingStationAvailable() &&
- type === OCPP16AvailabilityType.Inoperative))
- ) {
- if (chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
+ } catch (error) {
+ await chargingStation.ocppRequestService.requestHandler<
+ OCPP16DiagnosticsStatusNotificationRequest,
+ OCPP16DiagnosticsStatusNotificationResponse
+ >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
+ status: OCPP16DiagnosticsStatus.UploadFailed,
+ })
+ ftpClient?.close()
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- chargingStation.getConnectorStatus(connectorId)!.availability = type
- return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED
+ return handleIncomingRequestError<GetDiagnosticsResponse>(
+ chargingStation,
+ OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
+ error as Error,
+ { errorResponse: OCPP16Constants.OCPP_RESPONSE_EMPTY }
+ )!
}
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- chargingStation.getConnectorStatus(connectorId)!.availability = type
- await OCPP16ServiceUtils.sendAndSetConnectorStatus(
- chargingStation,
- connectorId,
- chargePointStatus
+ } else {
+ logger.error(
+ `${chargingStation.logPrefix()} Unsupported protocol ${
+ uri.protocol
+ } to transfer the diagnostic logs archive`
)
- return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED
+ await chargingStation.ocppRequestService.requestHandler<
+ OCPP16DiagnosticsStatusNotificationRequest,
+ OCPP16DiagnosticsStatusNotificationResponse
+ >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
+ status: OCPP16DiagnosticsStatus.UploadFailed,
+ })
+ return OCPP16Constants.OCPP_RESPONSE_EMPTY
}
- return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_REJECTED
}
private async handleRequestRemoteStartTransaction (
chargingStation: ChargingStation,
commandPayload: RemoteStartTransactionRequest
): Promise<GenericResponse> {
- const { connectorId: transactionConnectorId, idTag, chargingProfile } = commandPayload
+ if (commandPayload.connectorId == null) {
+ for (
+ let connectorId = 1;
+ connectorId <= chargingStation.getNumberOfConnectors();
+ connectorId++
+ ) {
+ if (
+ chargingStation.getConnectorStatus(connectorId)?.transactionStarted === false &&
+ !OCPP16ServiceUtils.hasReservation(chargingStation, connectorId, commandPayload.idTag)
+ ) {
+ commandPayload.connectorId = connectorId
+ break
+ }
+ }
+ if (commandPayload.connectorId == null) {
+ logger.debug(
+ `${chargingStation.logPrefix()} Remote start transaction REJECTED on ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ chargingStation.stationInfo?.chargingStationId
+ }, idTag '${commandPayload.idTag}': no available connector found`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_REJECTED
+ }
+ }
+ const { chargingProfile, connectorId: transactionConnectorId, idTag } = commandPayload
if (!chargingStation.hasConnector(transactionConnectorId)) {
return this.notifyRemoteStartTransactionRejected(
chargingStation,
)
}
logger.debug(
- `${chargingStation.logPrefix()} Remote start transaction ACCEPTED on ${chargingStation.stationInfo?.chargingStationId}#${transactionConnectorId}}, idTag '${idTag}'`
+ `${chargingStation.logPrefix()} Remote start transaction ACCEPTED on ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ chargingStation.stationInfo?.chargingStationId
+ }#${transactionConnectorId.toString()}}, idTag '${idTag}'`
)
return OCPP16Constants.OCPP_RESPONSE_ACCEPTED
}
- private notifyRemoteStartTransactionRejected (
- chargingStation: ChargingStation,
- connectorId: number,
- idTag: string
- ): GenericResponse {
- const connectorStatus = chargingStation.getConnectorStatus(connectorId)
- logger.debug(
- `${chargingStation.logPrefix()} Remote start transaction REJECTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId}, idTag '${idTag}', availability '${connectorStatus?.availability}', status '${connectorStatus?.status}'`
- )
- return OCPP16Constants.OCPP_RESPONSE_REJECTED
- }
-
- private setRemoteStartTransactionChargingProfile (
- chargingStation: ChargingStation,
- connectorId: number,
- chargingProfile: OCPP16ChargingProfile
- ): boolean {
- if (chargingProfile.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE) {
- OCPP16ServiceUtils.setChargingProfile(chargingStation, connectorId, chargingProfile)
- logger.debug(
- `${chargingStation.logPrefix()} Charging profile(s) set at remote start transaction on ${chargingStation.stationInfo?.chargingStationId}#${connectorId}`,
- chargingProfile
- )
- return true
- }
- logger.debug(
- `${chargingStation.logPrefix()} Not allowed to set ${
- chargingProfile.chargingProfilePurpose
- } charging profile(s) at remote start transaction`
- )
- return false
- }
-
private handleRequestRemoteStopTransaction (
chargingStation: ChargingStation,
commandPayload: RemoteStopTransactionRequest
const { transactionId } = commandPayload
if (chargingStation.getConnectorIdByTransactionId(transactionId) != null) {
logger.debug(
- `${chargingStation.logPrefix()} Remote stop transaction ACCEPTED for transactionId '${transactionId}'`
+ `${chargingStation.logPrefix()} Remote stop transaction ACCEPTED for transactionId '${transactionId.toString()}'`
)
return OCPP16Constants.OCPP_RESPONSE_ACCEPTED
}
logger.debug(
- `${chargingStation.logPrefix()} Remote stop transaction REJECTED for transactionId '${transactionId}'`
+ `${chargingStation.logPrefix()} Remote stop transaction REJECTED for transactionId '${transactionId.toString()}'`
)
return OCPP16Constants.OCPP_RESPONSE_REJECTED
}
- private handleRequestUpdateFirmware (
+ private async handleRequestReserveNow (
chargingStation: ChargingStation,
- commandPayload: OCPP16UpdateFirmwareRequest
- ): OCPP16UpdateFirmwareResponse {
+ commandPayload: OCPP16ReserveNowRequest
+ ): Promise<OCPP16ReserveNowResponse> {
if (
!OCPP16ServiceUtils.checkFeatureProfile(
chargingStation,
- OCPP16SupportedFeatureProfiles.FirmwareManagement,
- OCPP16IncomingRequestCommand.UPDATE_FIRMWARE
+ OCPP16SupportedFeatureProfiles.Reservation,
+ OCPP16IncomingRequestCommand.RESERVE_NOW
)
) {
- logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: Cannot simulate firmware update: feature profile not supported`
- )
- return OCPP16Constants.OCPP_RESPONSE_EMPTY
+ return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- commandPayload.retrieveDate = convertToDate(commandPayload.retrieveDate)!
- const { retrieveDate } = commandPayload
- if (chargingStation.stationInfo?.firmwareStatus !== OCPP16FirmwareStatus.Installed) {
- logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: Cannot simulate firmware update: firmware update is already in progress`
+ commandPayload.expiryDate = convertToDate(commandPayload.expiryDate)!
+ const { connectorId, idTag, reservationId } = commandPayload
+ if (!chargingStation.hasConnector(connectorId)) {
+ logger.error(
+ `${chargingStation.logPrefix()} Trying to reserve a non existing connector id ${connectorId.toString()}`
)
- return OCPP16Constants.OCPP_RESPONSE_EMPTY
+ return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED
}
- const now = Date.now()
- if (retrieveDate.getTime() <= now) {
- this.updateFirmwareSimulation(chargingStation).catch(Constants.EMPTY_FUNCTION)
- } else {
- setTimeout(() => {
- this.updateFirmwareSimulation(chargingStation).catch(Constants.EMPTY_FUNCTION)
- }, retrieveDate.getTime() - now)
+ if (connectorId > 0 && !chargingStation.isConnectorAvailable(connectorId)) {
+ return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED
}
- return OCPP16Constants.OCPP_RESPONSE_EMPTY
- }
-
- private async updateFirmwareSimulation (
- chargingStation: ChargingStation,
- maxDelay = 30,
- minDelay = 15
- ): Promise<void> {
- if (!checkChargingStation(chargingStation, chargingStation.logPrefix())) {
- return
+ if (connectorId === 0 && !chargingStation.getReserveConnectorZeroSupported()) {
+ return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED
}
- if (chargingStation.hasEvses) {
- for (const [evseId, evseStatus] of chargingStation.evses) {
- if (evseId > 0) {
- for (const [connectorId, connectorStatus] of evseStatus.connectors) {
- if (connectorStatus.transactionStarted === false) {
- await OCPP16ServiceUtils.sendAndSetConnectorStatus(
- chargingStation,
- connectorId,
- OCPP16ChargePointStatus.Unavailable
- )
- }
- }
- }
- }
- } else {
- for (const connectorId of chargingStation.connectors.keys()) {
- if (
- connectorId > 0 &&
- chargingStation.getConnectorStatus(connectorId)?.transactionStarted === false
- ) {
- await OCPP16ServiceUtils.sendAndSetConnectorStatus(
- chargingStation,
- connectorId,
- OCPP16ChargePointStatus.Unavailable
- )
- }
- }
+ if (!(await OCPP16ServiceUtils.isIdTagAuthorized(chargingStation, connectorId, idTag))) {
+ return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED
}
- await chargingStation.ocppRequestService.requestHandler<
- OCPP16FirmwareStatusNotificationRequest,
- OCPP16FirmwareStatusNotificationResponse
- >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
- status: OCPP16FirmwareStatus.Downloading
- })
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- chargingStation.stationInfo!.firmwareStatus = OCPP16FirmwareStatus.Downloading
- if (
- chargingStation.stationInfo?.firmwareUpgrade?.failureStatus ===
- OCPP16FirmwareStatus.DownloadFailed
- ) {
- await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay)))
- await chargingStation.ocppRequestService.requestHandler<
- OCPP16FirmwareStatusNotificationRequest,
- OCPP16FirmwareStatusNotificationResponse
- >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
- status: chargingStation.stationInfo.firmwareUpgrade.failureStatus
- })
- chargingStation.stationInfo.firmwareStatus =
- chargingStation.stationInfo.firmwareUpgrade.failureStatus
- return
- }
- await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay)))
- await chargingStation.ocppRequestService.requestHandler<
- OCPP16FirmwareStatusNotificationRequest,
- OCPP16FirmwareStatusNotificationResponse
- >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
- status: OCPP16FirmwareStatus.Downloaded
- })
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- chargingStation.stationInfo!.firmwareStatus = OCPP16FirmwareStatus.Downloaded
- let wasTransactionsStarted = false
- let transactionsStarted: boolean
- do {
- const runningTransactions = chargingStation.getNumberOfRunningTransactions()
- if (runningTransactions > 0) {
- const waitTime = secondsToMilliseconds(15)
- logger.debug(
- `${chargingStation.logPrefix()} ${moduleName}.updateFirmwareSimulation: ${runningTransactions} transaction(s) in progress, waiting ${formatDurationMilliSeconds(
- waitTime
- )} before continuing firmware update simulation`
- )
- await sleep(waitTime)
- transactionsStarted = true
- wasTransactionsStarted = true
- } else {
- if (chargingStation.hasEvses) {
- for (const [evseId, evseStatus] of chargingStation.evses) {
- if (evseId > 0) {
- for (const [connectorId, connectorStatus] of evseStatus.connectors) {
- if (connectorStatus.status !== OCPP16ChargePointStatus.Unavailable) {
- await OCPP16ServiceUtils.sendAndSetConnectorStatus(
- chargingStation,
- connectorId,
- OCPP16ChargePointStatus.Unavailable
- )
- }
- }
- }
+ const connectorStatus = chargingStation.getConnectorStatus(connectorId)!
+ resetAuthorizeConnectorStatus(connectorStatus)
+ let response: OCPP16ReserveNowResponse
+ try {
+ await removeExpiredReservations(chargingStation)
+ switch (connectorStatus.status) {
+ case OCPP16ChargePointStatus.Charging:
+ case OCPP16ChargePointStatus.Finishing:
+ case OCPP16ChargePointStatus.Preparing:
+ case OCPP16ChargePointStatus.SuspendedEV:
+ case OCPP16ChargePointStatus.SuspendedEVSE:
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_OCCUPIED
+ break
+ case OCPP16ChargePointStatus.Faulted:
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_FAULTED
+ break
+ case OCPP16ChargePointStatus.Unavailable:
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_UNAVAILABLE
+ break
+ case OCPP16ChargePointStatus.Reserved:
+ if (!chargingStation.isConnectorReservable(reservationId, idTag, connectorId)) {
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_OCCUPIED
+ break
}
- } else {
- for (const connectorId of chargingStation.connectors.keys()) {
- if (
- connectorId > 0 &&
- chargingStation.getConnectorStatus(connectorId)?.status !==
- OCPP16ChargePointStatus.Unavailable
- ) {
- await OCPP16ServiceUtils.sendAndSetConnectorStatus(
- chargingStation,
- connectorId,
- OCPP16ChargePointStatus.Unavailable
- )
- }
+ // eslint-disable-next-line no-fallthrough
+ default:
+ if (!chargingStation.isConnectorReservable(reservationId, idTag)) {
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_OCCUPIED
+ break
}
- }
- transactionsStarted = false
+ await chargingStation.addReservation({
+ id: commandPayload.reservationId,
+ ...commandPayload,
+ })
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_ACCEPTED
+ break
}
- } while (transactionsStarted)
- !wasTransactionsStarted && (await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay))))
- if (!checkChargingStation(chargingStation, chargingStation.logPrefix())) {
- return
- }
- await chargingStation.ocppRequestService.requestHandler<
- OCPP16FirmwareStatusNotificationRequest,
- OCPP16FirmwareStatusNotificationResponse
- >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
- status: OCPP16FirmwareStatus.Installing
- })
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- chargingStation.stationInfo!.firmwareStatus = OCPP16FirmwareStatus.Installing
- if (
- chargingStation.stationInfo?.firmwareUpgrade?.failureStatus ===
- OCPP16FirmwareStatus.InstallationFailed
- ) {
- await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay)))
- await chargingStation.ocppRequestService.requestHandler<
- OCPP16FirmwareStatusNotificationRequest,
- OCPP16FirmwareStatusNotificationResponse
- >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
- status: chargingStation.stationInfo.firmwareUpgrade.failureStatus
- })
- chargingStation.stationInfo.firmwareStatus =
- chargingStation.stationInfo.firmwareUpgrade.failureStatus
- return
- }
- if (chargingStation.stationInfo?.firmwareUpgrade?.reset === true) {
- await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay)))
- await chargingStation.reset(OCPP16StopTransactionReason.REBOOT)
+ return response
+ } catch (error) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.getConnectorStatus(connectorId)!.status = OCPP16ChargePointStatus.Available
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return handleIncomingRequestError<OCPP16ReserveNowResponse>(
+ chargingStation,
+ OCPP16IncomingRequestCommand.RESERVE_NOW,
+ error as Error,
+ { errorResponse: OCPP16Constants.OCPP_RESERVATION_RESPONSE_FAULTED }
+ )!
}
}
- private async handleRequestGetDiagnostics (
+ // Simulate charging station restart
+ private handleRequestReset (
chargingStation: ChargingStation,
- commandPayload: GetDiagnosticsRequest
- ): Promise<GetDiagnosticsResponse> {
+ commandPayload: ResetRequest
+ ): GenericResponse {
+ const { type } = commandPayload
+ chargingStation
+ .reset(`${type}Reset` as OCPP16StopTransactionReason)
+ .catch(Constants.EMPTY_FUNCTION)
+ logger.info(
+ `${chargingStation.logPrefix()} ${type} reset command received, simulating it. The station will be back online in ${formatDurationMilliSeconds(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.stationInfo!.resetTime!
+ )}`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_ACCEPTED
+ }
+
+ private handleRequestSetChargingProfile (
+ chargingStation: ChargingStation,
+ commandPayload: SetChargingProfileRequest
+ ): SetChargingProfileResponse {
if (
!OCPP16ServiceUtils.checkFeatureProfile(
chargingStation,
- OCPP16SupportedFeatureProfiles.FirmwareManagement,
- OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
+ OCPP16SupportedFeatureProfiles.SmartCharging,
+ OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE
)
) {
- logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: Cannot get diagnostics: feature profile not supported`
- )
- return OCPP16Constants.OCPP_RESPONSE_EMPTY
+ return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_NOT_SUPPORTED
}
- const { location } = commandPayload
- const uri = new URL(location)
- if (uri.protocol.startsWith('ftp:')) {
- let ftpClient: Client | undefined
- try {
- const logConfiguration = Configuration.getConfigurationSection<LogConfiguration>(
- ConfigurationSection.log
- )
- const logFiles = readdirSync(resolve(dirname(fileURLToPath(import.meta.url)), '../'))
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- .filter(file => file.endsWith(extname(logConfiguration.file!)))
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- .map(file => join(dirname(logConfiguration.file!), file))
- const diagnosticsArchive = `${chargingStation.stationInfo?.chargingStationId}_logs.tar.gz`
- create({ gzip: true }, logFiles).pipe(createWriteStream(diagnosticsArchive))
- ftpClient = new Client()
- const accessResponse = await ftpClient.access({
- host: uri.hostname,
- ...(isNotEmptyString(uri.port) && { port: convertToInt(uri.port) }),
- ...(isNotEmptyString(uri.username) && { user: uri.username }),
- ...(isNotEmptyString(uri.password) && { password: uri.password })
- })
- let uploadResponse: FTPResponse | undefined
- if (accessResponse.code === 220) {
- ftpClient.trackProgress(info => {
- logger.info(
- `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: ${
- info.bytes / 1024
- } bytes transferred from diagnostics archive ${info.name}`
- )
- chargingStation.ocppRequestService
- .requestHandler<
- OCPP16DiagnosticsStatusNotificationRequest,
- OCPP16DiagnosticsStatusNotificationResponse
- >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
- status: OCPP16DiagnosticsStatus.Uploading
- })
- .catch((error: unknown) => {
- logger.error(
- `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: Error while sending '${
- OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION
- }'`,
- error
- )
- })
- })
- uploadResponse = await ftpClient.uploadFrom(
- join(resolve(dirname(fileURLToPath(import.meta.url)), '../'), diagnosticsArchive),
- `${uri.pathname}${diagnosticsArchive}`
- )
- if (uploadResponse.code === 226) {
- await chargingStation.ocppRequestService.requestHandler<
- OCPP16DiagnosticsStatusNotificationRequest,
- OCPP16DiagnosticsStatusNotificationResponse
- >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
- status: OCPP16DiagnosticsStatus.Uploaded
- })
- ftpClient.close()
- return { fileName: diagnosticsArchive }
- }
- throw new OCPPError(
- ErrorType.GENERIC_ERROR,
- `Diagnostics transfer failed with error code ${accessResponse.code}|${uploadResponse.code}`,
- OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
- )
- }
- throw new OCPPError(
- ErrorType.GENERIC_ERROR,
- `Diagnostics transfer failed with error code ${accessResponse.code}|${uploadResponse?.code}`,
- OCPP16IncomingRequestCommand.GET_DIAGNOSTICS
- )
- } catch (error) {
- await chargingStation.ocppRequestService.requestHandler<
- OCPP16DiagnosticsStatusNotificationRequest,
- OCPP16DiagnosticsStatusNotificationResponse
- >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
- status: OCPP16DiagnosticsStatus.UploadFailed
- })
- ftpClient?.close()
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return this.handleIncomingRequestError<GetDiagnosticsResponse>(
- chargingStation,
- OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
- error as Error,
- { errorResponse: OCPP16Constants.OCPP_RESPONSE_EMPTY }
- )!
- }
- } else {
+ const { connectorId, csChargingProfiles } = commandPayload
+ if (!chargingStation.hasConnector(connectorId)) {
logger.error(
- `${chargingStation.logPrefix()} Unsupported protocol ${
- uri.protocol
- } to transfer the diagnostic logs archive`
+ `${chargingStation.logPrefix()} Trying to set charging profile(s) to a non existing connector id ${connectorId.toString()}`
)
- await chargingStation.ocppRequestService.requestHandler<
- OCPP16DiagnosticsStatusNotificationRequest,
- OCPP16DiagnosticsStatusNotificationResponse
- >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
- status: OCPP16DiagnosticsStatus.UploadFailed
- })
- return OCPP16Constants.OCPP_RESPONSE_EMPTY
+ return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED
}
- }
-
- private handleRequestTriggerMessage (
- chargingStation: ChargingStation,
- commandPayload: OCPP16TriggerMessageRequest
- ): OCPP16TriggerMessageResponse {
- const { requestedMessage, connectorId } = commandPayload
if (
- !OCPP16ServiceUtils.checkFeatureProfile(
- chargingStation,
- OCPP16SupportedFeatureProfiles.RemoteTrigger,
- OCPP16IncomingRequestCommand.TRIGGER_MESSAGE
- ) ||
- !OCPP16ServiceUtils.isMessageTriggerSupported(chargingStation, requestedMessage)
+ csChargingProfiles.chargingProfilePurpose ===
+ OCPP16ChargingProfilePurposeType.CHARGE_POINT_MAX_PROFILE &&
+ connectorId !== 0
) {
- return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED
+ return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED
}
if (
- !OCPP16ServiceUtils.isConnectorIdValid(
- chargingStation,
- OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- connectorId!
- )
+ csChargingProfiles.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE &&
+ connectorId === 0
+ ) {
+ logger.error(
+ `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${connectorId.toString()}`
+ )
+ return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED
+ }
+ const connectorStatus = chargingStation.getConnectorStatus(connectorId)
+ if (
+ csChargingProfiles.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE &&
+ connectorId > 0 &&
+ connectorStatus?.transactionStarted === false
+ ) {
+ logger.error(
+ `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${connectorId.toString()} without a started transaction`
+ )
+ return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED
+ }
+ if (
+ csChargingProfiles.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE &&
+ connectorId > 0 &&
+ connectorStatus?.transactionStarted === true &&
+ csChargingProfiles.transactionId != null &&
+ csChargingProfiles.transactionId !== connectorStatus.transactionId
+ ) {
+ logger.error(
+ `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${connectorId.toString()} with a different transaction id ${
+ csChargingProfiles.transactionId.toString()
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ } than the started transaction id ${connectorStatus.transactionId?.toString()}`
+ )
+ return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED
+ }
+ OCPP16ServiceUtils.setChargingProfile(chargingStation, connectorId, csChargingProfiles)
+ logger.debug(
+ `${chargingStation.logPrefix()} Charging profile(s) set on connector id ${connectorId.toString()}: %j`,
+ csChargingProfiles
+ )
+ return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_ACCEPTED
+ }
+
+ private handleRequestTriggerMessage (
+ chargingStation: ChargingStation,
+ commandPayload: OCPP16TriggerMessageRequest
+ ): OCPP16TriggerMessageResponse {
+ const { connectorId, requestedMessage } = commandPayload
+ if (
+ !OCPP16ServiceUtils.checkFeatureProfile(
+ chargingStation,
+ OCPP16SupportedFeatureProfiles.RemoteTrigger,
+ OCPP16IncomingRequestCommand.TRIGGER_MESSAGE
+ ) ||
+ !OCPP16ServiceUtils.isMessageTriggerSupported(chargingStation, requestedMessage)
+ ) {
+ return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED
+ }
+ if (
+ !OCPP16ServiceUtils.isConnectorIdValid(
+ chargingStation,
+ OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ connectorId!
+ )
) {
return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED
}
}
}
- private handleRequestDataTransfer (
+ private async handleRequestUnlockConnector (
chargingStation: ChargingStation,
- commandPayload: OCPP16DataTransferRequest
- ): OCPP16DataTransferResponse {
- const { vendorId } = commandPayload
- try {
- if (Object.values(OCPP16DataTransferVendorId).includes(vendorId)) {
- return OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_ACCEPTED
+ commandPayload: UnlockConnectorRequest
+ ): Promise<UnlockConnectorResponse> {
+ const { connectorId } = commandPayload
+ if (!chargingStation.hasConnector(connectorId)) {
+ logger.error(
+ `${chargingStation.logPrefix()} Trying to unlock a non existing connector id ${connectorId.toString()}`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED
+ }
+ if (connectorId === 0) {
+ logger.error(
+ `${chargingStation.logPrefix()} Trying to unlock connector id ${connectorId.toString()}`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED
+ }
+ if (chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
+ const stopResponse = await chargingStation.stopTransactionOnConnector(
+ connectorId,
+ OCPP16StopTransactionReason.UNLOCK_COMMAND
+ )
+ if (stopResponse.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
+ return OCPP16Constants.OCPP_RESPONSE_UNLOCKED
}
- return OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_UNKNOWN_VENDOR_ID
- } catch (error) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return this.handleIncomingRequestError<OCPP16DataTransferResponse>(
- chargingStation,
- OCPP16IncomingRequestCommand.DATA_TRANSFER,
- error as Error,
- { errorResponse: OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_REJECTED }
- )!
+ return OCPP16Constants.OCPP_RESPONSE_UNLOCK_FAILED
}
+ await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+ chargingStation,
+ connectorId,
+ OCPP16ChargePointStatus.Available
+ )
+ return OCPP16Constants.OCPP_RESPONSE_UNLOCKED
}
- private async handleRequestReserveNow (
+ private handleRequestUpdateFirmware (
chargingStation: ChargingStation,
- commandPayload: OCPP16ReserveNowRequest
- ): Promise<OCPP16ReserveNowResponse> {
+ commandPayload: OCPP16UpdateFirmwareRequest
+ ): OCPP16UpdateFirmwareResponse {
if (
!OCPP16ServiceUtils.checkFeatureProfile(
chargingStation,
- OCPP16SupportedFeatureProfiles.Reservation,
- OCPP16IncomingRequestCommand.RESERVE_NOW
+ OCPP16SupportedFeatureProfiles.FirmwareManagement,
+ OCPP16IncomingRequestCommand.UPDATE_FIRMWARE
)
) {
- return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED
+ logger.warn(
+ `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: Cannot simulate firmware update: feature profile not supported`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_EMPTY
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- commandPayload.expiryDate = convertToDate(commandPayload.expiryDate)!
- const { reservationId, idTag, connectorId } = commandPayload
- let response: OCPP16ReserveNowResponse
- try {
- if (connectorId > 0 && !chargingStation.isConnectorAvailable(connectorId)) {
- return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED
- }
- if (connectorId === 0 && !chargingStation.getReserveConnectorZeroSupported()) {
- return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED
- }
- if (!(await OCPP16ServiceUtils.isIdTagAuthorized(chargingStation, connectorId, idTag))) {
- return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED
- }
- await removeExpiredReservations(chargingStation)
- switch (chargingStation.getConnectorStatus(connectorId)?.status) {
- case OCPP16ChargePointStatus.Faulted:
- response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_FAULTED
- break
- case OCPP16ChargePointStatus.Preparing:
- case OCPP16ChargePointStatus.Charging:
- case OCPP16ChargePointStatus.SuspendedEV:
- case OCPP16ChargePointStatus.SuspendedEVSE:
- case OCPP16ChargePointStatus.Finishing:
- response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_OCCUPIED
- break
- case OCPP16ChargePointStatus.Unavailable:
- response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_UNAVAILABLE
- break
- case OCPP16ChargePointStatus.Reserved:
- if (!chargingStation.isConnectorReservable(reservationId, idTag, connectorId)) {
- response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_OCCUPIED
- break
- }
- // eslint-disable-next-line no-fallthrough
- default:
- if (!chargingStation.isConnectorReservable(reservationId, idTag)) {
- response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_OCCUPIED
- break
- }
- await chargingStation.addReservation({
- id: commandPayload.reservationId,
- ...commandPayload
- })
- response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_ACCEPTED
- break
- }
- return response
- } catch (error) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- chargingStation.getConnectorStatus(connectorId)!.status = OCPP16ChargePointStatus.Available
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return this.handleIncomingRequestError<OCPP16ReserveNowResponse>(
- chargingStation,
- OCPP16IncomingRequestCommand.RESERVE_NOW,
- error as Error,
- { errorResponse: OCPP16Constants.OCPP_RESERVATION_RESPONSE_FAULTED }
- )!
+ commandPayload.retrieveDate = convertToDate(commandPayload.retrieveDate)!
+ const { retrieveDate } = commandPayload
+ if (
+ chargingStation.stationInfo?.firmwareStatus != null &&
+ chargingStation.stationInfo.firmwareStatus !== OCPP16FirmwareStatus.Installed
+ ) {
+ logger.warn(
+ `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: Cannot simulate firmware update: firmware update is already in progress`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_EMPTY
}
+ const now = Date.now()
+ if (retrieveDate.getTime() <= now) {
+ this.updateFirmwareSimulation(chargingStation).catch(Constants.EMPTY_FUNCTION)
+ } else {
+ setTimeout(() => {
+ this.updateFirmwareSimulation(chargingStation).catch(Constants.EMPTY_FUNCTION)
+ }, retrieveDate.getTime() - now)
+ }
+ return OCPP16Constants.OCPP_RESPONSE_EMPTY
}
- private async handleRequestCancelReservation (
+ private notifyRemoteStartTransactionRejected (
chargingStation: ChargingStation,
- commandPayload: OCPP16CancelReservationRequest
- ): Promise<GenericResponse> {
+ connectorId: number,
+ idTag: string
+ ): GenericResponse {
+ const connectorStatus = chargingStation.getConnectorStatus(connectorId)
+ logger.debug(
+ `${chargingStation.logPrefix()} Remote start transaction REJECTED on ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ chargingStation.stationInfo?.chargingStationId
+ }#${connectorId.toString()}, idTag '${idTag}', availability '${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ connectorStatus?.availability
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ }', status '${connectorStatus?.status}'`
+ )
+ return OCPP16Constants.OCPP_RESPONSE_REJECTED
+ }
+
+ private setRemoteStartTransactionChargingProfile (
+ chargingStation: ChargingStation,
+ connectorId: number,
+ chargingProfile: OCPP16ChargingProfile
+ ): boolean {
if (
- !OCPP16ServiceUtils.checkFeatureProfile(
- chargingStation,
- OCPP16SupportedFeatureProfiles.Reservation,
- OCPP16IncomingRequestCommand.CANCEL_RESERVATION
+ chargingProfile.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE &&
+ chargingProfile.transactionId == null
+ ) {
+ OCPP16ServiceUtils.setChargingProfile(chargingStation, connectorId, chargingProfile)
+ logger.debug(
+ `${chargingStation.logPrefix()} Charging profile(s) set at remote start transaction on ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ chargingStation.stationInfo?.chargingStationId
+ }#${connectorId.toString()}`,
+ chargingProfile
)
+ return true
+ }
+ logger.debug(
+ `${chargingStation.logPrefix()} Not allowed to set ${
+ chargingProfile.chargingProfilePurpose
+ } charging profile(s)${chargingProfile.transactionId != null ? ' with transactionId set' : ''} at remote start transaction`
+ )
+ return false
+ }
+
+ private async updateFirmwareSimulation (
+ chargingStation: ChargingStation,
+ maxDelay = 30,
+ minDelay = 15
+ ): Promise<void> {
+ if (!checkChargingStationState(chargingStation, chargingStation.logPrefix())) {
+ return
+ }
+ if (chargingStation.hasEvses) {
+ for (const [evseId, evseStatus] of chargingStation.evses) {
+ if (evseId > 0) {
+ for (const [connectorId, connectorStatus] of evseStatus.connectors) {
+ if (connectorStatus.transactionStarted === false) {
+ await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+ chargingStation,
+ connectorId,
+ OCPP16ChargePointStatus.Unavailable
+ )
+ }
+ }
+ }
+ }
+ } else {
+ for (const connectorId of chargingStation.connectors.keys()) {
+ if (
+ connectorId > 0 &&
+ chargingStation.getConnectorStatus(connectorId)?.transactionStarted === false
+ ) {
+ await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+ chargingStation,
+ connectorId,
+ OCPP16ChargePointStatus.Unavailable
+ )
+ }
+ }
+ }
+ await chargingStation.ocppRequestService.requestHandler<
+ OCPP16FirmwareStatusNotificationRequest,
+ OCPP16FirmwareStatusNotificationResponse
+ >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
+ status: OCPP16FirmwareStatus.Downloading,
+ })
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.stationInfo!.firmwareStatus = OCPP16FirmwareStatus.Downloading
+ if (
+ chargingStation.stationInfo?.firmwareUpgrade?.failureStatus ===
+ OCPP16FirmwareStatus.DownloadFailed
) {
- return OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED
+ await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay)))
+ await chargingStation.ocppRequestService.requestHandler<
+ OCPP16FirmwareStatusNotificationRequest,
+ OCPP16FirmwareStatusNotificationResponse
+ >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
+ status: chargingStation.stationInfo.firmwareUpgrade.failureStatus,
+ })
+ chargingStation.stationInfo.firmwareStatus =
+ chargingStation.stationInfo.firmwareUpgrade.failureStatus
+ return
}
- try {
- const { reservationId } = commandPayload
- const reservation = chargingStation.getReservationBy('reservationId', reservationId)
- if (reservation == null) {
+ await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay)))
+ await chargingStation.ocppRequestService.requestHandler<
+ OCPP16FirmwareStatusNotificationRequest,
+ OCPP16FirmwareStatusNotificationResponse
+ >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
+ status: OCPP16FirmwareStatus.Downloaded,
+ })
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.stationInfo!.firmwareStatus = OCPP16FirmwareStatus.Downloaded
+ let wasTransactionsStarted = false
+ let transactionsStarted: boolean
+ do {
+ const runningTransactions = chargingStation.getNumberOfRunningTransactions()
+ if (runningTransactions > 0) {
+ const waitTime = secondsToMilliseconds(15)
logger.debug(
- `${chargingStation.logPrefix()} Reservation with id ${reservationId} does not exist on charging station`
+ `${chargingStation.logPrefix()} ${moduleName}.updateFirmwareSimulation: ${runningTransactions.toString()} transaction(s) in progress, waiting ${formatDurationMilliSeconds(
+ waitTime
+ )} before continuing firmware update simulation`
)
- return OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED
+ await sleep(waitTime)
+ transactionsStarted = true
+ wasTransactionsStarted = true
+ } else {
+ if (chargingStation.hasEvses) {
+ for (const [evseId, evseStatus] of chargingStation.evses) {
+ if (evseId > 0) {
+ for (const [connectorId, connectorStatus] of evseStatus.connectors) {
+ if (connectorStatus.status !== OCPP16ChargePointStatus.Unavailable) {
+ await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+ chargingStation,
+ connectorId,
+ OCPP16ChargePointStatus.Unavailable
+ )
+ }
+ }
+ }
+ }
+ } else {
+ for (const connectorId of chargingStation.connectors.keys()) {
+ if (
+ connectorId > 0 &&
+ chargingStation.getConnectorStatus(connectorId)?.status !==
+ OCPP16ChargePointStatus.Unavailable
+ ) {
+ await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+ chargingStation,
+ connectorId,
+ OCPP16ChargePointStatus.Unavailable
+ )
+ }
+ }
+ }
+ transactionsStarted = false
}
- await chargingStation.removeReservation(
- reservation,
- ReservationTerminationReason.RESERVATION_CANCELED
- )
- return OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_ACCEPTED
- } catch (error) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return this.handleIncomingRequestError<GenericResponse>(
- chargingStation,
- OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
- error as Error,
- { errorResponse: OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED }
- )!
+ } while (transactionsStarted)
+ !wasTransactionsStarted && (await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay))))
+ if (!checkChargingStationState(chargingStation, chargingStation.logPrefix())) {
+ return
+ }
+ await chargingStation.ocppRequestService.requestHandler<
+ OCPP16FirmwareStatusNotificationRequest,
+ OCPP16FirmwareStatusNotificationResponse
+ >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
+ status: OCPP16FirmwareStatus.Installing,
+ })
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.stationInfo!.firmwareStatus = OCPP16FirmwareStatus.Installing
+ if (
+ chargingStation.stationInfo?.firmwareUpgrade?.failureStatus ===
+ OCPP16FirmwareStatus.InstallationFailed
+ ) {
+ await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay)))
+ await chargingStation.ocppRequestService.requestHandler<
+ OCPP16FirmwareStatusNotificationRequest,
+ OCPP16FirmwareStatusNotificationResponse
+ >(chargingStation, OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, {
+ status: chargingStation.stationInfo.firmwareUpgrade.failureStatus,
+ })
+ chargingStation.stationInfo.firmwareStatus =
+ chargingStation.stationInfo.firmwareUpgrade.failureStatus
+ return
+ }
+ if (chargingStation.stationInfo?.firmwareUpgrade?.reset === true) {
+ await sleep(secondsToMilliseconds(randomInt(minDelay, maxDelay)))
+ await chargingStation.reset(OCPP16StopTransactionReason.REBOOT)
}
}
+
+ private validatePayload (
+ chargingStation: ChargingStation,
+ commandName: OCPP16IncomingRequestCommand,
+ commandPayload: JsonType
+ ): boolean {
+ if (this.payloadValidateFunctions.has(commandName)) {
+ return this.validateIncomingRequestPayload(chargingStation, commandName, commandPayload)
+ }
+ logger.warn(
+ `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema validation function found for command '${commandName}' PDU validation`
+ )
+ return false
+ }
}
import type { ValidateFunction } from 'ajv'
import type { ChargingStation } from '../../../charging-station/index.js'
+import type { OCPPResponseService } from '../OCPPResponseService.js'
+
import { OCPPError } from '../../../exception/index.js'
import {
ErrorType,
type OCPP16StatusNotificationRequest,
type OCPP16StopTransactionRequest,
OCPPVersion,
- type RequestParams
+ type RequestParams,
} from '../../../types/index.js'
import { Constants, generateUUID } from '../../../utils/index.js'
import { OCPPRequestService } from '../OCPPRequestService.js'
-import type { OCPPResponseService } from '../OCPPResponseService.js'
import { OCPP16Constants } from './OCPP16Constants.js'
import { OCPP16ServiceUtils } from './OCPP16ServiceUtils.js'
this.payloadValidateFunctions = new Map<OCPP16RequestCommand, ValidateFunction<JsonType>>([
[
OCPP16RequestCommand.AUTHORIZE,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16AuthorizeRequest>(
- 'assets/json-schemas/ocpp/1.6/Authorize.json',
- moduleName,
- 'constructor'
- )
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16AuthorizeRequest>(
+ 'assets/json-schemas/ocpp/1.6/Authorize.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
OCPP16RequestCommand.BOOT_NOTIFICATION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16BootNotificationRequest>(
- 'assets/json-schemas/ocpp/1.6/BootNotification.json',
- moduleName,
- 'constructor'
- )
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16BootNotificationRequest>(
+ 'assets/json-schemas/ocpp/1.6/BootNotification.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DiagnosticsStatusNotificationRequest>(
- 'assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotification.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.DATA_TRANSFER,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferRequest>(
+ 'assets/json-schemas/ocpp/1.6/DataTransfer.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16RequestCommand.HEARTBEAT,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16HeartbeatRequest>(
- 'assets/json-schemas/ocpp/1.6/Heartbeat.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DiagnosticsStatusNotificationRequest>(
+ 'assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotification.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16RequestCommand.METER_VALUES,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16MeterValuesRequest>(
- 'assets/json-schemas/ocpp/1.6/MeterValues.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16FirmwareStatusNotificationRequest>(
+ 'assets/json-schemas/ocpp/1.6/FirmwareStatusNotification.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16RequestCommand.STATUS_NOTIFICATION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StatusNotificationRequest>(
- 'assets/json-schemas/ocpp/1.6/StatusNotification.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.HEARTBEAT,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16HeartbeatRequest>(
+ 'assets/json-schemas/ocpp/1.6/Heartbeat.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16RequestCommand.START_TRANSACTION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StartTransactionRequest>(
- 'assets/json-schemas/ocpp/1.6/StartTransaction.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.METER_VALUES,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16MeterValuesRequest>(
+ 'assets/json-schemas/ocpp/1.6/MeterValues.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16RequestCommand.STOP_TRANSACTION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StopTransactionRequest>(
- 'assets/json-schemas/ocpp/1.6/StopTransaction.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.START_TRANSACTION,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StartTransactionRequest>(
+ 'assets/json-schemas/ocpp/1.6/StartTransaction.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16RequestCommand.DATA_TRANSFER,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferRequest>(
- 'assets/json-schemas/ocpp/1.6/DataTransfer.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.STATUS_NOTIFICATION,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StatusNotificationRequest>(
+ 'assets/json-schemas/ocpp/1.6/StatusNotification.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16FirmwareStatusNotificationRequest>(
- 'assets/json-schemas/ocpp/1.6/FirmwareStatusNotification.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.STOP_TRANSACTION,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StopTransactionRequest>(
+ 'assets/json-schemas/ocpp/1.6/StopTransaction.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
- ]
+ ),
+ ],
])
this.buildRequestPayload = this.buildRequestPayload.bind(this)
}
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
public async requestHandler<RequestType extends JsonType, ResponseType extends JsonType>(
chargingStation: ChargingStation,
commandName: OCPP16RequestCommand,
): Promise<ResponseType> {
// FIXME?: add sanity checks on charging station availability, connector availability, connector status, etc.
if (OCPP16ServiceUtils.isRequestCommandSupported(chargingStation, commandName)) {
- // Post request actions hook
+ // Pre request actions hook
switch (commandName) {
case OCPP16RequestCommand.START_TRANSACTION:
await OCPP16ServiceUtils.sendAndSetConnectorStatus(
// OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
throw new OCPPError(
ErrorType.NOT_SUPPORTED,
- `Unsupported OCPP command '${commandName}'`,
+ `Unsupported OCPP command ${commandName}`,
commandName,
commandParams
)
}
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
private buildRequestPayload<Request extends JsonType>(
chargingStation: ChargingStation,
commandName: OCPP16RequestCommand,
let energyActiveImportRegister: number
commandParams = commandParams as JsonObject
switch (commandName) {
+ case OCPP16RequestCommand.AUTHORIZE:
+ return {
+ idTag: Constants.DEFAULT_IDTAG,
+ ...commandParams,
+ } as unknown as Request
case OCPP16RequestCommand.BOOT_NOTIFICATION:
+ case OCPP16RequestCommand.DATA_TRANSFER:
case OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION:
case OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION:
case OCPP16RequestCommand.METER_VALUES:
case OCPP16RequestCommand.STATUS_NOTIFICATION:
- case OCPP16RequestCommand.DATA_TRANSFER:
return commandParams as unknown as Request
- case OCPP16RequestCommand.AUTHORIZE:
- return {
- idTag: Constants.DEFAULT_IDTAG,
- ...commandParams
- } as unknown as Request
case OCPP16RequestCommand.HEARTBEAT:
return OCPP16Constants.OCPP_REQUEST_EMPTY as unknown as Request
case OCPP16RequestCommand.START_TRANSACTION:
chargingStation.getConnectorStatus(0)?.status === OCPP16ChargePointStatus.Reserved
? 0
: (commandParams.connectorId as number)
- )!.reservationId
+ )!.reservationId,
}),
- ...commandParams
+ ...commandParams,
} as unknown as Request
case OCPP16RequestCommand.STOP_TRANSACTION:
chargingStation.stationInfo?.transactionDataMeterValues === true &&
connectorId!,
energyActiveImportRegister
)
- )
+ ),
}),
- ...commandParams
+ ...commandParams,
} as unknown as Request
default:
// OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
throw new OCPPError(
ErrorType.NOT_SUPPORTED,
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- `Unsupported OCPP command '${commandName}'`,
+ `Unsupported OCPP command ${commandName}`,
commandName,
commandParams
)
// Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
import type { ValidateFunction } from 'ajv'
+
import { secondsToMilliseconds } from 'date-fns'
import {
type ChargingStation,
getConfigurationKey,
hasReservationExpired,
- resetConnectorStatus
+ resetConnectorStatus,
} from '../../../charging-station/index.js'
import { OCPPError } from '../../../exception/index.js'
import {
type ChangeConfigurationResponse,
+ ChargingStationEvents,
ErrorType,
type GenericResponse,
type GetConfigurationResponse,
ReservationTerminationReason,
type ResponseHandler,
type SetChargingProfileResponse,
- type UnlockConnectorResponse
+ type UnlockConnectorResponse,
} from '../../../types/index.js'
import { Constants, convertToInt, isAsyncFunction, logger } from '../../../utils/index.js'
import { OCPPResponseService } from '../OCPPResponseService.js'
export class OCPP16ResponseService extends OCPPResponseService {
public incomingRequestResponsePayloadValidateFunctions: Map<
- OCPP16IncomingRequestCommand,
- ValidateFunction<JsonType>
+ OCPP16IncomingRequestCommand,
+ ValidateFunction<JsonType>
>
protected payloadValidateFunctions: Map<OCPP16RequestCommand, ValidateFunction<JsonType>>
// }
super(OCPPVersion.VERSION_16)
this.responseHandlers = new Map<OCPP16RequestCommand, ResponseHandler>([
+ [OCPP16RequestCommand.AUTHORIZE, this.handleResponseAuthorize.bind(this) as ResponseHandler],
[
OCPP16RequestCommand.BOOT_NOTIFICATION,
- this.handleResponseBootNotification.bind(this) as ResponseHandler
+ this.handleResponseBootNotification.bind(this) as ResponseHandler,
],
- [OCPP16RequestCommand.HEARTBEAT, this.emptyResponseHandler],
- [OCPP16RequestCommand.AUTHORIZE, this.handleResponseAuthorize.bind(this) as ResponseHandler],
+ [OCPP16RequestCommand.DATA_TRANSFER, this.emptyResponseHandler],
[
- OCPP16RequestCommand.START_TRANSACTION,
- this.handleResponseStartTransaction.bind(this) as ResponseHandler
+ OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
+ this.emptyResponseHandler.bind(this) as ResponseHandler,
],
+ [OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, this.emptyResponseHandler],
+ [OCPP16RequestCommand.HEARTBEAT, this.emptyResponseHandler],
+ [OCPP16RequestCommand.METER_VALUES, this.emptyResponseHandler],
[
- OCPP16RequestCommand.STOP_TRANSACTION,
- this.handleResponseStopTransaction.bind(this) as ResponseHandler
+ OCPP16RequestCommand.START_TRANSACTION,
+ this.handleResponseStartTransaction.bind(this) as ResponseHandler,
],
[
OCPP16RequestCommand.STATUS_NOTIFICATION,
- this.emptyResponseHandler.bind(this) as ResponseHandler
+ this.emptyResponseHandler.bind(this) as ResponseHandler,
],
- [OCPP16RequestCommand.METER_VALUES, this.emptyResponseHandler],
[
- OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
- this.emptyResponseHandler.bind(this) as ResponseHandler
+ OCPP16RequestCommand.STOP_TRANSACTION,
+ this.handleResponseStopTransaction.bind(this) as ResponseHandler,
],
- [OCPP16RequestCommand.DATA_TRANSFER, this.emptyResponseHandler],
- [OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, this.emptyResponseHandler]
])
this.payloadValidateFunctions = new Map<OCPP16RequestCommand, ValidateFunction<JsonType>>([
[
- OCPP16RequestCommand.BOOT_NOTIFICATION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16BootNotificationResponse>(
- 'assets/json-schemas/ocpp/1.6/BootNotificationResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.AUTHORIZE,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16AuthorizeResponse>(
+ 'assets/json-schemas/ocpp/1.6/AuthorizeResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16RequestCommand.HEARTBEAT,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16HeartbeatResponse>(
- 'assets/json-schemas/ocpp/1.6/HeartbeatResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.BOOT_NOTIFICATION,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16BootNotificationResponse>(
+ 'assets/json-schemas/ocpp/1.6/BootNotificationResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16RequestCommand.AUTHORIZE,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16AuthorizeResponse>(
- 'assets/json-schemas/ocpp/1.6/AuthorizeResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.DATA_TRANSFER,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferResponse>(
+ 'assets/json-schemas/ocpp/1.6/DataTransferResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16RequestCommand.START_TRANSACTION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StartTransactionResponse>(
- 'assets/json-schemas/ocpp/1.6/StartTransactionResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DiagnosticsStatusNotificationResponse>(
+ 'assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotificationResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16RequestCommand.STOP_TRANSACTION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StopTransactionResponse>(
- 'assets/json-schemas/ocpp/1.6/StopTransactionResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16FirmwareStatusNotificationResponse>(
+ 'assets/json-schemas/ocpp/1.6/FirmwareStatusNotificationResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16RequestCommand.STATUS_NOTIFICATION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StatusNotificationResponse>(
- 'assets/json-schemas/ocpp/1.6/StatusNotificationResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.HEARTBEAT,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16HeartbeatResponse>(
+ 'assets/json-schemas/ocpp/1.6/HeartbeatResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
OCPP16RequestCommand.METER_VALUES,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16MeterValuesResponse>(
- 'assets/json-schemas/ocpp/1.6/MeterValuesResponse.json',
- moduleName,
- 'constructor'
- )
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16MeterValuesResponse>(
+ 'assets/json-schemas/ocpp/1.6/MeterValuesResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DiagnosticsStatusNotificationResponse>(
- 'assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotificationResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.START_TRANSACTION,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StartTransactionResponse>(
+ 'assets/json-schemas/ocpp/1.6/StartTransactionResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16RequestCommand.DATA_TRANSFER,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferResponse>(
- 'assets/json-schemas/ocpp/1.6/DataTransferResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.STATUS_NOTIFICATION,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StatusNotificationResponse>(
+ 'assets/json-schemas/ocpp/1.6/StatusNotificationResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
- this.ajv
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16FirmwareStatusNotificationResponse>(
- 'assets/json-schemas/ocpp/1.6/FirmwareStatusNotificationResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16RequestCommand.STOP_TRANSACTION,
+ this.ajv.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16StopTransactionResponse>(
+ 'assets/json-schemas/ocpp/1.6/StopTransactionResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
- ]
+ ),
+ ],
])
this.incomingRequestResponsePayloadValidateFunctions = new Map<
- OCPP16IncomingRequestCommand,
- ValidateFunction<JsonType>
+ OCPP16IncomingRequestCommand,
+ ValidateFunction<JsonType>
>([
[
- OCPP16IncomingRequestCommand.RESET,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<GenericResponse>(
- 'assets/json-schemas/ocpp/1.6/ResetResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<GenericResponse>(
+ 'assets/json-schemas/ocpp/1.6/CancelReservationResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.CLEAR_CACHE,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<GenericResponse>(
- 'assets/json-schemas/ocpp/1.6/ClearCacheResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY,
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ChangeAvailabilityResponse>(
+ 'assets/json-schemas/ocpp/1.6/ChangeAvailabilityResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ChangeAvailabilityResponse>(
- 'assets/json-schemas/ocpp/1.6/ChangeAvailabilityResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION,
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<ChangeConfigurationResponse>(
+ 'assets/json-schemas/ocpp/1.6/ChangeConfigurationResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<UnlockConnectorResponse>(
- 'assets/json-schemas/ocpp/1.6/UnlockConnectorResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.CLEAR_CACHE,
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<GenericResponse>(
+ 'assets/json-schemas/ocpp/1.6/ClearCacheResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.GET_CONFIGURATION,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<GetConfigurationResponse>(
- 'assets/json-schemas/ocpp/1.6/GetConfigurationResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ClearChargingProfileResponse>(
+ 'assets/json-schemas/ocpp/1.6/ClearChargingProfileResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<ChangeConfigurationResponse>(
- 'assets/json-schemas/ocpp/1.6/ChangeConfigurationResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.DATA_TRANSFER,
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferResponse>(
+ 'assets/json-schemas/ocpp/1.6/DataTransferResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16GetCompositeScheduleResponse>(
- 'assets/json-schemas/ocpp/1.6/GetCompositeScheduleResponse.json',
- moduleName,
- 'constructor'
- )
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16GetCompositeScheduleResponse>(
+ 'assets/json-schemas/ocpp/1.6/GetCompositeScheduleResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<SetChargingProfileResponse>(
- 'assets/json-schemas/ocpp/1.6/SetChargingProfileResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.GET_CONFIGURATION,
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<GetConfigurationResponse>(
+ 'assets/json-schemas/ocpp/1.6/GetConfigurationResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ClearChargingProfileResponse>(
- 'assets/json-schemas/ocpp/1.6/ClearChargingProfileResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<GetDiagnosticsResponse>(
+ 'assets/json-schemas/ocpp/1.6/GetDiagnosticsResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<GenericResponse>(
- 'assets/json-schemas/ocpp/1.6/RemoteStartTransactionResponse.json',
- moduleName,
- 'constructor'
- )
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<GenericResponse>(
+ 'assets/json-schemas/ocpp/1.6/RemoteStartTransactionResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<GenericResponse>(
- 'assets/json-schemas/ocpp/1.6/RemoteStopTransactionResponse.json',
- moduleName,
- 'constructor'
- )
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<GenericResponse>(
+ 'assets/json-schemas/ocpp/1.6/RemoteStopTransactionResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<GetDiagnosticsResponse>(
- 'assets/json-schemas/ocpp/1.6/GetDiagnosticsResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.RESERVE_NOW,
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ReserveNowResponse>(
+ 'assets/json-schemas/ocpp/1.6/ReserveNowResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16TriggerMessageResponse>(
- 'assets/json-schemas/ocpp/1.6/TriggerMessageResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.RESET,
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<GenericResponse>(
+ 'assets/json-schemas/ocpp/1.6/ResetResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.DATA_TRANSFER,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16DataTransferResponse>(
- 'assets/json-schemas/ocpp/1.6/DataTransferResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<SetChargingProfileResponse>(
+ 'assets/json-schemas/ocpp/1.6/SetChargingProfileResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.UPDATE_FIRMWARE,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16UpdateFirmwareResponse>(
- 'assets/json-schemas/ocpp/1.6/UpdateFirmwareResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16TriggerMessageResponse>(
+ 'assets/json-schemas/ocpp/1.6/TriggerMessageResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.RESERVE_NOW,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16ReserveNowResponse>(
- 'assets/json-schemas/ocpp/1.6/ReserveNowResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR,
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<UnlockConnectorResponse>(
+ 'assets/json-schemas/ocpp/1.6/UnlockConnectorResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
- OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
- this.ajvIncomingRequest
- .compile(
- OCPP16ServiceUtils.parseJsonSchemaFile<GenericResponse>(
- 'assets/json-schemas/ocpp/1.6/CancelReservationResponse.json',
- moduleName,
- 'constructor'
- )
+ OCPP16IncomingRequestCommand.UPDATE_FIRMWARE,
+ this.ajvIncomingRequest.compile(
+ OCPP16ServiceUtils.parseJsonSchemaFile<OCPP16UpdateFirmwareResponse>(
+ 'assets/json-schemas/ocpp/1.6/UpdateFirmwareResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
- ]
+ ),
+ ],
])
this.validatePayload = this.validatePayload.bind(this)
}
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
public async responseHandler<ReqType extends JsonType, ResType extends JsonType>(
chargingStation: ChargingStation,
commandName: OCPP16RequestCommand,
payload: ResType,
requestPayload: ReqType
): Promise<void> {
- if (chargingStation.isRegistered() || commandName === OCPP16RequestCommand.BOOT_NOTIFICATION) {
+ if (
+ chargingStation.inAcceptedState() ||
+ ((chargingStation.inUnknownState() || chargingStation.inPendingState()) &&
+ commandName === OCPP16RequestCommand.BOOT_NOTIFICATION) ||
+ (chargingStation.stationInfo?.ocppStrictCompliance === false &&
+ (chargingStation.inUnknownState() || chargingStation.inPendingState()))
+ ) {
if (
this.responseHandlers.has(commandName) &&
OCPP16ServiceUtils.isRequestCommandSupported(chargingStation, commandName)
if (isAsyncFunction(responseHandler)) {
await responseHandler(chargingStation, payload, requestPayload)
} else {
- (
+ ;(
responseHandler as (
chargingStation: ChargingStation,
payload: JsonType,
// Throw exception
throw new OCPPError(
ErrorType.NOT_IMPLEMENTED,
- `'${commandName}' is not implemented to handle response PDU ${JSON.stringify(
+ `${commandName} is not implemented to handle response PDU ${JSON.stringify(
payload,
undefined,
2
}
}
- private validatePayload (
- chargingStation: ChargingStation,
- commandName: OCPP16RequestCommand,
- payload: JsonType
- ): boolean {
- if (this.payloadValidateFunctions.has(commandName)) {
- return this.validateResponsePayload(chargingStation, commandName, payload)
- }
- logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema validation function found for command '${commandName}' PDU validation`
- )
- return false
- }
-
- private handleResponseBootNotification (
- chargingStation: ChargingStation,
- payload: OCPP16BootNotificationResponse
- ): void {
- if (payload.status === RegistrationStatusEnumType.ACCEPTED) {
- addConfigurationKey(
- chargingStation,
- OCPP16StandardParametersKey.HeartbeatInterval,
- payload.interval.toString(),
- {},
- { overwrite: true, save: true }
- )
- addConfigurationKey(
- chargingStation,
- OCPP16StandardParametersKey.HeartBeatInterval,
- payload.interval.toString(),
- { visible: false },
- { overwrite: true, save: true }
- )
- OCPP16ServiceUtils.startHeartbeatInterval(chargingStation, payload.interval)
- }
- if (Object.values(RegistrationStatusEnumType).includes(payload.status)) {
- const logMsg = `${chargingStation.logPrefix()} Charging station in '${
- payload.status
- }' state on the central server`
- payload.status === RegistrationStatusEnumType.REJECTED
- ? logger.warn(logMsg)
- : logger.info(logMsg)
- } else {
- logger.error(
- `${chargingStation.logPrefix()} Charging station boot notification response received: %j with undefined registration status`,
- payload
- )
- }
- }
-
private handleResponseAuthorize (
chargingStation: ChargingStation,
payload: OCPP16AuthorizeResponse,
logger.debug(
`${chargingStation.logPrefix()} idTag '${
requestPayload.idTag
- }' accepted on connector id ${authorizeConnectorId}`
+ }' accepted on connector id ${authorizeConnectorId.toString()}`
)
} else {
authorizeConnectorStatus.idTagAuthorized = false
delete authorizeConnectorStatus.authorizeIdTag
logger.debug(
- `${chargingStation.logPrefix()} idTag '${requestPayload.idTag}' rejected with status '${
- payload.idTagInfo.status
- }'`
+ `${chargingStation.logPrefix()} idTag '${
+ requestPayload.idTag
+ }' rejected with status '${payload.idTagInfo.status}'`
)
}
} else {
}
}
+ private handleResponseBootNotification (
+ chargingStation: ChargingStation,
+ payload: OCPP16BootNotificationResponse
+ ): void {
+ if (Object.values(RegistrationStatusEnumType).includes(payload.status)) {
+ chargingStation.bootNotificationResponse = payload
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ if (payload.interval != null) {
+ addConfigurationKey(
+ chargingStation,
+ OCPP16StandardParametersKey.HeartbeatInterval,
+ payload.interval.toString(),
+ {},
+ { overwrite: true, save: true }
+ )
+ addConfigurationKey(
+ chargingStation,
+ OCPP16StandardParametersKey.HeartBeatInterval,
+ payload.interval.toString(),
+ { visible: false },
+ { overwrite: true, save: true }
+ )
+ }
+ if (chargingStation.inAcceptedState()) {
+ chargingStation.emit(ChargingStationEvents.accepted)
+ } else if (chargingStation.inPendingState()) {
+ chargingStation.emit(ChargingStationEvents.pending)
+ } else if (chargingStation.inRejectedState()) {
+ chargingStation.emit(ChargingStationEvents.rejected)
+ }
+ const logMsg = `${chargingStation.logPrefix()} Charging station in '${
+ payload.status
+ }' state on the central server`
+ payload.status === RegistrationStatusEnumType.REJECTED
+ ? logger.warn(logMsg)
+ : logger.info(logMsg)
+ } else {
+ delete chargingStation.bootNotificationResponse
+ logger.error(
+ `${chargingStation.logPrefix()} Charging station boot notification response received: %j with undefined registration status`,
+ payload
+ )
+ }
+ }
+
private async handleResponseStartTransaction (
chargingStation: ChargingStation,
payload: OCPP16StartTransactionResponse,
const { connectorId } = requestPayload
if (connectorId === 0 || !chargingStation.hasConnector(connectorId)) {
logger.error(
- `${chargingStation.logPrefix()} Trying to start a transaction on a non existing connector id ${connectorId}`
+ `${chargingStation.logPrefix()} Trying to start a transaction on a non existing connector id ${connectorId.toString()}`
)
return
}
) {
logger.error(
`${chargingStation.logPrefix()} Trying to start a transaction with a not local authorized idTag ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
connectorStatus.localAuthorizeIdTag
- } on connector id ${connectorId}`
+ } on connector id ${connectorId.toString()}`
)
await this.resetConnectorOnStartTransactionError(chargingStation, connectorId)
return
) {
logger.error(
`${chargingStation.logPrefix()} Trying to start a transaction with a not authorized idTag ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
connectorStatus.authorizeIdTag
- } on connector id ${connectorId}`
+ } on connector id ${connectorId.toString()}`
)
await this.resetConnectorOnStartTransactionError(chargingStation, connectorId)
return
}
if (
connectorStatus?.idTagAuthorized === true &&
+ connectorStatus.authorizeIdTag != null &&
connectorStatus.authorizeIdTag !== requestPayload.idTag
) {
logger.error(
requestPayload.idTag
} different from the authorize request one ${
connectorStatus.authorizeIdTag
- } on connector id ${connectorId}`
+ } on connector id ${connectorId.toString()}`
)
await this.resetConnectorOnStartTransactionError(chargingStation, connectorId)
return
}
if (
connectorStatus?.idTagLocalAuthorized === true &&
+ connectorStatus.localAuthorizeIdTag != null &&
connectorStatus.localAuthorizeIdTag !== requestPayload.idTag
) {
logger.error(
requestPayload.idTag
} different from the local authorized one ${
connectorStatus.localAuthorizeIdTag
- } on connector id ${connectorId}`
+ } on connector id ${connectorId.toString()}`
)
await this.resetConnectorOnStartTransactionError(chargingStation, connectorId)
return
}
if (connectorStatus?.transactionStarted === true) {
logger.error(
- `${chargingStation.logPrefix()} Trying to start a transaction on an already used connector id ${connectorId} by idTag ${
+ `${chargingStation.logPrefix()} Trying to start a transaction on an already used connector id ${connectorId.toString()} by idTag ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
connectorStatus.transactionIdTag
}`
)
for (const [id, status] of evseStatus.connectors) {
if (id !== connectorId && status.transactionStarted === true) {
logger.error(
- `${chargingStation.logPrefix()} Trying to start a transaction on an already used evse id ${evseId} by connector id ${id} with idTag ${
+ `${chargingStation.logPrefix()} Trying to start a transaction on an already used evse id ${evseId.toString()} by connector id ${id.toString()} with idTag ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
status.transactionIdTag
}`
)
connectorStatus?.status !== OCPP16ChargePointStatus.Preparing
) {
logger.error(
- `${chargingStation.logPrefix()} Trying to start a transaction on connector id ${connectorId} with status ${connectorStatus?.status}`
+ `${chargingStation.logPrefix()} Trying to start a transaction on connector id ${connectorId.toString()} with status ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ connectorStatus?.status
+ }`
)
return
}
if (!Number.isSafeInteger(payload.transactionId)) {
logger.warn(
- `${chargingStation.logPrefix()} Trying to start a transaction on connector id ${connectorId} with a non integer transaction id ${
- payload.transactionId
- }, converting to integer`
+ `${chargingStation.logPrefix()} Trying to start a transaction on connector id ${connectorId.toString()} with a non integer transaction id ${payload.transactionId.toString()}, converting to integer`
)
payload.transactionId = convertToInt(payload.transactionId)
}
if (reservation != null) {
if (reservation.idTag !== requestPayload.idTag) {
logger.warn(
- `${chargingStation.logPrefix()} Reserved transaction ${
- payload.transactionId
- } started with a different idTag ${requestPayload.idTag} than the reservation one ${
- reservation.idTag
- }`
+ `${chargingStation.logPrefix()} Reserved transaction ${payload.transactionId.toString()} started with a different idTag ${
+ requestPayload.idTag
+ } than the reservation one ${reservation.idTag}`
)
}
if (hasReservationExpired(reservation)) {
logger.warn(
- `${chargingStation.logPrefix()} Reserved transaction ${
- payload.transactionId
- } started with expired reservation ${
- requestPayload.reservationId
- } (expiry date: ${reservation.expiryDate.toISOString()}))`
+ `${chargingStation.logPrefix()} Reserved transaction ${payload.transactionId.toString()} started with expired reservation ${requestPayload.reservationId.toString()} (expiry date: ${reservation.expiryDate.toISOString()}))`
)
}
await chargingStation.removeReservation(
)
} else {
logger.warn(
- `${chargingStation.logPrefix()} Reserved transaction ${
- payload.transactionId
- } started with unknown reservation ${requestPayload.reservationId}`
+ `${chargingStation.logPrefix()} Reserved transaction ${payload.transactionId.toString()} started with unknown reservation ${requestPayload.reservationId.toString()}`
)
}
}
chargingStation.stationInfo?.beginEndMeterValues === true &&
(await chargingStation.ocppRequestService.requestHandler<
- OCPP16MeterValuesRequest,
- OCPP16MeterValuesResponse
+ OCPP16MeterValuesRequest,
+ OCPP16MeterValuesResponse
>(chargingStation, OCPP16RequestCommand.METER_VALUES, {
connectorId,
+ meterValue: [connectorStatus.transactionBeginMeterValue],
transactionId: payload.transactionId,
- meterValue: [connectorStatus.transactionBeginMeterValue]
} satisfies OCPP16MeterValuesRequest))
await OCPP16ServiceUtils.sendAndSetConnectorStatus(
chargingStation,
OCPP16ChargePointStatus.Charging
)
logger.info(
- `${chargingStation.logPrefix()} Transaction with id ${
- payload.transactionId
- } STARTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId} for idTag '${
- requestPayload.idTag
- }'`
+ `${chargingStation.logPrefix()} Transaction with id ${payload.transactionId.toString()} STARTED on ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ chargingStation.stationInfo?.chargingStationId
+ }#${connectorId.toString()} for idTag '${requestPayload.idTag}'`
)
if (chargingStation.stationInfo?.powerSharedByConnectors === true) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
)
} else {
logger.warn(
- `${chargingStation.logPrefix()} Starting transaction with id ${
- payload.transactionId
- } REJECTED on ${
+ `${chargingStation.logPrefix()} Starting transaction with id ${payload.transactionId.toString()} REJECTED on ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
chargingStation.stationInfo?.chargingStationId
- }#${connectorId} with status '${payload.idTagInfo.status}', idTag '${
+ }#${connectorId.toString()} with status '${payload.idTagInfo.status}', idTag '${
requestPayload.idTag
}'${
OCPP16ServiceUtils.hasReservation(chargingStation, connectorId, requestPayload.idTag)
- ? `, reservationId '${requestPayload.reservationId}'`
+ ? // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `, reservationId '${requestPayload.reservationId?.toString()}'`
: ''
}`
)
}
}
- private async resetConnectorOnStartTransactionError (
- chargingStation: ChargingStation,
- connectorId: number
- ): Promise<void> {
- chargingStation.stopMeterValues(connectorId)
- const connectorStatus = chargingStation.getConnectorStatus(connectorId)
- resetConnectorStatus(connectorStatus)
- await OCPP16ServiceUtils.restoreConnectorStatus(chargingStation, connectorId, connectorStatus)
- }
-
private async handleResponseStopTransaction (
chargingStation: ChargingStation,
payload: OCPP16StopTransactionResponse,
)
if (transactionConnectorId == null) {
logger.error(
- `${chargingStation.logPrefix()} Trying to stop a non existing transaction with id ${
- requestPayload.transactionId
- }`
+ `${chargingStation.logPrefix()} Trying to stop a non existing transaction with id ${requestPayload.transactionId.toString()}`
)
return
}
chargingStation.stationInfo.ocppStrictCompliance === false &&
chargingStation.stationInfo.outOfOrderEndMeterValues === true &&
(await chargingStation.ocppRequestService.requestHandler<
- OCPP16MeterValuesRequest,
- OCPP16MeterValuesResponse
+ OCPP16MeterValuesRequest,
+ OCPP16MeterValuesResponse
>(chargingStation, OCPP16RequestCommand.METER_VALUES, {
connectorId: transactionConnectorId,
- transactionId: requestPayload.transactionId,
meterValue: [
OCPP16ServiceUtils.buildTransactionEndMeterValue(
chargingStation,
transactionConnectorId,
requestPayload.meterStop
- )
- ]
+ ),
+ ],
+ transactionId: requestPayload.transactionId,
}))
if (
!chargingStation.isChargingStationAvailable() ||
}
resetConnectorStatus(chargingStation.getConnectorStatus(transactionConnectorId))
chargingStation.stopMeterValues(transactionConnectorId)
- const logMsg = `${chargingStation.logPrefix()} Transaction with id ${
- requestPayload.transactionId
- } STOPPED on ${
+ const logMsg = `${chargingStation.logPrefix()} Transaction with id ${requestPayload.transactionId.toString()} STOPPED on ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
chargingStation.stationInfo?.chargingStationId
- }#${transactionConnectorId} with status '${payload.idTagInfo?.status}'`
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ }#${transactionConnectorId.toString()} with status '${payload.idTagInfo?.status}'`
if (
payload.idTagInfo == null ||
payload.idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED
logger.warn(logMsg)
}
}
+
+ private async resetConnectorOnStartTransactionError (
+ chargingStation: ChargingStation,
+ connectorId: number
+ ): Promise<void> {
+ chargingStation.stopMeterValues(connectorId)
+ const connectorStatus = chargingStation.getConnectorStatus(connectorId)
+ resetConnectorStatus(connectorStatus)
+ await OCPP16ServiceUtils.restoreConnectorStatus(chargingStation, connectorId, connectorStatus)
+ }
+
+ private validatePayload (
+ chargingStation: ChargingStation,
+ commandName: OCPP16RequestCommand,
+ payload: JsonType
+ ): boolean {
+ if (this.payloadValidateFunctions.has(commandName)) {
+ return this.validateResponsePayload(chargingStation, commandName, payload)
+ }
+ logger.warn(
+ `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema validation function found for command '${commandName}' PDU validation`
+ )
+ return false
+ }
}
// Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
import type { JSONSchemaType } from 'ajv'
+
import {
addSeconds,
areIntervalsOverlapping,
type Interval,
isAfter,
isBefore,
- isWithinInterval
+ isWithinInterval,
} from 'date-fns'
import {
type ChargingStation,
hasFeatureProfile,
- hasReservationExpired
+ hasReservationExpired,
} from '../../../charging-station/index.js'
import {
type ConfigurationKey,
OCPP16StandardParametersKey,
OCPP16StopTransactionReason,
type OCPP16SupportedFeatureProfiles,
- OCPPVersion
+ OCPPVersion,
} from '../../../types/index.js'
import { convertToDate, isNotEmptyArray, logger, roundTo } from '../../../utils/index.js'
import { OCPPServiceUtils } from '../OCPPServiceUtils.js'
import { OCPP16Constants } from './OCPP16Constants.js'
export class OCPP16ServiceUtils extends OCPPServiceUtils {
- public static checkFeatureProfile (
- chargingStation: ChargingStation,
- featureProfile: OCPP16SupportedFeatureProfiles,
- command: OCPP16RequestCommand | OCPP16IncomingRequestCommand
- ): boolean {
- if (hasFeatureProfile(chargingStation, featureProfile) === false) {
- logger.warn(
- `${chargingStation.logPrefix()} Trying to '${command}' without '${featureProfile}' feature enabled in ${
- OCPP16StandardParametersKey.SupportedFeatureProfiles
- } in configuration`
- )
- return false
- }
- return true
- }
-
public static buildTransactionBeginMeterValue (
chargingStation: ChargingStation,
connectorId: number,
meterStart: number | undefined
): OCPP16MeterValue {
const meterValue: OCPP16MeterValue = {
+ sampledValue: [],
timestamp: new Date(),
- sampledValue: []
}
// Energy.Active.Import.Register measurand (default)
const sampledValueTemplate = OCPP16ServiceUtils.getSampledValueTemplate(
return meterValues
}
- public static remoteStopTransaction = async (
- chargingStation: ChargingStation,
- connectorId: number
- ): Promise<GenericResponse> => {
- await OCPP16ServiceUtils.sendAndSetConnectorStatus(
- chargingStation,
- connectorId,
- OCPP16ChargePointStatus.Finishing
- )
- const stopResponse = await chargingStation.stopTransactionOnConnector(
- connectorId,
- OCPP16StopTransactionReason.REMOTE
- )
- if (stopResponse.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
- return OCPP16Constants.OCPP_RESPONSE_ACCEPTED
- }
- return OCPP16Constants.OCPP_RESPONSE_REJECTED
- }
-
public static changeAvailability = async (
chargingStation: ChargingStation,
connectorIds: number[],
return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED
}
- public static setChargingProfile (
+ public static checkFeatureProfile (
chargingStation: ChargingStation,
- connectorId: number,
- cp: OCPP16ChargingProfile
- ): void {
- if (chargingStation.getConnectorStatus(connectorId)?.chargingProfiles == null) {
- logger.error(
- `${chargingStation.logPrefix()} Trying to set a charging profile on connector id ${connectorId} with an uninitialized charging profiles array attribute, applying deferred initialization`
- )
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- chargingStation.getConnectorStatus(connectorId)!.chargingProfiles = []
- }
- if (!Array.isArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)) {
- logger.error(
- `${chargingStation.logPrefix()} Trying to set a charging profile on connector id ${connectorId} with an improper attribute type for the charging profiles array, applying proper type deferred initialization`
+ featureProfile: OCPP16SupportedFeatureProfiles,
+ command: OCPP16IncomingRequestCommand | OCPP16RequestCommand
+ ): boolean {
+ if (hasFeatureProfile(chargingStation, featureProfile) === false) {
+ logger.warn(
+ `${chargingStation.logPrefix()} Trying to '${command}' without '${featureProfile}' feature enabled in ${
+ OCPP16StandardParametersKey.SupportedFeatureProfiles
+ } in configuration`
)
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- chargingStation.getConnectorStatus(connectorId)!.chargingProfiles = []
- }
- cp.chargingSchedule.startSchedule = convertToDate(cp.chargingSchedule.startSchedule)
- cp.validFrom = convertToDate(cp.validFrom)
- cp.validTo = convertToDate(cp.validTo)
- let cpReplaced = false
- if (isNotEmptyArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- for (const [index, chargingProfile] of chargingStation
- .getConnectorStatus(connectorId)!
- .chargingProfiles!.entries()) {
- if (
- chargingProfile.chargingProfileId === cp.chargingProfileId ||
- (chargingProfile.stackLevel === cp.stackLevel &&
- chargingProfile.chargingProfilePurpose === cp.chargingProfilePurpose)
- ) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- chargingStation.getConnectorStatus(connectorId)!.chargingProfiles![index] = cp
- cpReplaced = true
- }
- }
+ return false
}
- !cpReplaced && chargingStation.getConnectorStatus(connectorId)?.chargingProfiles?.push(cp)
+ return true
}
public static clearChargingProfiles = (
commandPayload: OCPP16ClearChargingProfileRequest,
chargingProfiles: OCPP16ChargingProfile[] | undefined
): boolean => {
- const { id, chargingProfilePurpose, stackLevel } = commandPayload
+ const { chargingProfilePurpose, id, stackLevel } = commandPayload
let clearedCP = false
if (isNotEmptyArray(chargingProfiles)) {
chargingProfiles.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
OCPP16ServiceUtils.composeChargingSchedule(chargingScheduleLower!, compositeInterval)
const compositeChargingScheduleHigherInterval: Interval = {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- start: compositeChargingScheduleHigher!.startSchedule!,
end: addSeconds(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
compositeChargingScheduleHigher!.startSchedule!,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
compositeChargingScheduleHigher!.duration!
- )
+ ),
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ start: compositeChargingScheduleHigher!.startSchedule!,
}
const compositeChargingScheduleLowerInterval: Interval = {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- start: compositeChargingScheduleLower!.startSchedule!,
end: addSeconds(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
compositeChargingScheduleLower!.startSchedule!,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
compositeChargingScheduleLower!.duration!
- )
+ ),
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ start: compositeChargingScheduleLower!.startSchedule!,
}
const higherFirst = isBefore(
compositeChargingScheduleHigherInterval.start,
...compositeChargingScheduleLower,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
...compositeChargingScheduleHigher!,
- startSchedule: higherFirst
- ? (compositeChargingScheduleHigherInterval.start as Date)
- : (compositeChargingScheduleLowerInterval.start as Date),
- duration: higherFirst
- ? differenceInSeconds(
- compositeChargingScheduleLowerInterval.end,
- compositeChargingScheduleHigherInterval.start
- )
- : differenceInSeconds(
- compositeChargingScheduleHigherInterval.end,
- compositeChargingScheduleLowerInterval.start
- ),
chargingSchedulePeriod: [
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
...compositeChargingScheduleHigher!.chargingSchedulePeriod.map(schedulePeriod => {
differenceInSeconds(
compositeChargingScheduleHigherInterval.start,
compositeChargingScheduleLowerInterval.start
- )
+ ),
}
}),
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
compositeChargingScheduleLowerInterval.start,
compositeChargingScheduleHigherInterval.start
)
- : 0
+ : 0,
}
- })
- ].sort((a, b) => a.startPeriod - b.startPeriod)
+ }),
+ ].sort((a, b) => a.startPeriod - b.startPeriod),
+ duration: higherFirst
+ ? differenceInSeconds(
+ compositeChargingScheduleLowerInterval.end,
+ compositeChargingScheduleHigherInterval.start
+ )
+ : differenceInSeconds(
+ compositeChargingScheduleHigherInterval.end,
+ compositeChargingScheduleLowerInterval.start
+ ),
+ startSchedule: higherFirst
+ ? (compositeChargingScheduleHigherInterval.start as Date)
+ : (compositeChargingScheduleLowerInterval.start as Date),
}
}
return {
...compositeChargingScheduleLower,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
...compositeChargingScheduleHigher!,
- startSchedule: higherFirst
- ? (compositeChargingScheduleHigherInterval.start as Date)
- : (compositeChargingScheduleLowerInterval.start as Date),
- duration: higherFirst
- ? differenceInSeconds(
- compositeChargingScheduleLowerInterval.end,
- compositeChargingScheduleHigherInterval.start
- )
- : differenceInSeconds(
- compositeChargingScheduleHigherInterval.end,
- compositeChargingScheduleLowerInterval.start
- ),
chargingSchedulePeriod: [
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
...compositeChargingScheduleHigher!.chargingSchedulePeriod.map(schedulePeriod => {
differenceInSeconds(
compositeChargingScheduleHigherInterval.start,
compositeChargingScheduleLowerInterval.start
- )
+ ),
}
}),
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
schedulePeriod.startPeriod
),
{
+ end: compositeChargingScheduleHigherInterval.end,
start: compositeChargingScheduleLowerInterval.start,
- end: compositeChargingScheduleHigherInterval.end
}
)
) {
schedulePeriod.startPeriod
),
{
+ end: compositeChargingScheduleHigherInterval.end,
start: compositeChargingScheduleLowerInterval.start,
- end: compositeChargingScheduleHigherInterval.end
}
) &&
isWithinInterval(
compositeChargingScheduleLower!.chargingSchedulePeriod[index + 1].startPeriod
),
{
+ end: compositeChargingScheduleHigherInterval.end,
start: compositeChargingScheduleLowerInterval.start,
- end: compositeChargingScheduleHigherInterval.end
}
)
) {
schedulePeriod.startPeriod
),
{
+ end: compositeChargingScheduleLowerInterval.end,
start: compositeChargingScheduleHigherInterval.start,
- end: compositeChargingScheduleLowerInterval.end
}
)
) {
compositeChargingScheduleLowerInterval.start,
compositeChargingScheduleHigherInterval.start
)
- : 0
+ : 0,
}
- })
- ].sort((a, b) => a.startPeriod - b.startPeriod)
+ }),
+ ].sort((a, b) => a.startPeriod - b.startPeriod),
+ duration: higherFirst
+ ? differenceInSeconds(
+ compositeChargingScheduleLowerInterval.end,
+ compositeChargingScheduleHigherInterval.start
+ )
+ : differenceInSeconds(
+ compositeChargingScheduleHigherInterval.end,
+ compositeChargingScheduleLowerInterval.start
+ ),
+ startSchedule: higherFirst
+ ? (compositeChargingScheduleHigherInterval.start as Date)
+ : (compositeChargingScheduleLowerInterval.start as Date),
}
}
- public static isConfigurationKeyVisible (key: ConfigurationKey): boolean {
- if (key.visible == null) {
- return true
- }
- return key.visible
- }
-
public static hasReservation = (
chargingStation: ChargingStation,
connectorId: number,
chargingStationReservation.idTag === idTag)
) {
logger.debug(
- `${chargingStation.logPrefix()} Connector id ${connectorId} has a valid reservation for idTag ${idTag}: %j`,
+ `${chargingStation.logPrefix()} Connector id ${connectorId.toString()} has a valid reservation for idTag ${idTag}: %j`,
connectorReservation ?? chargingStationReservation
)
return true
return false
}
- public static parseJsonSchemaFile<T extends JsonType>(
+ public static isConfigurationKeyVisible (key: ConfigurationKey): boolean {
+ if (key.visible == null) {
+ return true
+ }
+ return key.visible
+ }
+
+ public static override parseJsonSchemaFile<T extends JsonType>(
relativePath: string,
moduleName?: string,
methodName?: string
): JSONSchemaType<T> {
- return super.parseJsonSchemaFile<T>(
+ return OCPPServiceUtils.parseJsonSchemaFile<T>(
relativePath,
OCPPVersion.VERSION_16,
moduleName,
)
}
+ public static remoteStopTransaction = async (
+ chargingStation: ChargingStation,
+ connectorId: number
+ ): Promise<GenericResponse> => {
+ await OCPP16ServiceUtils.sendAndSetConnectorStatus(
+ chargingStation,
+ connectorId,
+ OCPP16ChargePointStatus.Finishing
+ )
+ const stopResponse = await chargingStation.stopTransactionOnConnector(
+ connectorId,
+ OCPP16StopTransactionReason.REMOTE
+ )
+ if (stopResponse.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
+ return OCPP16Constants.OCPP_RESPONSE_ACCEPTED
+ }
+ return OCPP16Constants.OCPP_RESPONSE_REJECTED
+ }
+
+ public static setChargingProfile (
+ chargingStation: ChargingStation,
+ connectorId: number,
+ cp: OCPP16ChargingProfile
+ ): void {
+ if (chargingStation.getConnectorStatus(connectorId)?.chargingProfiles == null) {
+ logger.error(
+ `${chargingStation.logPrefix()} Trying to set a charging profile on connector id ${connectorId.toString()} with an uninitialized charging profiles array attribute, applying deferred initialization`
+ )
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.getConnectorStatus(connectorId)!.chargingProfiles = []
+ }
+ if (!Array.isArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)) {
+ logger.error(
+ `${chargingStation.logPrefix()} Trying to set a charging profile on connector id ${connectorId.toString()} with an improper attribute type for the charging profiles array, applying proper type deferred initialization`
+ )
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.getConnectorStatus(connectorId)!.chargingProfiles = []
+ }
+ cp.chargingSchedule.startSchedule = convertToDate(cp.chargingSchedule.startSchedule)
+ cp.validFrom = convertToDate(cp.validFrom)
+ cp.validTo = convertToDate(cp.validTo)
+ let cpReplaced = false
+ if (isNotEmptyArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ for (const [index, chargingProfile] of chargingStation
+ .getConnectorStatus(connectorId)!
+ .chargingProfiles!.entries()) {
+ if (
+ chargingProfile.chargingProfileId === cp.chargingProfileId ||
+ (chargingProfile.stackLevel === cp.stackLevel &&
+ chargingProfile.chargingProfilePurpose === cp.chargingProfilePurpose)
+ ) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.getConnectorStatus(connectorId)!.chargingProfiles![index] = cp
+ cpReplaced = true
+ }
+ }
+ }
+ !cpReplaced && chargingStation.getConnectorStatus(connectorId)?.chargingProfiles?.push(cp)
+ }
+
private static readonly composeChargingSchedule = (
chargingSchedule: OCPP16ChargingSchedule,
compositeInterval: Interval
): OCPP16ChargingSchedule | undefined => {
const chargingScheduleInterval: Interval = {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- start: chargingSchedule.startSchedule!,
+ end: addSeconds(chargingSchedule.startSchedule!, chargingSchedule.duration!),
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- end: addSeconds(chargingSchedule.startSchedule!, chargingSchedule.duration!)
+ start: chargingSchedule.startSchedule!,
}
if (areIntervalsOverlapping(chargingScheduleInterval, compositeInterval)) {
chargingSchedule.chargingSchedulePeriod.sort((a, b) => a.startPeriod - b.startPeriod)
if (isBefore(chargingScheduleInterval.start, compositeInterval.start)) {
return {
...chargingSchedule,
- startSchedule: compositeInterval.start as Date,
- duration: differenceInSeconds(
- chargingScheduleInterval.end,
- compositeInterval.start as Date
- ),
chargingSchedulePeriod: chargingSchedule.chargingSchedulePeriod
.filter((schedulePeriod, index) => {
if (
schedulePeriod.startPeriod = 0
}
return schedulePeriod
- })
+ }),
+ duration: differenceInSeconds(
+ chargingScheduleInterval.end,
+ compositeInterval.start as Date
+ ),
+ startSchedule: compositeInterval.start as Date,
}
}
if (isAfter(chargingScheduleInterval.end, compositeInterval.end)) {
return {
...chargingSchedule,
- duration: differenceInSeconds(
- compositeInterval.end as Date,
- chargingScheduleInterval.start
- ),
chargingSchedulePeriod: chargingSchedule.chargingSchedulePeriod.filter(schedulePeriod =>
isWithinInterval(
addSeconds(chargingScheduleInterval.start, schedulePeriod.startPeriod),
compositeInterval
)
- )
+ ),
+ duration: differenceInSeconds(
+ compositeInterval.end as Date,
+ chargingScheduleInterval.start
+ ),
}
}
return chargingSchedule
import {
type ConnectorStatusTransition,
- OCPP20ConnectorStatusEnumType
+ OCPP20ConnectorStatusEnumType,
} from '../../../types/index.js'
import { OCPPConstants } from '../OCPPConstants.js'
export class OCPP20Constants extends OCPPConstants {
- static readonly ChargingStationStatusTransitions: Readonly<ConnectorStatusTransition[]> =
+ static readonly ChargingStationStatusTransitions: readonly ConnectorStatusTransition[] =
Object.freeze([
{ to: OCPP20ConnectorStatusEnumType.Available },
// { from: OCPP20ConnectorStatusEnumType.Available, to: OCPP20ConnectorStatusEnumType.Available },
{
from: OCPP20ConnectorStatusEnumType.Available,
- to: OCPP20ConnectorStatusEnumType.Unavailable
+ to: OCPP20ConnectorStatusEnumType.Unavailable,
+ },
+ {
+ from: OCPP20ConnectorStatusEnumType.Available,
+ to: OCPP20ConnectorStatusEnumType.Faulted,
},
- { from: OCPP20ConnectorStatusEnumType.Available, to: OCPP20ConnectorStatusEnumType.Faulted },
{ to: OCPP20ConnectorStatusEnumType.Unavailable },
{
from: OCPP20ConnectorStatusEnumType.Unavailable,
- to: OCPP20ConnectorStatusEnumType.Available
+ to: OCPP20ConnectorStatusEnumType.Available,
},
// {
// from: OCPP20ConnectorStatusEnumType.Unavailable,
// },
{
from: OCPP20ConnectorStatusEnumType.Unavailable,
- to: OCPP20ConnectorStatusEnumType.Faulted
+ to: OCPP20ConnectorStatusEnumType.Faulted,
},
{ to: OCPP20ConnectorStatusEnumType.Faulted },
- { from: OCPP20ConnectorStatusEnumType.Faulted, to: OCPP20ConnectorStatusEnumType.Available },
{
from: OCPP20ConnectorStatusEnumType.Faulted,
- to: OCPP20ConnectorStatusEnumType.Unavailable
- }
- // { from: OCPP20ConnectorStatusEnumType.Faulted, to: OCPP20ConnectorStatusEnumType.Faulted }
- ])
-
- static readonly ConnectorStatusTransitions: Readonly<ConnectorStatusTransition[]> = Object.freeze(
- [
- { to: OCPP20ConnectorStatusEnumType.Available },
- // { from: OCPP20ConnectorStatusEnumType.Available, to: OCPP20ConnectorStatusEnumType.Available },
- { from: OCPP20ConnectorStatusEnumType.Available, to: OCPP20ConnectorStatusEnumType.Occupied },
- { from: OCPP20ConnectorStatusEnumType.Available, to: OCPP20ConnectorStatusEnumType.Reserved },
- {
- from: OCPP20ConnectorStatusEnumType.Available,
- to: OCPP20ConnectorStatusEnumType.Unavailable
- },
- { from: OCPP20ConnectorStatusEnumType.Available, to: OCPP20ConnectorStatusEnumType.Faulted },
- // { to: OCPP20ConnectorStatusEnumType.Occupied },
- { from: OCPP20ConnectorStatusEnumType.Occupied, to: OCPP20ConnectorStatusEnumType.Available },
- // { from: OCPP20ConnectorStatusEnumType.Occupied, to: OCPP20ConnectorStatusEnumType.Occupied },
- // { from: OCPP20ConnectorStatusEnumType.Occupied, to: OCPP20ConnectorStatusEnumType.Reserved },
- {
- from: OCPP20ConnectorStatusEnumType.Occupied,
- to: OCPP20ConnectorStatusEnumType.Unavailable
- },
- { from: OCPP20ConnectorStatusEnumType.Occupied, to: OCPP20ConnectorStatusEnumType.Faulted },
- // { to: OCPP20ConnectorStatusEnumType.Reserved },
- { from: OCPP20ConnectorStatusEnumType.Reserved, to: OCPP20ConnectorStatusEnumType.Available },
- { from: OCPP20ConnectorStatusEnumType.Reserved, to: OCPP20ConnectorStatusEnumType.Occupied },
- // { from: OCPP20ConnectorStatusEnumType.Reserved, to: OCPP20ConnectorStatusEnumType.Reserved },
- {
- from: OCPP20ConnectorStatusEnumType.Reserved,
- to: OCPP20ConnectorStatusEnumType.Unavailable
+ to: OCPP20ConnectorStatusEnumType.Available,
},
- { from: OCPP20ConnectorStatusEnumType.Reserved, to: OCPP20ConnectorStatusEnumType.Faulted },
- { to: OCPP20ConnectorStatusEnumType.Unavailable },
- {
- from: OCPP20ConnectorStatusEnumType.Unavailable,
- to: OCPP20ConnectorStatusEnumType.Available
- },
- {
- from: OCPP20ConnectorStatusEnumType.Unavailable,
- to: OCPP20ConnectorStatusEnumType.Occupied
- },
- // { from: OCPP20ConnectorStatusEnumType.Unavailable, to: OCPP20ConnectorStatusEnumType.Reserved },
- // { from: OCPP20ConnectorStatusEnumType.Unavailable, to: OCPP20ConnectorStatusEnumType.Unavailable },
- {
- from: OCPP20ConnectorStatusEnumType.Unavailable,
- to: OCPP20ConnectorStatusEnumType.Faulted
- },
- { to: OCPP20ConnectorStatusEnumType.Faulted },
- { from: OCPP20ConnectorStatusEnumType.Faulted, to: OCPP20ConnectorStatusEnumType.Available },
- { from: OCPP20ConnectorStatusEnumType.Faulted, to: OCPP20ConnectorStatusEnumType.Occupied },
- { from: OCPP20ConnectorStatusEnumType.Faulted, to: OCPP20ConnectorStatusEnumType.Reserved },
{
from: OCPP20ConnectorStatusEnumType.Faulted,
- to: OCPP20ConnectorStatusEnumType.Unavailable
- }
+ to: OCPP20ConnectorStatusEnumType.Unavailable,
+ },
// { from: OCPP20ConnectorStatusEnumType.Faulted, to: OCPP20ConnectorStatusEnumType.Faulted }
- ]
- )
+ ])
+
+ static readonly ConnectorStatusTransitions: readonly ConnectorStatusTransition[] = Object.freeze([
+ { to: OCPP20ConnectorStatusEnumType.Available },
+ // { from: OCPP20ConnectorStatusEnumType.Available, to: OCPP20ConnectorStatusEnumType.Available },
+ {
+ from: OCPP20ConnectorStatusEnumType.Available,
+ to: OCPP20ConnectorStatusEnumType.Occupied,
+ },
+ {
+ from: OCPP20ConnectorStatusEnumType.Available,
+ to: OCPP20ConnectorStatusEnumType.Reserved,
+ },
+ {
+ from: OCPP20ConnectorStatusEnumType.Available,
+ to: OCPP20ConnectorStatusEnumType.Unavailable,
+ },
+ {
+ from: OCPP20ConnectorStatusEnumType.Available,
+ to: OCPP20ConnectorStatusEnumType.Faulted,
+ },
+ // { to: OCPP20ConnectorStatusEnumType.Occupied },
+ {
+ from: OCPP20ConnectorStatusEnumType.Occupied,
+ to: OCPP20ConnectorStatusEnumType.Available,
+ },
+ // { from: OCPP20ConnectorStatusEnumType.Occupied, to: OCPP20ConnectorStatusEnumType.Occupied },
+ // { from: OCPP20ConnectorStatusEnumType.Occupied, to: OCPP20ConnectorStatusEnumType.Reserved },
+ {
+ from: OCPP20ConnectorStatusEnumType.Occupied,
+ to: OCPP20ConnectorStatusEnumType.Unavailable,
+ },
+ {
+ from: OCPP20ConnectorStatusEnumType.Occupied,
+ to: OCPP20ConnectorStatusEnumType.Faulted,
+ },
+ // { to: OCPP20ConnectorStatusEnumType.Reserved },
+ {
+ from: OCPP20ConnectorStatusEnumType.Reserved,
+ to: OCPP20ConnectorStatusEnumType.Available,
+ },
+ {
+ from: OCPP20ConnectorStatusEnumType.Reserved,
+ to: OCPP20ConnectorStatusEnumType.Occupied,
+ },
+ // { from: OCPP20ConnectorStatusEnumType.Reserved, to: OCPP20ConnectorStatusEnumType.Reserved },
+ {
+ from: OCPP20ConnectorStatusEnumType.Reserved,
+ to: OCPP20ConnectorStatusEnumType.Unavailable,
+ },
+ {
+ from: OCPP20ConnectorStatusEnumType.Reserved,
+ to: OCPP20ConnectorStatusEnumType.Faulted,
+ },
+ { to: OCPP20ConnectorStatusEnumType.Unavailable },
+ {
+ from: OCPP20ConnectorStatusEnumType.Unavailable,
+ to: OCPP20ConnectorStatusEnumType.Available,
+ },
+ {
+ from: OCPP20ConnectorStatusEnumType.Unavailable,
+ to: OCPP20ConnectorStatusEnumType.Occupied,
+ },
+ // { from: OCPP20ConnectorStatusEnumType.Unavailable, to: OCPP20ConnectorStatusEnumType.Reserved },
+ // { from: OCPP20ConnectorStatusEnumType.Unavailable, to: OCPP20ConnectorStatusEnumType.Unavailable },
+ {
+ from: OCPP20ConnectorStatusEnumType.Unavailable,
+ to: OCPP20ConnectorStatusEnumType.Faulted,
+ },
+ { to: OCPP20ConnectorStatusEnumType.Faulted },
+ {
+ from: OCPP20ConnectorStatusEnumType.Faulted,
+ to: OCPP20ConnectorStatusEnumType.Available,
+ },
+ {
+ from: OCPP20ConnectorStatusEnumType.Faulted,
+ to: OCPP20ConnectorStatusEnumType.Occupied,
+ },
+ {
+ from: OCPP20ConnectorStatusEnumType.Faulted,
+ to: OCPP20ConnectorStatusEnumType.Reserved,
+ },
+ {
+ from: OCPP20ConnectorStatusEnumType.Faulted,
+ to: OCPP20ConnectorStatusEnumType.Unavailable,
+ },
+ // { from: OCPP20ConnectorStatusEnumType.Faulted, to: OCPP20ConnectorStatusEnumType.Faulted }
+ ])
}
import type { ValidateFunction } from 'ajv'
import type { ChargingStation } from '../../../charging-station/index.js'
+
import { OCPPError } from '../../../exception/index.js'
import {
ErrorType,
type JsonType,
type OCPP20ClearCacheRequest,
OCPP20IncomingRequestCommand,
- OCPPVersion
+ OCPPVersion,
} from '../../../types/index.js'
import { isAsyncFunction, logger } from '../../../utils/index.js'
import { OCPPIncomingRequestService } from '../OCPPIncomingRequestService.js'
protected payloadValidateFunctions: Map<OCPP20IncomingRequestCommand, ValidateFunction<JsonType>>
private readonly incomingRequestHandlers: Map<
- OCPP20IncomingRequestCommand,
- IncomingRequestHandler
+ OCPP20IncomingRequestCommand,
+ IncomingRequestHandler
>
public constructor () {
// }
super(OCPPVersion.VERSION_201)
this.incomingRequestHandlers = new Map<OCPP20IncomingRequestCommand, IncomingRequestHandler>([
- [OCPP20IncomingRequestCommand.CLEAR_CACHE, this.handleRequestClearCache.bind(this)]
+ [OCPP20IncomingRequestCommand.CLEAR_CACHE, this.handleRequestClearCache.bind(this)],
])
this.payloadValidateFunctions = new Map<
- OCPP20IncomingRequestCommand,
- ValidateFunction<JsonType>
+ OCPP20IncomingRequestCommand,
+ ValidateFunction<JsonType>
>([
[
OCPP20IncomingRequestCommand.CLEAR_CACHE,
- this.ajv
- .compile(
- OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20ClearCacheRequest>(
- 'assets/json-schemas/ocpp/2.0/ClearCacheRequest.json',
- moduleName,
- 'constructor'
- )
+ this.ajv.compile(
+ OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20ClearCacheRequest>(
+ 'assets/json-schemas/ocpp/2.0/ClearCacheRequest.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
- ]
+ ),
+ ],
])
this.validatePayload = this.validatePayload.bind(this)
}
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
public async incomingRequestHandler<ReqType extends JsonType, ResType extends JsonType>(
chargingStation: ChargingStation,
messageId: string,
)
}
if (
- chargingStation.isRegistered() ||
+ chargingStation.inAcceptedState() ||
+ chargingStation.inPendingState() ||
(chargingStation.stationInfo?.ocppStrictCompliance === false &&
chargingStation.inUnknownState())
) {
// Throw exception
throw new OCPPError(
ErrorType.NOT_IMPLEMENTED,
- `'${commandName}' is not implemented to handle request PDU ${JSON.stringify(
+ `${commandName} is not implemented to handle request PDU ${JSON.stringify(
commandPayload,
undefined,
2
import type { ValidateFunction } from 'ajv'
import type { ChargingStation } from '../../../charging-station/index.js'
+import type { OCPPResponseService } from '../OCPPResponseService.js'
+
import { OCPPError } from '../../../exception/index.js'
import {
ErrorType,
OCPP20RequestCommand,
type OCPP20StatusNotificationRequest,
OCPPVersion,
- type RequestParams
+ type RequestParams,
} from '../../../types/index.js'
import { generateUUID } from '../../../utils/index.js'
import { OCPPRequestService } from '../OCPPRequestService.js'
-import type { OCPPResponseService } from '../OCPPResponseService.js'
import { OCPP20Constants } from './OCPP20Constants.js'
import { OCPP20ServiceUtils } from './OCPP20ServiceUtils.js'
this.payloadValidateFunctions = new Map<OCPP20RequestCommand, ValidateFunction<JsonType>>([
[
OCPP20RequestCommand.BOOT_NOTIFICATION,
- this.ajv
- .compile(
- OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20BootNotificationRequest>(
- 'assets/json-schemas/ocpp/2.0/BootNotificationRequest.json',
- moduleName,
- 'constructor'
- )
+ this.ajv.compile(
+ OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20BootNotificationRequest>(
+ 'assets/json-schemas/ocpp/2.0/BootNotificationRequest.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
OCPP20RequestCommand.HEARTBEAT,
- this.ajv
- .compile(
- OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20HeartbeatRequest>(
- 'assets/json-schemas/ocpp/2.0/HeartbeatRequest.json',
- moduleName,
- 'constructor'
- )
+ this.ajv.compile(
+ OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20HeartbeatRequest>(
+ 'assets/json-schemas/ocpp/2.0/HeartbeatRequest.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
OCPP20RequestCommand.STATUS_NOTIFICATION,
- this.ajv
- .compile(
- OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20StatusNotificationRequest>(
- 'assets/json-schemas/ocpp/2.0/StatusNotificationRequest.json',
- moduleName,
- 'constructor'
- )
+ this.ajv.compile(
+ OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20StatusNotificationRequest>(
+ 'assets/json-schemas/ocpp/2.0/StatusNotificationRequest.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
- ]
+ ),
+ ],
])
this.buildRequestPayload = this.buildRequestPayload.bind(this)
}
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
public async requestHandler<RequestType extends JsonType, ResponseType extends JsonType>(
chargingStation: ChargingStation,
commandName: OCPP20RequestCommand,
): Promise<ResponseType> {
// FIXME?: add sanity checks on charging station availability, connector availability, connector status, etc.
if (OCPP20ServiceUtils.isRequestCommandSupported(chargingStation, commandName)) {
- // TODO: post request actions hook
+ // TODO: pre request actions hook
return (await this.sendMessage(
chargingStation,
generateUUID(),
// OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
throw new OCPPError(
ErrorType.NOT_SUPPORTED,
- `Unsupported OCPP command '${commandName}'`,
+ `Unsupported OCPP command ${commandName}`,
commandName,
commandParams
)
}
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
private buildRequestPayload<Request extends JsonType>(
chargingStation: ChargingStation,
commandName: OCPP20RequestCommand,
case OCPP20RequestCommand.STATUS_NOTIFICATION:
return {
timestamp: new Date(),
- ...commandParams
+ ...commandParams,
} as unknown as Request
default:
// OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
throw new OCPPError(
ErrorType.NOT_SUPPORTED,
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- `Unsupported OCPP command '${commandName}'`,
+ `Unsupported OCPP command ${commandName}`,
commandName,
commandParams
)
import { addConfigurationKey, type ChargingStation } from '../../../charging-station/index.js'
import { OCPPError } from '../../../exception/index.js'
import {
+ ChargingStationEvents,
ErrorType,
type JsonType,
type OCPP20BootNotificationResponse,
type OCPP20StatusNotificationResponse,
OCPPVersion,
RegistrationStatusEnumType,
- type ResponseHandler
+ type ResponseHandler,
} from '../../../types/index.js'
import { isAsyncFunction, logger } from '../../../utils/index.js'
import { OCPPResponseService } from '../OCPPResponseService.js'
export class OCPP20ResponseService extends OCPPResponseService {
public incomingRequestResponsePayloadValidateFunctions: Map<
- OCPP20IncomingRequestCommand,
- ValidateFunction<JsonType>
+ OCPP20IncomingRequestCommand,
+ ValidateFunction<JsonType>
>
protected payloadValidateFunctions: Map<OCPP20RequestCommand, ValidateFunction<JsonType>>
this.responseHandlers = new Map<OCPP20RequestCommand, ResponseHandler>([
[
OCPP20RequestCommand.BOOT_NOTIFICATION,
- this.handleResponseBootNotification.bind(this) as ResponseHandler
+ this.handleResponseBootNotification.bind(this) as ResponseHandler,
],
[OCPP20RequestCommand.HEARTBEAT, this.emptyResponseHandler],
- [OCPP20RequestCommand.STATUS_NOTIFICATION, this.emptyResponseHandler]
+ [OCPP20RequestCommand.STATUS_NOTIFICATION, this.emptyResponseHandler],
])
this.payloadValidateFunctions = new Map<OCPP20RequestCommand, ValidateFunction<JsonType>>([
[
OCPP20RequestCommand.BOOT_NOTIFICATION,
- this.ajv
- .compile(
- OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20BootNotificationResponse>(
- 'assets/json-schemas/ocpp/2.0/BootNotificationResponse.json',
- moduleName,
- 'constructor'
- )
+ this.ajv.compile(
+ OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20BootNotificationResponse>(
+ 'assets/json-schemas/ocpp/2.0/BootNotificationResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
OCPP20RequestCommand.HEARTBEAT,
- this.ajv
- .compile(
- OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20HeartbeatResponse>(
- 'assets/json-schemas/ocpp/2.0/HeartbeatResponse.json',
- moduleName,
- 'constructor'
- )
+ this.ajv.compile(
+ OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20HeartbeatResponse>(
+ 'assets/json-schemas/ocpp/2.0/HeartbeatResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
+ ),
],
[
OCPP20RequestCommand.STATUS_NOTIFICATION,
- this.ajv
- .compile(
- OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20StatusNotificationResponse>(
- 'assets/json-schemas/ocpp/2.0/StatusNotificationResponse.json',
- moduleName,
- 'constructor'
- )
+ this.ajv.compile(
+ OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20StatusNotificationResponse>(
+ 'assets/json-schemas/ocpp/2.0/StatusNotificationResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
- ]
+ ),
+ ],
])
this.incomingRequestResponsePayloadValidateFunctions = new Map<
- OCPP20IncomingRequestCommand,
- ValidateFunction<JsonType>
+ OCPP20IncomingRequestCommand,
+ ValidateFunction<JsonType>
>([
[
OCPP20IncomingRequestCommand.CLEAR_CACHE,
- this.ajvIncomingRequest
- .compile(
- OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20ClearCacheResponse>(
- 'assets/json-schemas/ocpp/2.0/ClearCacheResponse.json',
- moduleName,
- 'constructor'
- )
+ this.ajvIncomingRequest.compile(
+ OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20ClearCacheResponse>(
+ 'assets/json-schemas/ocpp/2.0/ClearCacheResponse.json',
+ moduleName,
+ 'constructor'
)
- .bind(this)
- ]
+ ),
+ ],
])
this.validatePayload = this.validatePayload.bind(this)
}
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
public async responseHandler<ReqType extends JsonType, ResType extends JsonType>(
chargingStation: ChargingStation,
commandName: OCPP20RequestCommand,
payload: ResType,
requestPayload: ReqType
): Promise<void> {
- if (chargingStation.isRegistered() || commandName === OCPP20RequestCommand.BOOT_NOTIFICATION) {
+ if (
+ chargingStation.inAcceptedState() ||
+ ((chargingStation.inUnknownState() || chargingStation.inPendingState()) &&
+ commandName === OCPP20RequestCommand.BOOT_NOTIFICATION) ||
+ (chargingStation.stationInfo?.ocppStrictCompliance === false &&
+ (chargingStation.inUnknownState() || chargingStation.inPendingState()))
+ ) {
if (
this.responseHandlers.has(commandName) &&
OCPP20ServiceUtils.isRequestCommandSupported(chargingStation, commandName)
if (isAsyncFunction(responseHandler)) {
await responseHandler(chargingStation, payload, requestPayload)
} else {
- (
+ ;(
responseHandler as (
chargingStation: ChargingStation,
payload: JsonType,
// Throw exception
throw new OCPPError(
ErrorType.NOT_IMPLEMENTED,
- `'${commandName}' is not implemented to handle response PDU ${JSON.stringify(
+ `${commandName} is not implemented to handle response PDU ${JSON.stringify(
payload,
undefined,
2
}
}
- private validatePayload (
- chargingStation: ChargingStation,
- commandName: OCPP20RequestCommand,
- payload: JsonType
- ): boolean {
- if (this.payloadValidateFunctions.has(commandName)) {
- return this.validateResponsePayload(chargingStation, commandName, payload)
- }
- logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema validation function found for command '${commandName}' PDU validation`
- )
- return false
- }
-
private handleResponseBootNotification (
chargingStation: ChargingStation,
payload: OCPP20BootNotificationResponse
): void {
- if (payload.status === RegistrationStatusEnumType.ACCEPTED) {
- addConfigurationKey(
- chargingStation,
- OCPP20OptionalVariableName.HeartbeatInterval,
- payload.interval.toString(),
- {},
- { overwrite: true, save: true }
- )
- OCPP20ServiceUtils.startHeartbeatInterval(chargingStation, payload.interval)
- }
if (Object.values(RegistrationStatusEnumType).includes(payload.status)) {
+ chargingStation.bootNotificationResponse = payload
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ if (payload.interval != null) {
+ addConfigurationKey(
+ chargingStation,
+ OCPP20OptionalVariableName.HeartbeatInterval,
+ payload.interval.toString(),
+ {},
+ { overwrite: true, save: true }
+ )
+ }
+ if (chargingStation.inAcceptedState()) {
+ chargingStation.emit(ChargingStationEvents.accepted)
+ } else if (chargingStation.inPendingState()) {
+ chargingStation.emit(ChargingStationEvents.pending)
+ } else if (chargingStation.inRejectedState()) {
+ chargingStation.emit(ChargingStationEvents.rejected)
+ }
const logMsg = `${chargingStation.logPrefix()} Charging station in '${
payload.status
}' state on the central server`
? logger.warn(logMsg)
: logger.info(logMsg)
} else {
+ delete chargingStation.bootNotificationResponse
logger.error(
`${chargingStation.logPrefix()} Charging station boot notification response received: %j with undefined registration status`,
payload
)
}
}
+
+ private validatePayload (
+ chargingStation: ChargingStation,
+ commandName: OCPP20RequestCommand,
+ payload: JsonType
+ ): boolean {
+ if (this.payloadValidateFunctions.has(commandName)) {
+ return this.validateResponsePayload(chargingStation, commandName, payload)
+ }
+ logger.warn(
+ `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema validation function found for command '${commandName}' PDU validation`
+ )
+ return false
+ }
}
import { OCPPServiceUtils } from '../OCPPServiceUtils.js'
export class OCPP20ServiceUtils extends OCPPServiceUtils {
- public static parseJsonSchemaFile<T extends JsonType>(
+ public static override parseJsonSchemaFile<T extends JsonType>(
relativePath: string,
moduleName?: string,
methodName?: string
): JSONSchemaType<T> {
- return super.parseJsonSchemaFile<T>(
+ return OCPPServiceUtils.parseJsonSchemaFile<T>(
relativePath,
OCPPVersion.VERSION_201,
moduleName,
MeterValueMeasurand,
ReservationStatus,
TriggerMessageStatus,
- UnlockStatus
+ UnlockStatus,
} from '../../types/index.js'
import { Constants } from '../../utils/index.js'
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class OCPPConstants {
- static readonly OCPP_WEBSOCKET_TIMEOUT = 60000 // Ms
+ static readonly OCPP_AVAILABILITY_RESPONSE_ACCEPTED = Object.freeze({
+ status: AvailabilityStatus.ACCEPTED,
+ })
- static readonly OCPP_MEASURANDS_SUPPORTED = Object.freeze([
- MeterValueMeasurand.STATE_OF_CHARGE,
- MeterValueMeasurand.VOLTAGE,
- MeterValueMeasurand.POWER_ACTIVE_IMPORT,
- MeterValueMeasurand.CURRENT_IMPORT,
- MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- ])
+ static readonly OCPP_AVAILABILITY_RESPONSE_REJECTED = Object.freeze({
+ status: AvailabilityStatus.REJECTED,
+ })
- static readonly OCPP_REQUEST_EMPTY = Constants.EMPTY_FROZEN_OBJECT
- static readonly OCPP_RESPONSE_EMPTY = Constants.EMPTY_FROZEN_OBJECT
- static readonly OCPP_RESPONSE_ACCEPTED = Object.freeze({ status: GenericStatus.Accepted })
- static readonly OCPP_RESPONSE_REJECTED = Object.freeze({ status: GenericStatus.Rejected })
+ static readonly OCPP_AVAILABILITY_RESPONSE_SCHEDULED = Object.freeze({
+ status: AvailabilityStatus.SCHEDULED,
+ })
- static readonly OCPP_CONFIGURATION_RESPONSE_ACCEPTED = Object.freeze({
- status: ConfigurationStatus.ACCEPTED
+ // Reservation for id has been cancelled
+ static readonly OCPP_CANCEL_RESERVATION_RESPONSE_ACCEPTED = Object.freeze({
+ status: GenericStatus.Accepted,
})
- static readonly OCPP_CONFIGURATION_RESPONSE_REJECTED = Object.freeze({
- status: ConfigurationStatus.REJECTED
+ // Reservation could not be cancelled, because there is no reservation active for id
+ static readonly OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED = Object.freeze({
+ status: GenericStatus.Rejected,
})
- static readonly OCPP_CONFIGURATION_RESPONSE_REBOOT_REQUIRED = Object.freeze({
- status: ConfigurationStatus.REBOOT_REQUIRED
+ static readonly OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED = Object.freeze({
+ status: ClearChargingProfileStatus.ACCEPTED,
})
- static readonly OCPP_CONFIGURATION_RESPONSE_NOT_SUPPORTED = Object.freeze({
- status: ConfigurationStatus.NOT_SUPPORTED
+ static readonly OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN = Object.freeze({
+ status: ClearChargingProfileStatus.UNKNOWN,
})
- static readonly OCPP_SET_CHARGING_PROFILE_RESPONSE_ACCEPTED = Object.freeze({
- status: ChargingProfileStatus.ACCEPTED
+ static readonly OCPP_CONFIGURATION_RESPONSE_ACCEPTED = Object.freeze({
+ status: ConfigurationStatus.ACCEPTED,
})
- static readonly OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED = Object.freeze({
- status: ChargingProfileStatus.REJECTED
+ static readonly OCPP_CONFIGURATION_RESPONSE_NOT_SUPPORTED = Object.freeze({
+ status: ConfigurationStatus.NOT_SUPPORTED,
})
- static readonly OCPP_SET_CHARGING_PROFILE_RESPONSE_NOT_SUPPORTED = Object.freeze({
- status: ChargingProfileStatus.NOT_SUPPORTED
+ static readonly OCPP_CONFIGURATION_RESPONSE_REBOOT_REQUIRED = Object.freeze({
+ status: ConfigurationStatus.REBOOT_REQUIRED,
})
- static readonly OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_ACCEPTED = Object.freeze({
- status: ClearChargingProfileStatus.ACCEPTED
+ static readonly OCPP_CONFIGURATION_RESPONSE_REJECTED = Object.freeze({
+ status: ConfigurationStatus.REJECTED,
})
- static readonly OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN = Object.freeze({
- status: ClearChargingProfileStatus.UNKNOWN
+ static readonly OCPP_DATA_TRANSFER_RESPONSE_ACCEPTED = Object.freeze({
+ status: DataTransferStatus.ACCEPTED,
})
- static readonly OCPP_RESPONSE_UNLOCKED = Object.freeze({ status: UnlockStatus.UNLOCKED })
- static readonly OCPP_RESPONSE_UNLOCK_FAILED = Object.freeze({
- status: UnlockStatus.UNLOCK_FAILED
+ static readonly OCPP_DATA_TRANSFER_RESPONSE_REJECTED = Object.freeze({
+ status: DataTransferStatus.REJECTED,
})
- static readonly OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED = Object.freeze({
- status: UnlockStatus.NOT_SUPPORTED
+ static readonly OCPP_DATA_TRANSFER_RESPONSE_UNKNOWN_VENDOR_ID = Object.freeze({
+ status: DataTransferStatus.UNKNOWN_VENDOR_ID,
})
- static readonly OCPP_AVAILABILITY_RESPONSE_ACCEPTED = Object.freeze({
- status: AvailabilityStatus.ACCEPTED
+ static readonly OCPP_MEASURANDS_SUPPORTED = Object.freeze([
+ MeterValueMeasurand.STATE_OF_CHARGE,
+ MeterValueMeasurand.VOLTAGE,
+ MeterValueMeasurand.POWER_ACTIVE_IMPORT,
+ MeterValueMeasurand.CURRENT_IMPORT,
+ MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER,
+ ])
+
+ static readonly OCPP_REQUEST_EMPTY = Constants.EMPTY_FROZEN_OBJECT
+
+ // Reservation has been made
+ static readonly OCPP_RESERVATION_RESPONSE_ACCEPTED = Object.freeze({
+ status: ReservationStatus.ACCEPTED,
})
- static readonly OCPP_AVAILABILITY_RESPONSE_REJECTED = Object.freeze({
- status: AvailabilityStatus.REJECTED
+ // Reservation has not been made, because of connector in FAULTED state
+ static readonly OCPP_RESERVATION_RESPONSE_FAULTED = Object.freeze({
+ status: ReservationStatus.FAULTED,
})
- static readonly OCPP_AVAILABILITY_RESPONSE_SCHEDULED = Object.freeze({
- status: AvailabilityStatus.SCHEDULED
+ // Reservation has not been made, because all connectors are OCCUPIED
+ static readonly OCPP_RESERVATION_RESPONSE_OCCUPIED = Object.freeze({
+ status: ReservationStatus.OCCUPIED,
})
- static readonly OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED = Object.freeze({
- status: TriggerMessageStatus.ACCEPTED
+ // Reservation has not been made, because charging station is not configured to accept reservations
+ static readonly OCPP_RESERVATION_RESPONSE_REJECTED = Object.freeze({
+ status: ReservationStatus.REJECTED,
})
- static readonly OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED = Object.freeze({
- status: TriggerMessageStatus.REJECTED
+ // Reservation has not been made, because connector is in UNAVAILABLE state
+ static readonly OCPP_RESERVATION_RESPONSE_UNAVAILABLE = Object.freeze({
+ status: ReservationStatus.UNAVAILABLE,
})
- static readonly OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED = Object.freeze({
- status: TriggerMessageStatus.NOT_IMPLEMENTED
+ static readonly OCPP_RESPONSE_ACCEPTED = Object.freeze({
+ status: GenericStatus.Accepted,
})
- static readonly OCPP_DATA_TRANSFER_RESPONSE_ACCEPTED = Object.freeze({
- status: DataTransferStatus.ACCEPTED
+ static readonly OCPP_RESPONSE_EMPTY = Constants.EMPTY_FROZEN_OBJECT
+
+ static readonly OCPP_RESPONSE_REJECTED = Object.freeze({
+ status: GenericStatus.Rejected,
})
- static readonly OCPP_DATA_TRANSFER_RESPONSE_REJECTED = Object.freeze({
- status: DataTransferStatus.REJECTED
+ static readonly OCPP_RESPONSE_UNLOCK_FAILED = Object.freeze({
+ status: UnlockStatus.UNLOCK_FAILED,
})
- static readonly OCPP_DATA_TRANSFER_RESPONSE_UNKNOWN_VENDOR_ID = Object.freeze({
- status: DataTransferStatus.UNKNOWN_VENDOR_ID
+ static readonly OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED = Object.freeze({
+ status: UnlockStatus.NOT_SUPPORTED,
})
- static readonly OCPP_RESERVATION_RESPONSE_ACCEPTED = Object.freeze({
- status: ReservationStatus.ACCEPTED
- }) // Reservation has been made
+ static readonly OCPP_RESPONSE_UNLOCKED = Object.freeze({
+ status: UnlockStatus.UNLOCKED,
+ })
- static readonly OCPP_RESERVATION_RESPONSE_FAULTED = Object.freeze({
- status: ReservationStatus.FAULTED
- }) // Reservation has not been made, because of connector in FAULTED state
+ static readonly OCPP_SET_CHARGING_PROFILE_RESPONSE_ACCEPTED = Object.freeze({
+ status: ChargingProfileStatus.ACCEPTED,
+ })
- static readonly OCPP_RESERVATION_RESPONSE_OCCUPIED = Object.freeze({
- status: ReservationStatus.OCCUPIED
- }) // Reservation has not been made, because all connectors are OCCUPIED
+ static readonly OCPP_SET_CHARGING_PROFILE_RESPONSE_NOT_SUPPORTED = Object.freeze({
+ status: ChargingProfileStatus.NOT_SUPPORTED,
+ })
- static readonly OCPP_RESERVATION_RESPONSE_REJECTED = Object.freeze({
- status: ReservationStatus.REJECTED
- }) // Reservation has not been made, because charging station is not configured to accept reservations
+ static readonly OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED = Object.freeze({
+ status: ChargingProfileStatus.REJECTED,
+ })
- static readonly OCPP_RESERVATION_RESPONSE_UNAVAILABLE = Object.freeze({
- status: ReservationStatus.UNAVAILABLE
- }) // Reservation has not been made, because connector is in UNAVAILABLE state
+ static readonly OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED = Object.freeze({
+ status: TriggerMessageStatus.ACCEPTED,
+ })
- static readonly OCPP_CANCEL_RESERVATION_RESPONSE_ACCEPTED = Object.freeze({
- status: GenericStatus.Accepted
- }) // Reservation for id has been cancelled
+ static readonly OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED = Object.freeze({
+ status: TriggerMessageStatus.NOT_IMPLEMENTED,
+ })
- static readonly OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED = Object.freeze({
- status: GenericStatus.Rejected
- }) // Reservation could not be cancelled, because there is no reservation active for id
+ static readonly OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED = Object.freeze({
+ status: TriggerMessageStatus.REJECTED,
+ })
+
+ static readonly OCPP_WEBSOCKET_TIMEOUT = 60000 // Ms
protected constructor () {
// This is intentional
-import { EventEmitter } from 'node:events'
-
import _Ajv, { type ValidateFunction } from 'ajv'
import _ajvFormats from 'ajv-formats'
+import { EventEmitter } from 'node:events'
-import { type ChargingStation, getIdTagsFile } from '../../charging-station/index.js'
-import { OCPPError } from '../../exception/index.js'
import type {
ClearCacheResponse,
- HandleErrorParams,
IncomingRequestCommand,
JsonType,
- OCPPVersion
+ OCPPVersion,
} from '../../types/index.js'
-import { logger, setDefaultErrorParams } from '../../utils/index.js'
+
+import { type ChargingStation, getIdTagsFile } from '../../charging-station/index.js'
+import { OCPPError } from '../../exception/index.js'
+import { logger } from '../../utils/index.js'
import { OCPPConstants } from './OCPPConstants.js'
-import { OCPPServiceUtils } from './OCPPServiceUtils.js'
+import { ajvErrorsToErrorType } from './OCPPServiceUtils.js'
+
type Ajv = _Ajv.default
// eslint-disable-next-line @typescript-eslint/no-redeclare
const Ajv = _Ajv.default
const moduleName = 'OCPPIncomingRequestService'
export abstract class OCPPIncomingRequestService extends EventEmitter {
- private static instance: OCPPIncomingRequestService | null = null
- private readonly version: OCPPVersion
+ private static instance: null | OCPPIncomingRequestService = null
protected readonly ajv: Ajv
protected abstract payloadValidateFunctions: Map<
- IncomingRequestCommand,
- ValidateFunction<JsonType>
+ IncomingRequestCommand,
+ ValidateFunction<JsonType>
>
+ private readonly version: OCPPVersion
+
protected constructor (version: OCPPVersion) {
super()
this.version = version
this.ajv = new Ajv({
keywords: ['javaType'],
- multipleOfPrecision: 2
+ multipleOfPrecision: 2,
})
ajvFormats(this.ajv)
this.incomingRequestHandler = this.incomingRequestHandler.bind(this)
}
public static getInstance<T extends OCPPIncomingRequestService>(this: new () => T): T {
- if (OCPPIncomingRequestService.instance === null) {
- OCPPIncomingRequestService.instance = new this()
- }
+ OCPPIncomingRequestService.instance ??= new this()
return OCPPIncomingRequestService.instance as T
}
- protected handleIncomingRequestError<T extends JsonType>(
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-unnecessary-type-parameters
+ public abstract incomingRequestHandler<ReqType extends JsonType, ResType extends JsonType>(
chargingStation: ChargingStation,
+ messageId: string,
commandName: IncomingRequestCommand,
- error: Error,
- params: HandleErrorParams<T> = { throwError: true, consoleOut: false }
- ): T | undefined {
- setDefaultErrorParams(params)
- logger.error(
- `${chargingStation.logPrefix()} ${moduleName}.handleIncomingRequestError: Incoming request command '${commandName}' error:`,
- error
- )
- if (params.throwError === false && params.errorResponse != null) {
- return params.errorResponse
- }
- if (params.throwError === true && params.errorResponse == null) {
- throw error
- }
- if (params.throwError === true && params.errorResponse != null) {
- return params.errorResponse
+ commandPayload: ReqType
+ ): Promise<void>
+
+ protected handleRequestClearCache (chargingStation: ChargingStation): ClearCacheResponse {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ if (chargingStation.idTagsCache.deleteIdTags(getIdTagsFile(chargingStation.stationInfo!)!)) {
+ return OCPPConstants.OCPP_RESPONSE_ACCEPTED
}
+ return OCPPConstants.OCPP_RESPONSE_REJECTED
}
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
protected validateIncomingRequestPayload<T extends JsonType>(
chargingStation: ChargingStation,
commandName: IncomingRequestCommand,
validate?.errors
)
throw new OCPPError(
- OCPPServiceUtils.ajvErrorsToErrorType(validate?.errors),
+ ajvErrorsToErrorType(validate?.errors),
'Incoming request PDU is invalid',
commandName,
JSON.stringify(validate?.errors, undefined, 2)
)
}
-
- protected handleRequestClearCache (chargingStation: ChargingStation): ClearCacheResponse {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- if (chargingStation.idTagsCache.deleteIdTags(getIdTagsFile(chargingStation.stationInfo!)!)) {
- return OCPPConstants.OCPP_RESPONSE_ACCEPTED
- }
- return OCPPConstants.OCPP_RESPONSE_REJECTED
- }
-
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- public abstract incomingRequestHandler<ReqType extends JsonType, ResType extends JsonType>(
- chargingStation: ChargingStation,
- messageId: string,
- commandName: IncomingRequestCommand,
- commandPayload: ReqType
- ): Promise<void>
}
import _ajvFormats from 'ajv-formats'
import type { ChargingStation } from '../../charging-station/index.js'
+import type { OCPPResponseService } from './OCPPResponseService.js'
+
import { OCPPError } from '../../exception/index.js'
import { PerformanceStatistics } from '../../performance/index.js'
import {
type RequestParams,
type Response,
type ResponseCallback,
- type ResponseType
+ type ResponseType,
} from '../../types/index.js'
import {
clone,
formatDurationMilliSeconds,
handleSendMessageError,
- logger
+ logger,
} from '../../utils/index.js'
import { OCPPConstants } from './OCPPConstants.js'
-import type { OCPPResponseService } from './OCPPResponseService.js'
-import { OCPPServiceUtils } from './OCPPServiceUtils.js'
+import {
+ ajvErrorsToErrorType,
+ convertDateToISOString,
+ getMessageTypeString,
+} from './OCPPServiceUtils.js'
+
type Ajv = _Ajv.default
// eslint-disable-next-line @typescript-eslint/no-redeclare
const Ajv = _Ajv.default
const defaultRequestParams: RequestParams = {
skipBufferingOnError: false,
+ throwError: false,
triggerMessage: false,
- throwError: false
}
export abstract class OCPPRequestService {
- private static instance: OCPPRequestService | null = null
- private readonly version: OCPPVersion
- private readonly ocppResponseService: OCPPResponseService
+ private static instance: null | OCPPRequestService = null
protected readonly ajv: Ajv
protected abstract payloadValidateFunctions: Map<RequestCommand, ValidateFunction<JsonType>>
+ private readonly ocppResponseService: OCPPResponseService
+ private readonly version: OCPPVersion
protected constructor (version: OCPPVersion, ocppResponseService: OCPPResponseService) {
this.version = version
this.ajv = new Ajv({
keywords: ['javaType'],
- multipleOfPrecision: 2
+ multipleOfPrecision: 2,
})
ajvFormats(this.ajv)
this.ocppResponseService = ocppResponseService
this: new (ocppResponseService: OCPPResponseService) => T,
ocppResponseService: OCPPResponseService
): T {
- if (OCPPRequestService.instance === null) {
- OCPPRequestService.instance = new this(ocppResponseService)
- }
+ OCPPRequestService.instance ??= new this(ocppResponseService)
return OCPPRequestService.instance as T
}
- public async sendResponse (
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
+ public abstract requestHandler<ReqType extends JsonType, ResType extends JsonType>(
+ chargingStation: ChargingStation,
+ commandName: RequestCommand,
+ commandParams?: ReqType,
+ params?: RequestParams
+ ): Promise<ResType>
+
+ public async sendError (
chargingStation: ChargingStation,
messageId: string,
- messagePayload: JsonType,
- commandName: IncomingRequestCommand
+ ocppError: OCPPError,
+ commandName: IncomingRequestCommand | RequestCommand
): Promise<ResponseType> {
try {
- // Send response message
+ // Send error message
return await this.internalSendMessage(
chargingStation,
messageId,
- messagePayload,
- MessageType.CALL_RESULT_MESSAGE,
+ ocppError,
+ MessageType.CALL_ERROR_MESSAGE,
commandName
)
} catch (error) {
- handleSendMessageError(chargingStation, commandName, error as Error, {
- throwError: true
- })
+ handleSendMessageError(
+ chargingStation,
+ commandName,
+ MessageType.CALL_ERROR_MESSAGE,
+ error as Error
+ )
return null
}
}
- public async sendError (
+ public async sendResponse (
chargingStation: ChargingStation,
messageId: string,
- ocppError: OCPPError,
- commandName: RequestCommand | IncomingRequestCommand
+ messagePayload: JsonType,
+ commandName: IncomingRequestCommand
): Promise<ResponseType> {
try {
- // Send error message
+ // Send response message
return await this.internalSendMessage(
chargingStation,
messageId,
- ocppError,
- MessageType.CALL_ERROR_MESSAGE,
+ messagePayload,
+ MessageType.CALL_RESULT_MESSAGE,
commandName
)
} catch (error) {
- handleSendMessageError(chargingStation, commandName, error as Error)
+ handleSendMessageError(
+ chargingStation,
+ commandName,
+ MessageType.CALL_RESULT_MESSAGE,
+ error as Error,
+ {
+ throwError: true,
+ }
+ )
return null
}
}
): Promise<ResponseType> {
params = {
...defaultRequestParams,
- ...params
+ ...params,
}
try {
return await this.internalSendMessage(
params
)
} catch (error) {
- handleSendMessageError(chargingStation, commandName, error as Error, {
- throwError: params.throwError
- })
- return null
- }
- }
-
- private validateRequestPayload<T extends JsonType>(
- chargingStation: ChargingStation,
- commandName: RequestCommand | IncomingRequestCommand,
- payload: T
- ): boolean {
- if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
- return true
- }
- if (!this.payloadValidateFunctions.has(commandName as RequestCommand)) {
- logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validateRequestPayload: No JSON schema found for command '${commandName}' PDU validation`
+ handleSendMessageError(
+ chargingStation,
+ commandName,
+ MessageType.CALL_MESSAGE,
+ error as Error,
+ {
+ throwError: params.throwError,
+ }
)
- return true
- }
- const validate = this.payloadValidateFunctions.get(commandName as RequestCommand)
- payload = clone<T>(payload)
- OCPPServiceUtils.convertDateToISOString<T>(payload)
- if (validate?.(payload) === true) {
- return true
+ return null
}
- logger.error(
- `${chargingStation.logPrefix()} ${moduleName}.validateRequestPayload: Command '${commandName}' request PDU is invalid: %j`,
- validate?.errors
- )
- // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
- throw new OCPPError(
- OCPPServiceUtils.ajvErrorsToErrorType(validate?.errors),
- 'Request PDU is invalid',
- commandName,
- JSON.stringify(validate?.errors, undefined, 2)
- )
}
- private validateIncomingRequestResponsePayload<T extends JsonType>(
+ private buildMessageToSend (
chargingStation: ChargingStation,
- commandName: RequestCommand | IncomingRequestCommand,
- payload: T
- ): boolean {
- if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
- return true
- }
- if (
- !this.ocppResponseService.incomingRequestResponsePayloadValidateFunctions.has(
- commandName as IncomingRequestCommand
- )
- ) {
- logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestResponsePayload: No JSON schema validation function found for command '${commandName}' PDU validation`
- )
- return true
- }
- const validate = this.ocppResponseService.incomingRequestResponsePayloadValidateFunctions.get(
- commandName as IncomingRequestCommand
- )
- payload = clone<T>(payload)
- OCPPServiceUtils.convertDateToISOString<T>(payload)
- if (validate?.(payload) === true) {
- return true
+ messageId: string,
+ messagePayload: JsonType | OCPPError,
+ messageType: MessageType,
+ commandName: IncomingRequestCommand | RequestCommand
+ ): string {
+ let messageToSend: string
+ // Type of message
+ switch (messageType) {
+ // Error Message
+ case MessageType.CALL_ERROR_MESSAGE:
+ // Build Error Message
+ messageToSend = JSON.stringify([
+ messageType,
+ messageId,
+ (messagePayload as OCPPError).code,
+ (messagePayload as OCPPError).message,
+ (messagePayload as OCPPError).details ?? {
+ command: (messagePayload as OCPPError).command,
+ },
+ ] satisfies ErrorResponse)
+ break
+ // Request
+ case MessageType.CALL_MESSAGE:
+ // Build request
+ this.validateRequestPayload(chargingStation, commandName, messagePayload as JsonType)
+ messageToSend = JSON.stringify([
+ messageType,
+ messageId,
+ commandName as RequestCommand,
+ messagePayload as JsonType,
+ ] satisfies OutgoingRequest)
+ break
+ // Response
+ case MessageType.CALL_RESULT_MESSAGE:
+ // Build response
+ this.validateIncomingRequestResponsePayload(
+ chargingStation,
+ commandName,
+ messagePayload as JsonType
+ )
+ messageToSend = JSON.stringify([
+ messageType,
+ messageId,
+ messagePayload as JsonType,
+ ] satisfies Response)
+ break
}
- logger.error(
- `${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestResponsePayload: Command '${commandName}' response PDU is invalid: %j`,
- validate?.errors
- )
- // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
- throw new OCPPError(
- OCPPServiceUtils.ajvErrorsToErrorType(validate?.errors),
- 'Response PDU is invalid',
- commandName,
- JSON.stringify(validate?.errors, undefined, 2)
- )
+ return messageToSend
}
private async internalSendMessage (
messageId: string,
messagePayload: JsonType | OCPPError,
messageType: MessageType,
- commandName: RequestCommand | IncomingRequestCommand,
+ commandName: IncomingRequestCommand | RequestCommand,
params?: RequestParams
): Promise<ResponseType> {
params = {
...defaultRequestParams,
- ...params
+ ...params,
}
if (
- (chargingStation.inUnknownState() && commandName === RequestCommand.BOOT_NOTIFICATION) ||
+ ((chargingStation.inUnknownState() || chargingStation.inPendingState()) &&
+ commandName === RequestCommand.BOOT_NOTIFICATION) ||
(chargingStation.stationInfo?.ocppStrictCompliance === false &&
- chargingStation.inUnknownState()) ||
+ (chargingStation.inUnknownState() || chargingStation.inPendingState())) ||
chargingStation.inAcceptedState() ||
(chargingStation.inPendingState() &&
(params.triggerMessage === true || messageType === MessageType.CALL_RESULT_MESSAGE))
return await new Promise<ResponseType>((resolve, reject: (reason?: unknown) => void) => {
/**
* Function that will receive the request's response
- *
* @param payload -
* @param requestPayload -
*/
)
.then(() => {
resolve(payload)
+ return undefined
})
- .catch(reject)
.finally(() => {
chargingStation.requests.delete(messageId)
chargingStation.emit(ChargingStationEvents.updated)
})
+ .catch(reject)
}
/**
* Function that will receive the request's error response
- *
* @param ocppError -
* @param requestStatistic -
*/
)
}
logger.error(
- `${chargingStation.logPrefix()} Error occurred at ${OCPPServiceUtils.getMessageTypeString(
+ `${chargingStation.logPrefix()} Error occurred at ${getMessageTypeString(
messageType
)} command ${commandName} with PDU %j:`,
messagePayload,
clearTimeout(sendTimeout)
if (error == null) {
logger.debug(
- `${chargingStation.logPrefix()} >> Command '${commandName}' sent ${OCPPServiceUtils.getMessageTypeString(
+ `${chargingStation.logPrefix()} >> Command '${commandName}' sent ${getMessageTypeString(
messageType
)} payload: ${messageToSend}`
)
params.skipBufferingOnError === false ? '' : 'non '
}buffered message id '${messageId}' with content '${messageToSend}'`,
commandName,
- { name: error.name, message: error.message, stack: error.stack }
+ {
+ message: error.message,
+ name: error.name,
+ stack: error.stack,
+ }
)
)
}
}
throw new OCPPError(
ErrorType.SECURITY_ERROR,
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`Cannot send command ${commandName} PDU when the charging station is in ${chargingStation.bootNotificationResponse?.status} state on the central server`,
commandName
)
}
- private buildMessageToSend (
- chargingStation: ChargingStation,
- messageId: string,
- messagePayload: JsonType | OCPPError,
- messageType: MessageType,
- commandName: RequestCommand | IncomingRequestCommand
- ): string {
- let messageToSend: string
- // Type of message
- switch (messageType) {
- // Request
- case MessageType.CALL_MESSAGE:
- // Build request
- this.validateRequestPayload(chargingStation, commandName, messagePayload as JsonType)
- messageToSend = JSON.stringify([
- messageType,
- messageId,
- commandName as RequestCommand,
- messagePayload as JsonType
- ] satisfies OutgoingRequest)
- break
- // Response
- case MessageType.CALL_RESULT_MESSAGE:
- // Build response
- this.validateIncomingRequestResponsePayload(
- chargingStation,
- commandName,
- messagePayload as JsonType
- )
- messageToSend = JSON.stringify([
- messageType,
- messageId,
- messagePayload as JsonType
- ] satisfies Response)
- break
- // Error Message
- case MessageType.CALL_ERROR_MESSAGE:
- // Build Error Message
- messageToSend = JSON.stringify([
- messageType,
- messageId,
- (messagePayload as OCPPError).code,
- (messagePayload as OCPPError).message,
- (messagePayload as OCPPError).details ?? {
- command: (messagePayload as OCPPError).command
- }
- ] satisfies ErrorResponse)
- break
- }
- return messageToSend
- }
-
private setCachedRequest (
chargingStation: ChargingStation,
messageId: string,
messagePayload: JsonType,
- commandName: RequestCommand | IncomingRequestCommand,
+ commandName: IncomingRequestCommand | RequestCommand,
responseCallback: ResponseCallback,
errorCallback: ErrorCallback
): void {
responseCallback,
errorCallback,
commandName,
- messagePayload
+ messagePayload,
])
}
- public abstract requestHandler<ReqType extends JsonType, ResType extends JsonType>(
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
+ private validateIncomingRequestResponsePayload<T extends JsonType>(
chargingStation: ChargingStation,
- commandName: RequestCommand,
- commandParams?: ReqType,
- params?: RequestParams
- ): Promise<ResType>
+ commandName: IncomingRequestCommand | RequestCommand,
+ payload: T
+ ): boolean {
+ if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
+ return true
+ }
+ if (
+ !this.ocppResponseService.incomingRequestResponsePayloadValidateFunctions.has(
+ commandName as IncomingRequestCommand
+ )
+ ) {
+ logger.warn(
+ `${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestResponsePayload: No JSON schema validation function found for command '${commandName}' PDU validation`
+ )
+ return true
+ }
+ const validate = this.ocppResponseService.incomingRequestResponsePayloadValidateFunctions.get(
+ commandName as IncomingRequestCommand
+ )
+ payload = clone<T>(payload)
+ convertDateToISOString<T>(payload)
+ if (validate?.(payload) === true) {
+ return true
+ }
+ logger.error(
+ `${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestResponsePayload: Command '${commandName}' incoming request response PDU is invalid: %j`,
+ validate?.errors
+ )
+ // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
+ throw new OCPPError(
+ ajvErrorsToErrorType(validate?.errors),
+ 'Incoming request response PDU is invalid',
+ commandName,
+ JSON.stringify(validate?.errors, undefined, 2)
+ )
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
+ private validateRequestPayload<T extends JsonType>(
+ chargingStation: ChargingStation,
+ commandName: IncomingRequestCommand | RequestCommand,
+ payload: T
+ ): boolean {
+ if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
+ return true
+ }
+ if (!this.payloadValidateFunctions.has(commandName as RequestCommand)) {
+ logger.warn(
+ `${chargingStation.logPrefix()} ${moduleName}.validateRequestPayload: No JSON schema found for command '${commandName}' PDU validation`
+ )
+ return true
+ }
+ const validate = this.payloadValidateFunctions.get(commandName as RequestCommand)
+ payload = clone<T>(payload)
+ convertDateToISOString<T>(payload)
+ if (validate?.(payload) === true) {
+ return true
+ }
+ logger.error(
+ `${chargingStation.logPrefix()} ${moduleName}.validateRequestPayload: Command '${commandName}' request PDU is invalid: %j`,
+ validate?.errors
+ )
+ // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
+ throw new OCPPError(
+ ajvErrorsToErrorType(validate?.errors),
+ 'Request PDU is invalid',
+ commandName,
+ JSON.stringify(validate?.errors, undefined, 2)
+ )
+ }
}
import _ajvFormats from 'ajv-formats'
import type { ChargingStation } from '../../charging-station/index.js'
-import { OCPPError } from '../../exception/index.js'
import type {
IncomingRequestCommand,
JsonType,
OCPPVersion,
- RequestCommand
+ RequestCommand,
} from '../../types/index.js'
+
+import { OCPPError } from '../../exception/index.js'
import { Constants, logger } from '../../utils/index.js'
-import { OCPPServiceUtils } from './OCPPServiceUtils.js'
+import { ajvErrorsToErrorType } from './OCPPServiceUtils.js'
+
type Ajv = _Ajv.default
// eslint-disable-next-line @typescript-eslint/no-redeclare
const Ajv = _Ajv.default
const moduleName = 'OCPPResponseService'
export abstract class OCPPResponseService {
- private static instance: OCPPResponseService | null = null
- private readonly version: OCPPVersion
+ private static instance: null | OCPPResponseService = null
+ public abstract incomingRequestResponsePayloadValidateFunctions: Map<
+ IncomingRequestCommand,
+ ValidateFunction<JsonType>
+ >
+
protected readonly ajv: Ajv
protected readonly ajvIncomingRequest: Ajv
+ protected emptyResponseHandler = Constants.EMPTY_FUNCTION
protected abstract payloadValidateFunctions: Map<RequestCommand, ValidateFunction<JsonType>>
- public abstract incomingRequestResponsePayloadValidateFunctions: Map<
- IncomingRequestCommand,
- ValidateFunction<JsonType>
- >
+ private readonly version: OCPPVersion
protected constructor (version: OCPPVersion) {
this.version = version
this.ajv = new Ajv({
keywords: ['javaType'],
- multipleOfPrecision: 2
+ multipleOfPrecision: 2,
})
ajvFormats(this.ajv)
this.ajvIncomingRequest = new Ajv({
keywords: ['javaType'],
- multipleOfPrecision: 2
+ multipleOfPrecision: 2,
})
ajvFormats(this.ajvIncomingRequest)
this.responseHandler = this.responseHandler.bind(this)
}
public static getInstance<T extends OCPPResponseService>(this: new () => T): T {
- if (OCPPResponseService.instance === null) {
- OCPPResponseService.instance = new this()
- }
+ OCPPResponseService.instance ??= new this()
return OCPPResponseService.instance as T
}
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
+ public abstract responseHandler<ReqType extends JsonType, ResType extends JsonType>(
+ chargingStation: ChargingStation,
+ commandName: RequestCommand,
+ payload: ResType,
+ requestPayload: ReqType
+ ): Promise<void>
+
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
protected validateResponsePayload<T extends JsonType>(
chargingStation: ChargingStation,
commandName: RequestCommand,
validate?.errors
)
throw new OCPPError(
- OCPPServiceUtils.ajvErrorsToErrorType(validate?.errors),
+ ajvErrorsToErrorType(validate?.errors),
'Response PDU is invalid',
commandName,
JSON.stringify(validate?.errors, undefined, 2)
)
}
-
- protected emptyResponseHandler = Constants.EMPTY_FUNCTION
-
- public abstract responseHandler<ReqType extends JsonType, ResType extends JsonType>(
- chargingStation: ChargingStation,
- commandName: RequestCommand,
- payload: ResType,
- requestPayload: ReqType
- ): Promise<void>
}
+import type { ErrorObject, JSONSchemaType } from 'ajv'
+
+import { isDate } from 'date-fns'
import { randomInt } from 'node:crypto'
import { readFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
-import type { DefinedError, ErrorObject, JSONSchemaType } from 'ajv'
-import { isDate } from 'date-fns'
-
import {
type ChargingStation,
getConfigurationKey,
- getIdTagsFile
+ getIdTagsFile,
} from '../../charging-station/index.js'
import { BaseError, OCPPError } from '../../exception/index.js'
import {
type SampledValueTemplate,
StandardParametersKey,
type StatusNotificationRequest,
- type StatusNotificationResponse
+ type StatusNotificationResponse,
} from '../../types/index.js'
import {
ACElectricUtils,
logPrefix,
max,
min,
- roundTo
+ roundTo,
} from '../../utils/index.js'
import { OCPP16Constants } from './1.6/OCPP16Constants.js'
import { OCPP20Constants } from './2.0/OCPP20Constants.js'
export const getMessageTypeString = (messageType: MessageType | undefined): string => {
switch (messageType) {
+ case MessageType.CALL_ERROR_MESSAGE:
+ return 'error'
case MessageType.CALL_MESSAGE:
return 'request'
case MessageType.CALL_RESULT_MESSAGE:
return 'response'
- case MessageType.CALL_ERROR_MESSAGE:
- return 'error'
default:
return 'unknown'
}
case OCPPVersion.VERSION_16:
return {
connectorId,
+ errorCode: ChargePointErrorCode.NO_ERROR,
status: status as OCPP16ChargePointStatus,
- errorCode: ChargePointErrorCode.NO_ERROR
} satisfies OCPP16StatusNotificationRequest
case OCPPVersion.VERSION_20:
case OCPPVersion.VERSION_201:
return {
- timestamp: new Date(),
- connectorStatus: status as OCPP20ConnectorStatusEnumType,
connectorId,
+ connectorStatus: status as OCPP20ConnectorStatusEnumType,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- evseId: evseId!
+ evseId: evseId!,
+ timestamp: new Date(),
} satisfies OCPP20StatusNotificationRequest
default:
throw new BaseError('Cannot build status notification payload: OCPP version not supported')
chargingStation,
RequestCommand.AUTHORIZE,
{
- idTag
+ idTag,
}
)
).idTagInfo.status === AuthorizationStatus.ACCEPTED
if (options.send) {
checkConnectorStatusTransition(chargingStation, connectorId, status)
await chargingStation.ocppRequestService.requestHandler<
- StatusNotificationRequest,
- StatusNotificationResponse
+ StatusNotificationRequest,
+ StatusNotificationResponse
>(
chargingStation,
RequestCommand.STATUS_NOTIFICATION,
chargingStation.getConnectorStatus(connectorId)!.status = status
chargingStation.emit(ChargingStationEvents.connectorStatusChanged, {
connectorId,
- ...chargingStation.getConnectorStatus(connectorId)
+ ...chargingStation.getConnectorStatus(connectorId),
})
}
break
default:
throw new BaseError(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`Cannot check connector status transition: OCPP version ${chargingStation.stationInfo?.ocppVersion} not supported`
)
}
logger.warn(
`${chargingStation.logPrefix()} OCPP ${
chargingStation.stationInfo.ocppVersion
- } connector id ${connectorId} status transition from '${
+ } connector id ${connectorId.toString()} status transition from '${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
chargingStation.getConnectorStatus(connectorId)?.status
}' to '${status}' is not allowed`
)
return transitionAllowed
}
+export const ajvErrorsToErrorType = (errors: ErrorObject[] | null | undefined): ErrorType => {
+ if (isNotEmptyArray(errors)) {
+ for (const error of errors) {
+ switch (error.keyword) {
+ case 'dependencies':
+ case 'required':
+ return ErrorType.OCCURRENCE_CONSTRAINT_VIOLATION
+ case 'format':
+ case 'pattern':
+ return ErrorType.PROPERTY_CONSTRAINT_VIOLATION
+ case 'type':
+ return ErrorType.TYPE_CONSTRAINT_VIOLATION
+ }
+ }
+ }
+ return ErrorType.FORMAT_VIOLATION
+}
+
+// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
+export const convertDateToISOString = <T extends JsonType>(object: T): void => {
+ // eslint-disable-next-line @typescript-eslint/no-for-in-array
+ for (const key in object) {
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion, @typescript-eslint/no-non-null-assertion
+ if (isDate(object![key])) {
+ ;(object[key] as unknown as string) = (object[key] as Date).toISOString()
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion, @typescript-eslint/no-non-null-assertion
+ } else if (typeof object![key] === 'object' && object[key] !== null) {
+ convertDateToISOString<T>(object[key] as T)
+ }
+ }
+}
+
export const buildMeterValue = (
chargingStation: ChargingStation,
connectorId: number,
): MeterValue => {
const connector = chargingStation.getConnectorStatus(connectorId)
let meterValue: MeterValue
+ let connectorMaximumAvailablePower: number | undefined
let socSampledValueTemplate: SampledValueTemplate | undefined
let voltageSampledValueTemplate: SampledValueTemplate | undefined
let powerSampledValueTemplate: SampledValueTemplate | undefined
switch (chargingStation.stationInfo?.ocppVersion) {
case OCPPVersion.VERSION_16:
meterValue = {
+ sampledValue: [],
timestamp: new Date(),
- sampledValue: []
}
// SoC measurand
socSampledValueTemplate = getSampledValueTemplate(
const socMinimumValue = socSampledValueTemplate.minimumValue ?? 0
const socSampledValueTemplateValue = isNotEmptyString(socSampledValueTemplate.value)
? getRandomFloatFluctuatedRounded(
- parseInt(socSampledValueTemplate.value),
+ Number.parseInt(socSampledValueTemplate.value),
socSampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT
)
: randomInt(socMinimumValue, socMaximumValue)
`${chargingStation.logPrefix()} MeterValues measurand ${
meterValue.sampledValue[sampledValuesIndex].measurand ??
MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- }: connector id ${connectorId}, transaction id ${connector?.transactionId}, value: ${socMinimumValue}/${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ }: connector id ${connectorId.toString()}, transaction id ${connector?.transactionId?.toString()}, value: ${socMinimumValue.toString()}/${
meterValue.sampledValue[sampledValuesIndex].value
- }/${socMaximumValue}`
+ }/${socMaximumValue.toString()}`
)
}
}
)
if (voltageSampledValueTemplate != null) {
const voltageSampledValueTemplateValue = isNotEmptyString(voltageSampledValueTemplate.value)
- ? parseInt(voltageSampledValueTemplate.value)
+ ? Number.parseInt(voltageSampledValueTemplate.value)
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
chargingStation.stationInfo.voltageOut!
const fluctuationPercent =
chargingStation.getNumberOfPhases() === 3 && phase <= chargingStation.getNumberOfPhases();
phase++
) {
- const phaseLineToNeutralValue = `L${phase}-N`
+ const phaseLineToNeutralValue = `L${phase.toString()}-N`
const voltagePhaseLineToNeutralSampledValueTemplate = getSampledValueTemplate(
chargingStation,
connectorId,
const voltagePhaseLineToNeutralSampledValueTemplateValue = isNotEmptyString(
voltagePhaseLineToNeutralSampledValueTemplate.value
)
- ? parseInt(voltagePhaseLineToNeutralSampledValueTemplate.value)
+ ? Number.parseInt(voltagePhaseLineToNeutralSampledValueTemplate.value)
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
chargingStation.stationInfo.voltageOut!
const fluctuationPhaseToNeutralPercent =
)
)
if (chargingStation.stationInfo.phaseLineToLineVoltageMeterValues === true) {
- const phaseLineToLineValue = `L${phase}-L${
+ const phaseLineToLineValue = `L${phase.toString()}-L${
(phase + 1) % chargingStation.getNumberOfPhases() !== 0
- ? (phase + 1) % chargingStation.getNumberOfPhases()
- : chargingStation.getNumberOfPhases()
+ ? ((phase + 1) % chargingStation.getNumberOfPhases()).toString()
+ : chargingStation.getNumberOfPhases().toString()
}`
const voltagePhaseLineToLineValueRounded = roundTo(
Math.sqrt(chargingStation.getNumberOfPhases()) *
const voltagePhaseLineToLineSampledValueTemplateValue = isNotEmptyString(
voltagePhaseLineToLineSampledValueTemplate.value
)
- ? parseInt(voltagePhaseLineToLineSampledValueTemplate.value)
+ ? Number.parseInt(voltagePhaseLineToLineSampledValueTemplate.value)
: voltagePhaseLineToLineValueRounded
const fluctuationPhaseLineToLinePercent =
voltagePhaseLineToLineSampledValueTemplate.fluctuationPercent ??
connectorId,
MeterValueMeasurand.POWER_ACTIVE_IMPORT,
MeterValuePhase.L3_N
- )
+ ),
}
}
if (powerSampledValueTemplate != null) {
checkMeasurandPowerDivider(chargingStation, powerSampledValueTemplate.measurand)
const errMsg = `MeterValues measurand ${
powerSampledValueTemplate.measurand ?? MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
}: Unknown ${chargingStation.stationInfo.currentOutType} currentOutType in template file ${
chargingStation.templateFile
}, cannot calculate ${
powerSampledValueTemplate.measurand ?? MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
} measurand value`
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const powerMeasurandValues: MeasurandValues = {} as MeasurandValues
const unitDivider = powerSampledValueTemplate.unit === MeterValueUnit.KILO_WATT ? 1000 : 1
- const connectorMaximumAvailablePower =
+ connectorMaximumAvailablePower =
chargingStation.getConnectorMaximumAvailablePower(connectorId)
const connectorMaximumPower = Math.round(connectorMaximumAvailablePower)
const connectorMaximumPowerPerPhase = Math.round(
connectorMaximumPower / unitDivider,
connectorMinimumPower / unitDivider,
{
+ fallbackValue: connectorMinimumPower / unitDivider,
limitationEnabled:
chargingStation.stationInfo.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumPower / unitDivider
}
) / chargingStation.getNumberOfPhases(),
powerSampledValueTemplate.fluctuationPercent ??
connectorMaximumPowerPerPhase / unitDivider,
connectorMinimumPowerPerPhase / unitDivider,
{
+ fallbackValue: connectorMinimumPowerPerPhase / unitDivider,
limitationEnabled:
chargingStation.stationInfo.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumPowerPerPhase / unitDivider
}
),
powerPerPhaseSampledValueTemplates.L1.fluctuationPercent ??
connectorMaximumPowerPerPhase / unitDivider,
connectorMinimumPowerPerPhase / unitDivider,
{
+ fallbackValue: connectorMinimumPowerPerPhase / unitDivider,
limitationEnabled:
chargingStation.stationInfo.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumPowerPerPhase / unitDivider
}
),
powerPerPhaseSampledValueTemplates.L2.fluctuationPercent ??
connectorMaximumPowerPerPhase / unitDivider,
connectorMinimumPowerPerPhase / unitDivider,
{
+ fallbackValue: connectorMinimumPowerPerPhase / unitDivider,
limitationEnabled:
chargingStation.stationInfo.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumPowerPerPhase / unitDivider
}
),
powerPerPhaseSampledValueTemplates.L3.fluctuationPercent ??
connectorMaximumPower / unitDivider,
connectorMinimumPower / unitDivider,
{
+ fallbackValue: connectorMinimumPower / unitDivider,
limitationEnabled:
chargingStation.stationInfo.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumPower / unitDivider
}
),
powerSampledValueTemplate.fluctuationPercent ??
connectorMaximumPower / unitDivider,
connectorMinimumPower / unitDivider,
{
+ fallbackValue: connectorMinimumPower / unitDivider,
limitationEnabled:
chargingStation.stationInfo.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumPower / unitDivider
}
),
powerSampledValueTemplate.fluctuationPercent ??
`${chargingStation.logPrefix()} MeterValues measurand ${
meterValue.sampledValue[sampledValuesIndex].measurand ??
MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- }: connector id ${connectorId}, transaction id ${connector?.transactionId}, value: ${connectorMinimumPowerRounded}/${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ }: connector id ${connectorId.toString()}, transaction id ${connector?.transactionId?.toString()}, value: ${connectorMinimumPowerRounded.toString()}/${
meterValue.sampledValue[sampledValuesIndex].value
- }/${connectorMaximumPowerRounded}`
+ }/${connectorMaximumPowerRounded.toString()}`
)
}
for (
chargingStation.getNumberOfPhases() === 3 && phase <= chargingStation.getNumberOfPhases();
phase++
) {
- const phaseValue = `L${phase}-N`
+ const phaseValue = `L${phase.toString()}-N`
meterValue.sampledValue.push(
buildSampledValue(
powerPerPhaseSampledValueTemplates[
- `L${phase}` as keyof MeasurandPerPhaseSampledValueTemplates
+ `L${phase.toString()}` as keyof MeasurandPerPhaseSampledValueTemplates
] ?? powerSampledValueTemplate,
- powerMeasurandValues[`L${phase}` as keyof MeasurandPerPhaseSampledValueTemplates],
+ powerMeasurandValues[
+ `L${phase.toString()}` as keyof MeasurandPerPhaseSampledValueTemplates
+ ],
undefined,
phaseValue as MeterValuePhase
)
meterValue.sampledValue[sampledValuesPerPhaseIndex].measurand ??
MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
}: phase ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
meterValue.sampledValue[sampledValuesPerPhaseIndex].phase
- }, connector id ${connectorId}, transaction id ${connector?.transactionId}, value: ${connectorMinimumPowerPerPhaseRounded}/${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ }, connector id ${connectorId.toString()}, transaction id ${connector?.transactionId?.toString()}, value: ${connectorMinimumPowerPerPhaseRounded.toString()}/${
meterValue.sampledValue[sampledValuesPerPhaseIndex].value
- }/${connectorMaximumPowerPerPhaseRounded}`
+ }/${connectorMaximumPowerPerPhaseRounded.toString()}`
)
}
}
connectorId,
MeterValueMeasurand.CURRENT_IMPORT,
MeterValuePhase.L3
- )
+ ),
}
}
if (currentSampledValueTemplate != null) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
checkMeasurandPowerDivider(chargingStation, currentSampledValueTemplate.measurand)
const errMsg = `MeterValues measurand ${
currentSampledValueTemplate.measurand ?? MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
}: Unknown ${chargingStation.stationInfo.currentOutType} currentOutType in template file ${
chargingStation.templateFile
}, cannot calculate ${
currentSampledValueTemplate.measurand ?? MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
} measurand value`
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const currentMeasurandValues: MeasurandValues = {} as MeasurandValues
- const connectorMaximumAvailablePower =
- chargingStation.getConnectorMaximumAvailablePower(connectorId)
+ connectorMaximumAvailablePower == null &&
+ (connectorMaximumAvailablePower =
+ chargingStation.getConnectorMaximumAvailablePower(connectorId))
const connectorMinimumAmperage = currentSampledValueTemplate.minimumValue ?? 0
let connectorMaximumAmperage: number
switch (chargingStation.stationInfo.currentOutType) {
connectorMaximumAmperage,
connectorMinimumAmperage,
{
+ fallbackValue: connectorMinimumAmperage,
limitationEnabled:
chargingStation.stationInfo.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumAmperage
}
),
currentSampledValueTemplate.fluctuationPercent ??
connectorMaximumAmperage,
connectorMinimumAmperage,
{
+ fallbackValue: connectorMinimumAmperage,
limitationEnabled:
chargingStation.stationInfo.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumAmperage
}
),
currentPerPhaseSampledValueTemplates.L1.fluctuationPercent ??
connectorMaximumAmperage,
connectorMinimumAmperage,
{
+ fallbackValue: connectorMinimumAmperage,
limitationEnabled:
chargingStation.stationInfo.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumAmperage
}
),
currentPerPhaseSampledValueTemplates.L2.fluctuationPercent ??
connectorMaximumAmperage,
connectorMinimumAmperage,
{
+ fallbackValue: connectorMinimumAmperage,
limitationEnabled:
chargingStation.stationInfo.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumAmperage
}
),
currentPerPhaseSampledValueTemplates.L3.fluctuationPercent ??
connectorMaximumAmperage,
connectorMinimumAmperage,
{
+ fallbackValue: connectorMinimumAmperage,
limitationEnabled:
chargingStation.stationInfo.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumAmperage
}
),
currentSampledValueTemplate.fluctuationPercent ??
connectorMaximumAmperage,
connectorMinimumAmperage,
{
+ fallbackValue: connectorMinimumAmperage,
limitationEnabled:
chargingStation.stationInfo.customValueLimitationMeterValues,
- fallbackValue: connectorMinimumAmperage
}
),
currentSampledValueTemplate.fluctuationPercent ??
`${chargingStation.logPrefix()} MeterValues measurand ${
meterValue.sampledValue[sampledValuesIndex].measurand ??
MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- }: connector id ${connectorId}, transaction id ${connector?.transactionId}, value: ${connectorMinimumAmperage}/${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ }: connector id ${connectorId.toString()}, transaction id ${connector?.transactionId?.toString()}, value: ${connectorMinimumAmperage.toString()}/${
meterValue.sampledValue[sampledValuesIndex].value
- }/${connectorMaximumAmperage}`
+ }/${connectorMaximumAmperage.toString()}`
)
}
for (
chargingStation.getNumberOfPhases() === 3 && phase <= chargingStation.getNumberOfPhases();
phase++
) {
- const phaseValue = `L${phase}`
+ const phaseValue = `L${phase.toString()}`
meterValue.sampledValue.push(
buildSampledValue(
currentPerPhaseSampledValueTemplates[
meterValue.sampledValue[sampledValuesPerPhaseIndex].measurand ??
MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
}: phase ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
meterValue.sampledValue[sampledValuesPerPhaseIndex].phase
- }, connector id ${connectorId}, transaction id ${connector?.transactionId}, value: ${connectorMinimumAmperage}/${
+ }, connector id ${connectorId.toString()}, transaction id $
+ connector?.transactionId?.toString()}, value: ${connectorMinimumAmperage.toString()}/${
meterValue.sampledValue[sampledValuesPerPhaseIndex].value
- }/${connectorMaximumAmperage}`
+ }/${connectorMaximumAmperage.toString()}`
)
}
}
checkMeasurandPowerDivider(chargingStation, energySampledValueTemplate.measurand)
const unitDivider =
energySampledValueTemplate.unit === MeterValueUnit.KILO_WATT_HOUR ? 1000 : 1
- const connectorMaximumAvailablePower =
- chargingStation.getConnectorMaximumAvailablePower(connectorId)
+ connectorMaximumAvailablePower == null &&
+ (connectorMaximumAvailablePower =
+ chargingStation.getConnectorMaximumAvailablePower(connectorId))
const connectorMaximumEnergyRounded = roundTo(
(connectorMaximumAvailablePower * interval) / (3600 * 1000),
2
connectorMaximumEnergyRounded,
connectorMinimumEnergyRounded,
{
- limitationEnabled: chargingStation.stationInfo.customValueLimitationMeterValues,
fallbackValue: connectorMinimumEnergyRounded,
- unitMultiplier: unitDivider
+ limitationEnabled: chargingStation.stationInfo.customValueLimitationMeterValues,
+ unitMultiplier: unitDivider,
}
),
energySampledValueTemplate.fluctuationPercent ?? Constants.DEFAULT_FLUCTUATION_PERCENT
`${chargingStation.logPrefix()} MeterValues measurand ${
meterValue.sampledValue[sampledValuesIndex].measurand ??
MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- }: connector id ${connectorId}, transaction id ${connector?.transactionId}, value: ${connectorMinimumEnergyRounded}/${energyValueRounded}/${connectorMaximumEnergyRounded}, duration: ${interval}ms`
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ }: connector id ${connectorId.toString()}, transaction id ${connector?.transactionId?.toString()}, value: ${connectorMinimumEnergyRounded.toString()}/${energyValueRounded.toString()}/${connectorMaximumEnergyRounded.toString()}, duration: ${interval.toString()}ms`
)
}
}
case OCPPVersion.VERSION_201:
default:
throw new BaseError(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`Cannot build meterValue: OCPP version ${chargingStation.stationInfo?.ocppVersion} not supported`
)
}
switch (chargingStation.stationInfo?.ocppVersion) {
case OCPPVersion.VERSION_16:
meterValue = {
+ sampledValue: [],
timestamp: new Date(),
- sampledValue: []
}
// Energy.Active.Import.Register measurand (default)
sampledValueTemplate = getSampledValueTemplate(chargingStation, connectorId)
case OCPPVersion.VERSION_201:
default:
throw new BaseError(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`Cannot build meterValue: OCPP version ${chargingStation.stationInfo?.ocppVersion} not supported`
)
}
} else if (chargingStation.powerDivider <= 0) {
const errMsg = `MeterValues measurand ${
measurandType ?? MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- }: powerDivider have zero or below value ${chargingStation.powerDivider}`
+ }: powerDivider have zero or below value ${chargingStation.powerDivider.toString()}`
logger.error(`${chargingStation.logPrefix()} ${errMsg}`)
throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, RequestCommand.METER_VALUES)
}
value: string | undefined,
maxLimit: number,
minLimit: number,
- options?: { limitationEnabled?: boolean, fallbackValue?: number, unitMultiplier?: number }
+ options?: {
+ fallbackValue?: number
+ limitationEnabled?: boolean
+ unitMultiplier?: number
+ }
): number => {
options = {
...{
+ fallbackValue: 0,
limitationEnabled: false,
unitMultiplier: 1,
- fallbackValue: 0
},
- ...options
+ ...options,
}
- const parsedValue = parseInt(value ?? '')
- if (options.limitationEnabled === true) {
+ const parsedValue = Number.parseInt(value ?? '')
+ if (options.limitationEnabled) {
return max(
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- min((!isNaN(parsedValue) ? parsedValue : Infinity) * options.unitMultiplier!, maxLimit),
+ min(
+ (!Number.isNaN(parsedValue) ? parsedValue : Number.POSITIVE_INFINITY) *
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ options.unitMultiplier!,
+ maxLimit
+ ),
minLimit
)
}
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return (!isNaN(parsedValue) ? parsedValue : options.fallbackValue!) * options.unitMultiplier!
+ return (
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ (!Number.isNaN(parsedValue) ? parsedValue : options.fallbackValue!) * options.unitMultiplier!
+ )
}
const getSampledValueTemplate = (
const onPhaseStr = phase != null ? `on phase ${phase} ` : ''
if (!OCPPConstants.OCPP_MEASURANDS_SUPPORTED.includes(measurand)) {
logger.warn(
- `${chargingStation.logPrefix()} Trying to get unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}`
+ `${chargingStation.logPrefix()} Trying to get unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId.toString()}`
)
return
}
)?.value?.includes(measurand) === false
) {
logger.debug(
- `${chargingStation.logPrefix()} Trying to get MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId} not found in '${
+ `${chargingStation.logPrefix()} Trying to get MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId.toString()} not found in '${
StandardParametersKey.MeterValuesSampledData
}' OCPP parameter`
)
) {
if (
!OCPPConstants.OCPP_MEASURANDS_SUPPORTED.includes(
- sampledValueTemplates[index]?.measurand ?? MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
+ sampledValueTemplates[index].measurand ?? MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
)
) {
logger.warn(
- `${chargingStation.logPrefix()} Unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}`
+ `${chargingStation.logPrefix()} Unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId.toString()}`
)
} else if (
phase != null &&
- sampledValueTemplates[index]?.phase === phase &&
- sampledValueTemplates[index]?.measurand === measurand &&
+ sampledValueTemplates[index].phase === phase &&
+ sampledValueTemplates[index].measurand === measurand &&
getConfigurationKey(
chargingStation,
StandardParametersKey.MeterValuesSampledData
return sampledValueTemplates[index]
} else if (
phase == null &&
- sampledValueTemplates[index]?.phase == null &&
- sampledValueTemplates[index]?.measurand === measurand &&
+ sampledValueTemplates[index].phase == null &&
+ sampledValueTemplates[index].measurand === measurand &&
getConfigurationKey(
chargingStation,
StandardParametersKey.MeterValuesSampledData
return sampledValueTemplates[index]
} else if (
measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER &&
- (sampledValueTemplates[index]?.measurand == null ||
- sampledValueTemplates[index]?.measurand === measurand)
+ (sampledValueTemplates[index].measurand == null ||
+ sampledValueTemplates[index].measurand === measurand)
) {
return sampledValueTemplates[index]
}
}
if (measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER) {
- const errorMsg = `Missing MeterValues for default measurand '${measurand}' in template on connector id ${connectorId}`
+ const errorMsg = `Missing MeterValues for default measurand '${measurand}' in template on connector id ${connectorId.toString()}`
logger.error(`${chargingStation.logPrefix()} ${errorMsg}`)
throw new BaseError(errorMsg)
}
logger.debug(
- `${chargingStation.logPrefix()} No MeterValues for measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}`
+ `${chargingStation.logPrefix()} No MeterValues for measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId.toString()}`
)
}
const sampledValuePhase = phase ?? sampledValueTemplate.phase
return {
...(sampledValueTemplate.unit != null && {
- unit: sampledValueTemplate.unit
+ unit: sampledValueTemplate.unit,
}),
...(sampledValueContext != null && { context: sampledValueContext }),
...(sampledValueTemplate.measurand != null && {
- measurand: sampledValueTemplate.measurand
+ measurand: sampledValueTemplate.measurand,
}),
...(sampledValueLocation != null && { location: sampledValueLocation }),
...{ value: value.toString() },
- ...(sampledValuePhase != null && { phase: sampledValuePhase })
+ ...(sampledValuePhase != null && { phase: sampledValuePhase }),
} satisfies SampledValue
}
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class OCPPServiceUtils {
- public static readonly getMessageTypeString = getMessageTypeString
- public static readonly sendAndSetConnectorStatus = sendAndSetConnectorStatus
- public static readonly restoreConnectorStatus = restoreConnectorStatus
- public static readonly isIdTagAuthorized = isIdTagAuthorized
public static readonly buildTransactionEndMeterValue = buildTransactionEndMeterValue
- protected static getSampledValueTemplate = getSampledValueTemplate
+ public static readonly isIdTagAuthorized = isIdTagAuthorized
+ public static readonly restoreConnectorStatus = restoreConnectorStatus
+ public static readonly sendAndSetConnectorStatus = sendAndSetConnectorStatus
+
protected static buildSampledValue = buildSampledValue
+ protected static getSampledValueTemplate = getSampledValueTemplate
protected constructor () {
// This is intentional
}
- public static ajvErrorsToErrorType (errors: ErrorObject[] | undefined | null): ErrorType {
- if (isNotEmptyArray(errors)) {
- for (const error of errors as DefinedError[]) {
- switch (error.keyword) {
- case 'type':
- return ErrorType.TYPE_CONSTRAINT_VIOLATION
- case 'dependencies':
- case 'required':
- return ErrorType.OCCURRENCE_CONSTRAINT_VIOLATION
- case 'pattern':
- case 'format':
- return ErrorType.PROPERTY_CONSTRAINT_VIOLATION
- }
- }
- }
- return ErrorType.FORMAT_VIOLATION
- }
-
- public static isRequestCommandSupported (
+ public static isConnectorIdValid (
chargingStation: ChargingStation,
- command: RequestCommand
+ ocppCommand: IncomingRequestCommand,
+ connectorId: number
): boolean {
- const isRequestCommand = Object.values<RequestCommand>(RequestCommand).includes(command)
- if (
- isRequestCommand &&
- chargingStation.stationInfo?.commandsSupport?.outgoingCommands == null
- ) {
- return true
- } else if (
- isRequestCommand &&
- chargingStation.stationInfo?.commandsSupport?.outgoingCommands?.[command] != null
- ) {
- return chargingStation.stationInfo.commandsSupport.outgoingCommands[command]
+ if (connectorId < 0) {
+ logger.error(
+ `${chargingStation.logPrefix()} ${ocppCommand} incoming request received with invalid connector id ${connectorId.toString()}`
+ )
+ return false
}
- logger.error(`${chargingStation.logPrefix()} Unknown outgoing OCPP command '${command}'`)
- return false
+ return true
}
public static isIncomingRequestCommandSupported (
return false
}
- public static isConnectorIdValid (
+ public static isRequestCommandSupported (
chargingStation: ChargingStation,
- ocppCommand: IncomingRequestCommand,
- connectorId: number
+ command: RequestCommand
): boolean {
- if (connectorId < 0) {
- logger.error(
- `${chargingStation.logPrefix()} ${ocppCommand} incoming request received with invalid connector id ${connectorId}`
- )
- return false
- }
- return true
- }
-
- public static convertDateToISOString<T extends JsonType>(object: T): void {
- for (const key in object) {
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion, @typescript-eslint/no-non-null-assertion
- if (isDate(object![key])) {
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion, @typescript-eslint/no-non-null-assertion
- (object![key] as string) = (object![key] as Date).toISOString()
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion, @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-condition
- } else if (typeof object![key] === 'object' && object![key] !== null) {
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion, @typescript-eslint/no-non-null-assertion
- OCPPServiceUtils.convertDateToISOString<T>(object![key] as T)
- }
- }
- }
-
- public static startHeartbeatInterval (chargingStation: ChargingStation, interval: number): void {
- if (chargingStation.heartbeatSetInterval == null) {
- chargingStation.startHeartbeat()
- } else if (chargingStation.getHeartbeatInterval() !== interval) {
- chargingStation.restartHeartbeat()
+ const isRequestCommand = Object.values<RequestCommand>(RequestCommand).includes(command)
+ if (
+ isRequestCommand &&
+ chargingStation.stationInfo?.commandsSupport?.outgoingCommands == null
+ ) {
+ return true
+ } else if (
+ isRequestCommand &&
+ chargingStation.stationInfo?.commandsSupport?.outgoingCommands?.[command] != null
+ ) {
+ return chargingStation.stationInfo.commandsSupport.outgoingCommands[command]
}
+ logger.error(`${chargingStation.logPrefix()} Unknown outgoing OCPP command '${command}'`)
+ return false
}
protected static parseJsonSchemaFile<T extends JsonType>(
OCPPServiceUtils.logPrefix(ocppVersion, moduleName, methodName),
{ throwError: false }
)
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return {} as JSONSchemaType<T>
}
}
buildTransactionEndMeterValue,
getMessageTypeString,
isIdTagAuthorized,
- sendAndSetConnectorStatus
+ sendAndSetConnectorStatus,
} from './OCPPServiceUtils.js'
+import type { WebSocket } from 'ws'
+
import { type IncomingMessage, Server, type ServerResponse } from 'node:http'
import { createServer, type Http2Server } from 'node:http2'
-import type { WebSocket } from 'ws'
+import type { AbstractUIService } from './ui-services/AbstractUIService.js'
import { BaseError } from '../../exception/index.js'
import {
ProtocolVersion,
type RequestPayload,
type ResponsePayload,
- type UIServerConfiguration
+ type UIServerConfiguration,
} from '../../types/index.js'
import { logger } from '../../utils/index.js'
-import type { AbstractUIService } from './ui-services/AbstractUIService.js'
import { UIServiceFactory } from './ui-services/UIServiceFactory.js'
import { getUsernameAndPasswordFromAuthorizationToken } from './UIServerUtils.js'
export abstract class AbstractUIServer {
public readonly chargingStations: Map<string, ChargingStationData>
public readonly chargingStationTemplates: Set<string>
- protected readonly httpServer: Server | Http2Server
+
+ protected readonly httpServer: Http2Server | Server
protected readonly responseHandlers: Map<
`${string}-${string}-${string}-${string}-${string}`,
- ServerResponse | WebSocket
+ ServerResponse | WebSocket
>
protected readonly uiServices: Map<ProtocolVersion, AbstractUIService>
break
default:
throw new BaseError(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`Unsupported application protocol version ${this.uiServerConfiguration.version} in '${ConfigurationSection.uiServer}' configuration section`
)
}
this.responseHandlers = new Map<
`${string}-${string}-${string}-${string}-${string}`,
- ServerResponse | WebSocket
+ ServerResponse | WebSocket
>()
this.uiServices = new Map<ProtocolVersion, AbstractUIService>()
}
return [uuid, responsePayload]
}
- public stop (): void {
- this.stopHttpServer()
- for (const uiService of this.uiServices.values()) {
- uiService.stop()
- }
- this.clearCaches()
- }
-
public clearCaches (): void {
this.chargingStations.clear()
this.chargingStationTemplates.clear()
}
+ public hasResponseHandler (uuid: `${string}-${string}-${string}-${string}-${string}`): boolean {
+ return this.responseHandlers.has(uuid)
+ }
+
+ public abstract logPrefix (moduleName?: string, methodName?: string, prefixSuffix?: string): string
+
public async sendInternalRequest (request: ProtocolRequest): Promise<ProtocolResponse> {
const protocolVersion = ProtocolVersion['0.0.1']
this.registerProtocolVersionUIService(protocolVersion)
?.requestHandler(request) as Promise<ProtocolResponse>)
}
- public hasResponseHandler (uuid: `${string}-${string}-${string}-${string}-${string}`): boolean {
- return this.responseHandlers.has(uuid)
- }
+ public abstract sendRequest (request: ProtocolRequest): void
- protected startHttpServer (): void {
- this.httpServer.on('error', error => {
- logger.error(
- `${this.logPrefix(moduleName, 'start.httpServer.on.error')} HTTP server error:`,
- error
- )
- })
- if (!this.httpServer.listening) {
- this.httpServer.listen(this.uiServerConfiguration.options)
- }
- }
+ public abstract sendResponse (response: ProtocolResponse): void
- protected registerProtocolVersionUIService (version: ProtocolVersion): void {
- if (!this.uiServices.has(version)) {
- this.uiServices.set(version, UIServiceFactory.getUIServiceImplementation(version, this))
+ public abstract start (): void
+
+ public stop (): void {
+ this.stopHttpServer()
+ for (const uiService of this.uiServices.values()) {
+ uiService.stop()
}
+ this.clearCaches()
}
protected authenticate (req: IncomingMessage, next: (err?: Error) => void): void {
next()
}
- private stopHttpServer (): void {
- if (this.httpServer.listening) {
- this.httpServer.close()
- this.httpServer.removeAllListeners()
+ protected registerProtocolVersionUIService (version: ProtocolVersion): void {
+ if (!this.uiServices.has(version)) {
+ this.uiServices.set(version, UIServiceFactory.getUIServiceImplementation(version, this))
+ }
+ }
+
+ protected startHttpServer (): void {
+ this.httpServer.on('error', error => {
+ logger.error(
+ `${this.logPrefix(moduleName, 'start.httpServer.on.error')} HTTP server error:`,
+ error
+ )
+ })
+ if (!this.httpServer.listening) {
+ this.httpServer.listen(this.uiServerConfiguration.options)
}
}
private isValidProtocolBasicAuth (req: IncomingMessage, next: (err?: Error) => void): boolean {
const authorizationProtocol = req.headers['sec-websocket-protocol']?.split(/,\s+/).pop()
const [username, password] = getUsernameAndPasswordFromAuthorizationToken(
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- `${authorizationProtocol}${Array(((4 - (authorizationProtocol!.length % 4)) % 4) + 1).join('=')}`
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/restrict-template-expressions
+ `${authorizationProtocol}${Array(((4 - (authorizationProtocol!.length % 4)) % 4) + 1).join(
+ '='
+ )}`
.split('.')
.pop() ?? '',
next
)
}
- public abstract start (): void
- public abstract sendRequest (request: ProtocolRequest): void
- public abstract sendResponse (response: ProtocolResponse): void
- public abstract logPrefix (moduleName?: string, methodName?: string, prefixSuffix?: string): string
+ private stopHttpServer (): void {
+ if (this.httpServer.listening) {
+ this.httpServer.close()
+ this.httpServer.removeAllListeners()
+ }
+ }
}
type ProtocolVersion,
type RequestPayload,
ResponseStatus,
- type UIServerConfiguration
+ type UIServerConfiguration,
} from '../../types/index.js'
import {
Constants,
isNotEmptyString,
JSONStringify,
logger,
- logPrefix
+ logPrefix,
} from '../../utils/index.js'
import { AbstractUIServer } from './AbstractUIServer.js'
import { isProtocolAndVersionSupported } from './UIServerUtils.js'
enum HttpMethods {
GET = 'GET',
- PUT = 'PUT',
+ PATCH = 'PATCH',
POST = 'POST',
- PATCH = 'PATCH'
+ PUT = 'PUT',
}
export class UIHttpServer extends AbstractUIServer {
- public constructor (protected readonly uiServerConfiguration: UIServerConfiguration) {
+ public constructor (protected override readonly uiServerConfiguration: UIServerConfiguration) {
super(uiServerConfiguration)
}
- public start (): void {
- this.httpServer.on('request', this.requestListener.bind(this))
- this.startHttpServer()
+ public logPrefix = (modName?: string, methodName?: string, prefixSuffix?: string): string => {
+ const logMsgPrefix = prefixSuffix != null ? `UI HTTP Server ${prefixSuffix}` : 'UI HTTP Server'
+ const logMsg =
+ isNotEmptyString(modName) && isNotEmptyString(methodName)
+ ? ` ${logMsgPrefix} | ${modName}.${methodName}:`
+ : ` ${logMsgPrefix} |`
+ return logPrefix(logMsg)
}
public sendRequest (request: ProtocolRequest): void {
const res = this.responseHandlers.get(uuid) as ServerResponse
res
.writeHead(this.responseStatusToStatusCode(payload.status), {
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
})
.end(JSONStringify(payload, undefined, MapStringifyFormat.object))
} else {
}
}
- public logPrefix = (modName?: string, methodName?: string, prefixSuffix?: string): string => {
- const logMsgPrefix = prefixSuffix != null ? `UI HTTP Server ${prefixSuffix}` : 'UI HTTP Server'
- const logMsg =
- isNotEmptyString(modName) && isNotEmptyString(methodName)
- ? ` ${logMsgPrefix} | ${modName}.${methodName}:`
- : ` ${logMsgPrefix} |`
- return logPrefix(logMsg)
+ public start (): void {
+ this.httpServer.on('request', this.requestListener.bind(this))
+ this.startHttpServer()
}
private requestListener (req: IncomingMessage, res: ServerResponse): void {
res
.writeHead(StatusCodes.UNAUTHORIZED, {
'Content-Type': 'text/plain',
- 'WWW-Authenticate': 'Basic realm=users'
+ 'WWW-Authenticate': 'Basic realm=users',
})
- .end(`${StatusCodes.UNAUTHORIZED} Unauthorized`)
+ .end(`${StatusCodes.UNAUTHORIZED.toString()} Unauthorized`)
res.destroy()
req.destroy()
}
} catch (error) {
this.sendResponse(
this.buildProtocolResponse(uuid, {
- status: ResponseStatus.FAILURE,
errorMessage: (error as Error).message,
- errorStack: (error as Error).stack
+ errorStack: (error as Error).stack,
+ status: ResponseStatus.FAILURE,
})
)
return
if (protocolResponse != null) {
this.sendResponse(protocolResponse)
}
+ return undefined
})
.catch(Constants.EMPTY_FUNCTION)
})
} else {
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
throw new BaseError(`Unsupported HTTP method: '${req.method}'`)
}
} catch (error) {
private responseStatusToStatusCode (status: ResponseStatus): StatusCodes {
switch (status) {
- case ResponseStatus.SUCCESS:
- return StatusCodes.OK
case ResponseStatus.FAILURE:
return StatusCodes.BAD_REQUEST
+ case ResponseStatus.SUCCESS:
+ return StatusCodes.OK
default:
return StatusCodes.INTERNAL_SERVER_ERROR
}
import chalk from 'chalk'
+import type { AbstractUIServer } from './AbstractUIServer.js'
+
import { BaseError } from '../../exception/index.js'
import {
ApplicationProtocol,
ApplicationProtocolVersion,
AuthenticationType,
ConfigurationSection,
- type UIServerConfiguration
+ type UIServerConfiguration,
} from '../../types/index.js'
import { logger, logPrefix } from '../../utils/index.js'
-import type { AbstractUIServer } from './AbstractUIServer.js'
import { UIHttpServer } from './UIHttpServer.js'
import { isLoopback } from './UIServerUtils.js'
import { UIWebSocketServer } from './UIWebSocketServer.js'
uiServerConfiguration.type as ApplicationProtocol
)
) {
- // eslint-disable-next-line @typescript-eslint/no-base-to-string
- const logMsg = `Unknown application protocol type '${uiServerConfiguration.type}' in '${ConfigurationSection.uiServer}' configuration section from values '${ApplicationProtocol.toString()}', defaulting to '${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ const logMsg = `Unknown application protocol type '${uiServerConfiguration.type}' in '${
+ ConfigurationSection.uiServer
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
+ }' configuration section from values '${ApplicationProtocol.toString()}', defaulting to '${
ApplicationProtocol.WS
}'`
logger.warn(`${UIServerFactory.logPrefix()} ${logMsg}`)
import { BaseError } from '../../exception/index.js'
import { Protocol, ProtocolVersion } from '../../types/index.js'
-import { logger, logPrefix } from '../../utils/index.js'
+import { isEmpty, logger, logPrefix } from '../../utils/index.js'
export const getUsernameAndPasswordFromAuthorizationToken = (
authorizationToken: string,
export const handleProtocols = (
protocols: Set<string>,
_request: IncomingMessage
-): string | false => {
+): false | string => {
let protocol: Protocol | undefined
let version: ProtocolVersion | undefined
- if (protocols.size === 0) {
+ if (isEmpty(protocols)) {
return false
}
for (const fullProtocol of protocols) {
logger.error(
`${logPrefix(
' UI WebSocket Server |'
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
)} Unsupported protocol: '${protocol}' or protocol version: '${version}'`
)
return false
}
export const isLoopback = (address: string): boolean => {
- // eslint-disable-next-line no-useless-escape
- return /^localhost$|^127(?:\.\d+){0,2}\.\d+$|^(?:0*\:)*?:?0*1$/i.test(address)
+ return /^localhost$|^127(?:\.\d+){0,2}\.\d+$|^(?:0*:)*?:?0*1$/i.test(address)
}
type ProtocolRequest,
type ProtocolResponse,
type UIServerConfiguration,
- WebSocketCloseEventStatusCode
+ WebSocketCloseEventStatusCode,
} from '../../types/index.js'
import {
Constants,
JSONStringify,
logger,
logPrefix,
- validateUUID
+ validateUUID,
} from '../../utils/index.js'
import { AbstractUIServer } from './AbstractUIServer.js'
import {
getProtocolAndVersion,
handleProtocols,
- isProtocolAndVersionSupported
+ isProtocolAndVersionSupported,
} from './UIServerUtils.js'
const moduleName = 'UIWebSocketServer'
export class UIWebSocketServer extends AbstractUIServer {
private readonly webSocketServer: WebSocketServer
- public constructor (protected readonly uiServerConfiguration: UIServerConfiguration) {
+ public constructor (protected override readonly uiServerConfiguration: UIServerConfiguration) {
super(uiServerConfiguration)
this.webSocketServer = new WebSocketServer({
handleProtocols,
- noServer: true
+ noServer: true,
})
}
+ public logPrefix = (modName?: string, methodName?: string, prefixSuffix?: string): string => {
+ const logMsgPrefix =
+ prefixSuffix != null ? `UI WebSocket Server ${prefixSuffix}` : 'UI WebSocket Server'
+ const logMsg =
+ isNotEmptyString(modName) && isNotEmptyString(methodName)
+ ? ` ${logMsgPrefix} | ${modName}.${methodName}:`
+ : ` ${logMsgPrefix} |`
+ return logPrefix(logMsg)
+ }
+
+ public sendRequest (request: ProtocolRequest): void {
+ this.broadcastToClients(JSON.stringify(request))
+ }
+
+ public sendResponse (response: ProtocolResponse): void {
+ const responseId = response[0]
+ try {
+ if (this.hasResponseHandler(responseId)) {
+ const ws = this.responseHandlers.get(responseId) as WebSocket
+ if (ws.readyState === WebSocket.OPEN) {
+ ws.send(JSONStringify(response, undefined, MapStringifyFormat.object))
+ } else {
+ logger.error(
+ `${this.logPrefix(
+ moduleName,
+ 'sendResponse'
+ )} Error at sending response id '${responseId}', WebSocket is not open: ${ws.readyState.toString()}`
+ )
+ }
+ } else {
+ logger.error(
+ `${this.logPrefix(
+ moduleName,
+ 'sendResponse'
+ )} Response for unknown request id: ${responseId}`
+ )
+ }
+ } catch (error) {
+ logger.error(
+ `${this.logPrefix(
+ moduleName,
+ 'sendResponse'
+ )} Error at sending response id '${responseId}':`,
+ error
+ )
+ } finally {
+ this.responseHandlers.delete(responseId)
+ }
+ }
+
public start (): void {
this.webSocketServer.on('connection', (ws: WebSocket, _req: IncomingMessage): void => {
if (!isProtocolAndVersionSupported(ws.protocol)) {
if (protocolResponse != null) {
this.sendResponse(protocolResponse)
}
+ return undefined
})
.catch(Constants.EMPTY_FUNCTION)
})
})
this.httpServer.on('connect', (req: IncomingMessage, socket: Duplex, _head: Buffer) => {
if (req.headers.connection !== 'Upgrade' || req.headers.upgrade !== 'websocket') {
- socket.write(`HTTP/1.1 ${StatusCodes.BAD_REQUEST} Bad Request\r\n\r\n`)
+ socket.write(`HTTP/1.1 ${StatusCodes.BAD_REQUEST.toString()} Bad Request\r\n\r\n`)
socket.destroy()
}
})
socket.on('error', onSocketError)
this.authenticate(req, err => {
if (err != null) {
- socket.write(`HTTP/1.1 ${StatusCodes.UNAUTHORIZED} Unauthorized\r\n\r\n`)
+ socket.write(`HTTP/1.1 ${StatusCodes.UNAUTHORIZED.toString()} Unauthorized\r\n\r\n`)
socket.destroy()
return
}
this.startHttpServer()
}
- public sendRequest (request: ProtocolRequest): void {
- this.broadcastToClients(JSON.stringify(request))
- }
-
- public sendResponse (response: ProtocolResponse): void {
- const responseId = response[0]
- try {
- if (this.hasResponseHandler(responseId)) {
- const ws = this.responseHandlers.get(responseId) as WebSocket
- if (ws.readyState === WebSocket.OPEN) {
- ws.send(JSONStringify(response, undefined, MapStringifyFormat.object))
- } else {
- logger.error(
- `${this.logPrefix(
- moduleName,
- 'sendResponse'
- )} Error at sending response id '${responseId}', WebSocket is not open: ${
- ws.readyState
- }`
- )
- }
- } else {
- logger.error(
- `${this.logPrefix(
- moduleName,
- 'sendResponse'
- )} Response for unknown request id: ${responseId}`
- )
- }
- } catch (error) {
- logger.error(
- `${this.logPrefix(
- moduleName,
- 'sendResponse'
- )} Error at sending response id '${responseId}':`,
- error
- )
- } finally {
- this.responseHandlers.delete(responseId)
- }
- }
-
- public logPrefix = (modName?: string, methodName?: string, prefixSuffix?: string): string => {
- const logMsgPrefix =
- prefixSuffix != null ? `UI WebSocket Server ${prefixSuffix}` : 'UI WebSocket Server'
- const logMsg =
- isNotEmptyString(modName) && isNotEmptyString(methodName)
- ? ` ${logMsgPrefix} | ${modName}.${methodName}:`
- : ` ${logMsgPrefix} |`
- return logPrefix(logMsg)
- }
-
private broadcastToClients (message: string): void {
for (const client of this.webSocketServer.clients) {
if (client.readyState === WebSocket.OPEN) {
}
}
- private validateRawDataRequest (rawData: RawData): ProtocolRequest | false {
+ private validateRawDataRequest (rawData: RawData): false | ProtocolRequest {
// logger.debug(
// `${this.logPrefix(
// moduleName,
+import type { AbstractUIServer } from '../AbstractUIServer.js'
+
import { BaseError, type OCPPError } from '../../../exception/index.js'
import {
BroadcastChannelProcedureName,
type RequestPayload,
type ResponsePayload,
ResponseStatus,
- type StorageConfiguration
+ type StorageConfiguration,
} from '../../../types/index.js'
import { Configuration, isAsyncFunction, isNotEmptyArray, logger } from '../../../utils/index.js'
import { Bootstrap } from '../../Bootstrap.js'
import { UIServiceWorkerBroadcastChannel } from '../../broadcast-channel/UIServiceWorkerBroadcastChannel.js'
-import type { AbstractUIServer } from '../AbstractUIServer.js'
const moduleName = 'AbstractUIService'
interface AddChargingStationsRequestPayload extends RequestPayload {
- template: string
numberOfStations: number
options?: ChargingStationOptions
+ template: string
}
export abstract class AbstractUIService {
protected static readonly ProcedureNameToBroadCastChannelProcedureNameMapping = new Map<
- ProcedureName,
- BroadcastChannelProcedureName
+ ProcedureName,
+ BroadcastChannelProcedureName
>([
- [ProcedureName.START_CHARGING_STATION, BroadcastChannelProcedureName.START_CHARGING_STATION],
- [ProcedureName.STOP_CHARGING_STATION, BroadcastChannelProcedureName.STOP_CHARGING_STATION],
+ [ProcedureName.AUTHORIZE, BroadcastChannelProcedureName.AUTHORIZE],
+ [ProcedureName.BOOT_NOTIFICATION, BroadcastChannelProcedureName.BOOT_NOTIFICATION],
+ [ProcedureName.CLOSE_CONNECTION, BroadcastChannelProcedureName.CLOSE_CONNECTION],
+ [ProcedureName.DATA_TRANSFER, BroadcastChannelProcedureName.DATA_TRANSFER],
[
ProcedureName.DELETE_CHARGING_STATIONS,
- BroadcastChannelProcedureName.DELETE_CHARGING_STATIONS
+ BroadcastChannelProcedureName.DELETE_CHARGING_STATIONS,
],
- [ProcedureName.CLOSE_CONNECTION, BroadcastChannelProcedureName.CLOSE_CONNECTION],
- [ProcedureName.OPEN_CONNECTION, BroadcastChannelProcedureName.OPEN_CONNECTION],
[
- ProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
- BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR
+ ProcedureName.DIAGNOSTICS_STATUS_NOTIFICATION,
+ BroadcastChannelProcedureName.DIAGNOSTICS_STATUS_NOTIFICATION,
],
[
- ProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
- BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR
+ ProcedureName.FIRMWARE_STATUS_NOTIFICATION,
+ BroadcastChannelProcedureName.FIRMWARE_STATUS_NOTIFICATION,
],
- [ProcedureName.SET_SUPERVISION_URL, BroadcastChannelProcedureName.SET_SUPERVISION_URL],
- [ProcedureName.START_TRANSACTION, BroadcastChannelProcedureName.START_TRANSACTION],
- [ProcedureName.STOP_TRANSACTION, BroadcastChannelProcedureName.STOP_TRANSACTION],
- [ProcedureName.AUTHORIZE, BroadcastChannelProcedureName.AUTHORIZE],
- [ProcedureName.BOOT_NOTIFICATION, BroadcastChannelProcedureName.BOOT_NOTIFICATION],
- [ProcedureName.STATUS_NOTIFICATION, BroadcastChannelProcedureName.STATUS_NOTIFICATION],
[ProcedureName.HEARTBEAT, BroadcastChannelProcedureName.HEARTBEAT],
[ProcedureName.METER_VALUES, BroadcastChannelProcedureName.METER_VALUES],
- [ProcedureName.DATA_TRANSFER, BroadcastChannelProcedureName.DATA_TRANSFER],
+ [ProcedureName.OPEN_CONNECTION, BroadcastChannelProcedureName.OPEN_CONNECTION],
+ [ProcedureName.SET_SUPERVISION_URL, BroadcastChannelProcedureName.SET_SUPERVISION_URL],
[
- ProcedureName.DIAGNOSTICS_STATUS_NOTIFICATION,
- BroadcastChannelProcedureName.DIAGNOSTICS_STATUS_NOTIFICATION
+ ProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
+ BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
],
+ [ProcedureName.START_CHARGING_STATION, BroadcastChannelProcedureName.START_CHARGING_STATION],
+ [ProcedureName.START_TRANSACTION, BroadcastChannelProcedureName.START_TRANSACTION],
+ [ProcedureName.STATUS_NOTIFICATION, BroadcastChannelProcedureName.STATUS_NOTIFICATION],
[
- ProcedureName.FIRMWARE_STATUS_NOTIFICATION,
- BroadcastChannelProcedureName.FIRMWARE_STATUS_NOTIFICATION
- ]
+ ProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
+ BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
+ ],
+ [ProcedureName.STOP_CHARGING_STATION, BroadcastChannelProcedureName.STOP_CHARGING_STATION],
+ [ProcedureName.STOP_TRANSACTION, BroadcastChannelProcedureName.STOP_TRANSACTION],
])
protected readonly requestHandlers: Map<ProcedureName, ProtocolRequestHandler>
- private readonly version: ProtocolVersion
- private readonly uiServer: AbstractUIServer
- private readonly uiServiceWorkerBroadcastChannel: UIServiceWorkerBroadcastChannel
private readonly broadcastChannelRequests: Map<
`${string}-${string}-${string}-${string}-${string}`,
- number
+ number
>
+ private readonly uiServer: AbstractUIServer
+ private readonly uiServiceWorkerBroadcastChannel: UIServiceWorkerBroadcastChannel
+ private readonly version: ProtocolVersion
+
constructor (uiServer: AbstractUIServer, version: ProtocolVersion) {
this.uiServer = uiServer
this.version = version
this.requestHandlers = new Map<ProcedureName, ProtocolRequestHandler>([
- [ProcedureName.LIST_TEMPLATES, this.handleListTemplates.bind(this)],
- [ProcedureName.LIST_CHARGING_STATIONS, this.handleListChargingStations.bind(this)],
[ProcedureName.ADD_CHARGING_STATIONS, this.handleAddChargingStations.bind(this)],
+ [ProcedureName.LIST_CHARGING_STATIONS, this.handleListChargingStations.bind(this)],
+ [ProcedureName.LIST_TEMPLATES, this.handleListTemplates.bind(this)],
[ProcedureName.PERFORMANCE_STATISTICS, this.handlePerformanceStatistics.bind(this)],
[ProcedureName.SIMULATOR_STATE, this.handleSimulatorState.bind(this)],
[ProcedureName.START_SIMULATOR, this.handleStartSimulator.bind(this)],
- [ProcedureName.STOP_SIMULATOR, this.handleStopSimulator.bind(this)]
+ [ProcedureName.STOP_SIMULATOR, this.handleStopSimulator.bind(this)],
])
this.uiServiceWorkerBroadcastChannel = new UIServiceWorkerBroadcastChannel(this)
this.broadcastChannelRequests = new Map<
`${string}-${string}-${string}-${string}-${string}`,
- number
+ number
>()
}
- public stop (): void {
- this.broadcastChannelRequests.clear()
- this.uiServiceWorkerBroadcastChannel.close()
+ public deleteBroadcastChannelRequest (
+ uuid: `${string}-${string}-${string}-${string}-${string}`
+ ): void {
+ this.broadcastChannelRequests.delete(uuid)
+ }
+
+ public getBroadcastChannelExpectedResponses (
+ uuid: `${string}-${string}-${string}-${string}-${string}`
+ ): number {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return this.broadcastChannelRequests.get(uuid)!
+ }
+
+ public logPrefix = (modName: string, methodName: string): string => {
+ return this.uiServer.logPrefix(modName, methodName, this.version)
}
public async requestHandler (request: ProtocolRequest): Promise<ProtocolResponse | undefined> {
let requestPayload: RequestPayload | undefined
let responsePayload: ResponsePayload | undefined
try {
- [uuid, command, requestPayload] = request
+ ;[uuid, command, requestPayload] = request
if (!this.requestHandlers.has(command)) {
throw new BaseError(
uuid?: string,
procedureName?: ProcedureName,
payload?: RequestPayload
- ) => undefined | ResponsePayload
+ ) => ResponsePayload | undefined
)(uuid, command, requestPayload)
}
} catch (error) {
// Log
logger.error(`${this.logPrefix(moduleName, 'requestHandler')} Handle request error:`, error)
responsePayload = {
- hashIds: requestPayload?.hashIds,
- status: ResponseStatus.FAILURE,
command,
- requestPayload,
- responsePayload,
+ errorDetails: (error as OCPPError).details,
errorMessage: (error as OCPPError).message,
errorStack: (error as OCPPError).stack,
- errorDetails: (error as OCPPError).details
+ hashIds: requestPayload?.hashIds,
+ requestPayload,
+ responsePayload,
+ status: ResponseStatus.FAILURE,
} satisfies ResponsePayload
}
if (responsePayload != null) {
}
}
- // public sendRequest (
- // uuid: `${string}-${string}-${string}-${string}-${string}`,
- // procedureName: ProcedureName,
- // requestPayload: RequestPayload
- // ): void {
- // this.uiServer.sendRequest(
- // this.uiServer.buildProtocolRequest(uuid, procedureName, requestPayload)
- // )
- // }
-
public sendResponse (
uuid: `${string}-${string}-${string}-${string}-${string}`,
responsePayload: ResponsePayload
}
}
- public logPrefix = (modName: string, methodName: string): string => {
- return this.uiServer.logPrefix(modName, methodName, this.version)
- }
-
- public deleteBroadcastChannelRequest (
- uuid: `${string}-${string}-${string}-${string}-${string}`
- ): void {
- this.broadcastChannelRequests.delete(uuid)
- }
-
- public getBroadcastChannelExpectedResponses (
- uuid: `${string}-${string}-${string}-${string}-${string}`
- ): number {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return this.broadcastChannelRequests.get(uuid)!
+ public stop (): void {
+ this.broadcastChannelRequests.clear()
+ this.uiServiceWorkerBroadcastChannel.close()
}
protected handleProtocolRequest (
)
}
- private sendBroadcastChannelRequest (
- uuid: `${string}-${string}-${string}-${string}-${string}`,
- procedureName: BroadcastChannelProcedureName,
- payload: BroadcastChannelRequestPayload
- ): void {
- if (isNotEmptyArray(payload.hashIds)) {
- payload.hashIds = payload.hashIds
- .map(hashId => {
- if (this.uiServer.chargingStations.has(hashId)) {
- return hashId
- }
- logger.warn(
- `${this.logPrefix(
- moduleName,
- 'sendBroadcastChannelRequest'
- )} Charging station with hashId '${hashId}' not found`
- )
- return undefined
- })
- .filter(hashId => hashId != null) as string[]
- } else {
- delete payload.hashIds
- }
- const expectedNumberOfResponses = Array.isArray(payload.hashIds)
- ? payload.hashIds.length
- : this.uiServer.chargingStations.size
- if (expectedNumberOfResponses === 0) {
- throw new BaseError(
- 'hashIds array in the request payload does not contain any valid charging station hashId'
- )
- }
- this.uiServiceWorkerBroadcastChannel.sendRequest([uuid, procedureName, payload])
- this.broadcastChannelRequests.set(uuid, expectedNumberOfResponses)
- }
-
- private handleListTemplates (): ResponsePayload {
- return {
- status: ResponseStatus.SUCCESS,
- templates: [...this.uiServer.chargingStationTemplates.values()] as JsonType[]
- } satisfies ResponsePayload
- }
-
- private handleListChargingStations (): ResponsePayload {
- return {
- status: ResponseStatus.SUCCESS,
- chargingStations: [...this.uiServer.chargingStations.values()] as JsonType[]
- } satisfies ResponsePayload
- }
-
private async handleAddChargingStations (
_uuid?: `${string}-${string}-${string}-${string}-${string}`,
_procedureName?: ProcedureName,
requestPayload?: RequestPayload
): Promise<ResponsePayload> {
- const { template, numberOfStations, options } =
+ const { numberOfStations, options, template } =
requestPayload as AddChargingStationsRequestPayload
if (!Bootstrap.getInstance().getState().started) {
return {
- status: ResponseStatus.FAILURE,
errorMessage:
- 'Cannot add charging station(s) while the charging stations simulator is not started'
+ 'Cannot add charging station(s) while the charging stations simulator is not started',
+ status: ResponseStatus.FAILURE,
} satisfies ResponsePayload
}
if (typeof template !== 'string' || typeof numberOfStations !== 'number') {
return {
+ errorMessage: 'Invalid request payload',
status: ResponseStatus.FAILURE,
- errorMessage: 'Invalid request payload'
} satisfies ResponsePayload
}
if (!this.uiServer.chargingStationTemplates.has(template)) {
return {
+ errorMessage: `Template '${template}' not found`,
status: ResponseStatus.FAILURE,
- errorMessage: `Template '${template}' not found`
} satisfies ResponsePayload
}
const succeededStationInfos: ChargingStationInfo[] = []
return {
status: err != null ? ResponseStatus.FAILURE : ResponseStatus.SUCCESS,
...(succeededStationInfos.length > 0 && {
- hashIdsSucceeded: succeededStationInfos.map(stationInfo => stationInfo.hashId)
+ hashIdsSucceeded: succeededStationInfos.map(stationInfo => stationInfo.hashId),
}),
...(failedStationInfos.length > 0 && {
- hashIdsFailed: failedStationInfos.map(stationInfo => stationInfo.hashId)
+ hashIdsFailed: failedStationInfos.map(stationInfo => stationInfo.hashId),
}),
- ...(err != null && { errorMessage: err.message, errorStack: err.stack })
+ ...(err != null && { errorMessage: err.message, errorStack: err.stack }),
+ } satisfies ResponsePayload
+ }
+
+ private handleListChargingStations (): ResponsePayload {
+ return {
+ chargingStations: [...this.uiServer.chargingStations.values()] as JsonType[],
+ status: ResponseStatus.SUCCESS,
+ } satisfies ResponsePayload
+ }
+
+ private handleListTemplates (): ResponsePayload {
+ return {
+ status: ResponseStatus.SUCCESS,
+ templates: [...this.uiServer.chargingStationTemplates.values()],
} satisfies ResponsePayload
}
).enabled !== true
) {
return {
+ errorMessage: 'Performance statistics storage is not enabled',
status: ResponseStatus.FAILURE,
- errorMessage: 'Performance statistics storage is not enabled'
} satisfies ResponsePayload
}
try {
return {
- status: ResponseStatus.SUCCESS,
performanceStatistics: [
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- ...Bootstrap.getInstance().getPerformanceStatistics()!
- ] as JsonType[]
+ ...Bootstrap.getInstance().getPerformanceStatistics()!,
+ ] as JsonType[],
+ status: ResponseStatus.SUCCESS,
} satisfies ResponsePayload
} catch (error) {
return {
- status: ResponseStatus.FAILURE,
errorMessage: (error as Error).message,
- errorStack: (error as Error).stack
+ errorStack: (error as Error).stack,
+ status: ResponseStatus.FAILURE,
} satisfies ResponsePayload
}
}
private handleSimulatorState (): ResponsePayload {
try {
return {
+ state: Bootstrap.getInstance().getState() as unknown as JsonObject,
status: ResponseStatus.SUCCESS,
- state: Bootstrap.getInstance().getState() as unknown as JsonObject
} satisfies ResponsePayload
} catch (error) {
return {
- status: ResponseStatus.FAILURE,
errorMessage: (error as Error).message,
- errorStack: (error as Error).stack
+ errorStack: (error as Error).stack,
+ status: ResponseStatus.FAILURE,
} satisfies ResponsePayload
}
}
return { status: ResponseStatus.SUCCESS }
} catch (error) {
return {
- status: ResponseStatus.FAILURE,
errorMessage: (error as Error).message,
- errorStack: (error as Error).stack
+ errorStack: (error as Error).stack,
+ status: ResponseStatus.FAILURE,
} satisfies ResponsePayload
}
}
+ // public sendRequest (
+ // uuid: `${string}-${string}-${string}-${string}-${string}`,
+ // procedureName: ProcedureName,
+ // requestPayload: RequestPayload
+ // ): void {
+ // this.uiServer.sendRequest(
+ // this.uiServer.buildProtocolRequest(uuid, procedureName, requestPayload)
+ // )
+ // }
+
private async handleStopSimulator (): Promise<ResponsePayload> {
try {
await Bootstrap.getInstance().stop()
return { status: ResponseStatus.SUCCESS }
} catch (error) {
return {
- status: ResponseStatus.FAILURE,
errorMessage: (error as Error).message,
- errorStack: (error as Error).stack
+ errorStack: (error as Error).stack,
+ status: ResponseStatus.FAILURE,
} satisfies ResponsePayload
}
}
+
+ private sendBroadcastChannelRequest (
+ uuid: `${string}-${string}-${string}-${string}-${string}`,
+ procedureName: BroadcastChannelProcedureName,
+ payload: BroadcastChannelRequestPayload
+ ): void {
+ if (isNotEmptyArray(payload.hashIds)) {
+ payload.hashIds = payload.hashIds
+ .map(hashId => {
+ if (this.uiServer.chargingStations.has(hashId)) {
+ return hashId
+ }
+ logger.warn(
+ `${this.logPrefix(
+ moduleName,
+ 'sendBroadcastChannelRequest'
+ )} Charging station with hashId '${hashId}' not found`
+ )
+ return undefined
+ })
+ .filter(hashId => hashId != null)
+ } else {
+ delete payload.hashIds
+ }
+ const expectedNumberOfResponses = Array.isArray(payload.hashIds)
+ ? payload.hashIds.length
+ : this.uiServer.chargingStations.size
+ if (expectedNumberOfResponses === 0) {
+ throw new BaseError(
+ 'hashIds array in the request payload does not contain any valid charging station hashId'
+ )
+ }
+ this.uiServiceWorkerBroadcastChannel.sendRequest([uuid, procedureName, payload])
+ this.broadcastChannelRequests.set(uuid, expectedNumberOfResponses)
+ }
}
-import { type ProtocolRequestHandler, ProtocolVersion } from '../../../types/index.js'
import type { AbstractUIServer } from '../AbstractUIServer.js'
+
+import { type ProtocolRequestHandler, ProtocolVersion } from '../../../types/index.js'
import { AbstractUIService } from './AbstractUIService.js'
export class UIService001 extends AbstractUIService {
-import { ProtocolVersion } from '../../../types/index.js'
import type { AbstractUIServer } from '../AbstractUIServer.js'
import type { AbstractUIService } from './AbstractUIService.js'
+
+import { ProtocolVersion } from '../../../types/index.js'
import { UIService001 } from './UIService001.js'
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
uiServer: AbstractUIServer
): AbstractUIService {
switch (version) {
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
case ProtocolVersion['0.0.1']:
return new UIService001(uiServer)
}
// Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
import type { ErrorType, IncomingRequestCommand, JsonType, RequestCommand } from '../types/index.js'
+
import { Constants } from '../utils/index.js'
import { BaseError } from './BaseError.js'
export class OCPPError extends BaseError {
code: ErrorType
- command: RequestCommand | IncomingRequestCommand
+ command: IncomingRequestCommand | RequestCommand
details?: JsonType
constructor (
code: ErrorType,
message: string,
- command?: RequestCommand | IncomingRequestCommand,
+ command?: IncomingRequestCommand | RequestCommand,
details?: JsonType
) {
super(message)
// Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
-import { performance, type PerformanceEntry, PerformanceObserver } from 'node:perf_hooks'
import type { URL } from 'node:url'
-import { parentPort } from 'node:worker_threads'
import { secondsToMilliseconds } from 'date-fns'
import { CircularBuffer } from 'mnemonist'
-import { is, mean, median } from 'rambda'
+import { performance, type PerformanceEntry, PerformanceObserver } from 'node:perf_hooks'
+import { parentPort } from 'node:worker_threads'
import { BaseError } from '../exception/index.js'
import {
type Statistics,
type StatisticsData,
type StorageConfiguration,
- type TimestampedData
+ type TimestampedData,
} from '../types/index.js'
import {
+ average,
buildPerformanceStatisticsMessage,
Configuration,
Constants,
logger,
logPrefix,
max,
+ median,
min,
- nthPercentile,
- stdDeviation
+ percentile,
+ std,
} from '../utils/index.js'
export class PerformanceStatistics {
private static readonly instances: Map<string, PerformanceStatistics> = new Map<
- string,
- PerformanceStatistics
+ string,
+ PerformanceStatistics
>()
+ private displayInterval?: NodeJS.Timeout
private readonly objId: string | undefined
private readonly objName: string | undefined
private performanceObserver!: PerformanceObserver
private readonly statistics: Statistics
- private displayInterval?: NodeJS.Timeout
private constructor (objId: string, objName: string, uri: URL) {
this.objId = objId
this.objName = objName
this.initializePerformanceObserver()
this.statistics = {
+ createdAt: new Date(),
id: this.objId,
name: this.objName,
+ statisticsData: new Map(),
uri: uri.toString(),
- createdAt: new Date(),
- statisticsData: new Map()
}
}
+ public static beginMeasure (id: string): string {
+ const markId = `${id.charAt(0).toUpperCase()}${id.slice(1)}~${generateUUID()}`
+ performance.mark(markId)
+ return markId
+ }
+
+ public static deleteInstance (objId: string | undefined): boolean {
+ if (objId == null) {
+ const errMsg = 'Cannot delete performance statistics instance without specifying object id'
+ logger.error(`${PerformanceStatistics.logPrefix()} ${errMsg}`)
+ throw new BaseError(errMsg)
+ }
+ return PerformanceStatistics.instances.delete(objId)
+ }
+
+ public static endMeasure (name: string, markId: string): void {
+ try {
+ performance.measure(name, markId)
+ } catch (error) {
+ if (error instanceof Error && error.message.includes('performance mark has not been set')) {
+ /* Ignore */
+ } else {
+ throw error
+ }
+ }
+ performance.clearMarks(markId)
+ performance.clearMeasures(name)
+ }
+
public static getInstance (
objId: string | undefined,
objName: string | undefined,
- uri: URL | undefined
+ uri: undefined | URL
): PerformanceStatistics | undefined {
if (objId == null) {
const errMsg = 'Cannot get performance statistics instance without specifying object id'
return PerformanceStatistics.instances.get(objId)
}
- public static deleteInstance (objId: string | undefined): boolean {
- if (objId == null) {
- const errMsg = 'Cannot delete performance statistics instance without specifying object id'
- logger.error(`${PerformanceStatistics.logPrefix()} ${errMsg}`)
- throw new BaseError(errMsg)
- }
- return PerformanceStatistics.instances.delete(objId)
- }
-
- public static beginMeasure (id: string): string {
- const markId = `${id.charAt(0).toUpperCase()}${id.slice(1)}~${generateUUID()}`
- performance.mark(markId)
- return markId
- }
-
- public static endMeasure (name: string, markId: string): void {
- try {
- performance.measure(name, markId)
- } catch (error) {
- if (is(Error, error) && error.message.includes('performance mark has not been set')) {
- /* Ignore */
- } else {
- throw error
- }
- }
- performance.clearMarks(markId)
- performance.clearMeasures(name)
+ private static readonly logPrefix = (): string => {
+ return logPrefix(' Performance statistics')
}
public addRequestStatistic (
- command: RequestCommand | IncomingRequestCommand,
+ command: IncomingRequestCommand | RequestCommand,
messageType: MessageType
): void {
switch (messageType) {
- case MessageType.CALL_MESSAGE:
+ case MessageType.CALL_ERROR_MESSAGE:
if (
this.statistics.statisticsData.has(command) &&
- this.statistics.statisticsData.get(command)?.requestCount != null
+ this.statistics.statisticsData.get(command)?.errorCount != null
) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- ++this.statistics.statisticsData.get(command)!.requestCount!
+ ++this.statistics.statisticsData.get(command)!.errorCount!
} else {
this.statistics.statisticsData.set(command, {
...this.statistics.statisticsData.get(command),
- requestCount: 1
+ errorCount: 1,
})
}
break
- case MessageType.CALL_RESULT_MESSAGE:
+ case MessageType.CALL_MESSAGE:
if (
this.statistics.statisticsData.has(command) &&
- this.statistics.statisticsData.get(command)?.responseCount != null
+ this.statistics.statisticsData.get(command)?.requestCount != null
) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- ++this.statistics.statisticsData.get(command)!.responseCount!
+ ++this.statistics.statisticsData.get(command)!.requestCount!
} else {
this.statistics.statisticsData.set(command, {
...this.statistics.statisticsData.get(command),
- responseCount: 1
+ requestCount: 1,
})
}
break
- case MessageType.CALL_ERROR_MESSAGE:
+ case MessageType.CALL_RESULT_MESSAGE:
if (
this.statistics.statisticsData.has(command) &&
- this.statistics.statisticsData.get(command)?.errorCount != null
+ this.statistics.statisticsData.get(command)?.responseCount != null
) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- ++this.statistics.statisticsData.get(command)!.errorCount!
+ ++this.statistics.statisticsData.get(command)!.responseCount!
} else {
this.statistics.statisticsData.set(command, {
...this.statistics.statisticsData.get(command),
- errorCount: 1
+ responseCount: 1,
})
}
break
}
}
+ public restart (): void {
+ this.stop()
+ this.start()
+ }
+
public start (): void {
this.startLogStatisticsInterval()
const performanceStorageConfiguration =
)
if (performanceStorageConfiguration.enabled === true) {
logger.info(
- `${this.logPrefix()} storage enabled: type ${performanceStorageConfiguration.type}, uri: ${
- performanceStorageConfiguration.uri
- }`
+ `${this.logPrefix()} storage enabled: type ${
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ performanceStorageConfiguration.type
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ }, uri: ${performanceStorageConfiguration.uri}`
)
}
}
this.performanceObserver.disconnect()
}
- public restart (): void {
- this.stop()
- this.start()
- }
-
- private initializePerformanceObserver (): void {
- this.performanceObserver = new PerformanceObserver(performanceObserverList => {
- const lastPerformanceEntry = performanceObserverList.getEntries()[0]
- // logger.debug(
- // `${this.logPrefix()} '${lastPerformanceEntry.name}' performance entry: %j`,
- // lastPerformanceEntry
- // )
- this.addPerformanceEntryToStatistics(lastPerformanceEntry)
- })
- this.performanceObserver.observe({ entryTypes: ['measure'] })
- }
-
- private logStatistics (): void {
- logger.info(this.logPrefix(), {
- ...this.statistics,
- statisticsData: JSON.parse(
- JSONStringify(this.statistics.statisticsData, undefined, MapStringifyFormat.object)
- ) as Map<string | RequestCommand | IncomingRequestCommand, StatisticsData>
- })
- }
-
- private startLogStatisticsInterval (): void {
- const logConfiguration = Configuration.getConfigurationSection<LogConfiguration>(
- ConfigurationSection.log
- )
- const logStatisticsInterval =
- logConfiguration.enabled === true
- ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- logConfiguration.statisticsInterval!
- : 0
- if (logStatisticsInterval > 0 && this.displayInterval == null) {
- this.displayInterval = setInterval(() => {
- this.logStatistics()
- }, secondsToMilliseconds(logStatisticsInterval))
- logger.info(
- `${this.logPrefix()} logged every ${formatDurationSeconds(logStatisticsInterval)}`
- )
- } else if (this.displayInterval != null) {
- logger.info(
- `${this.logPrefix()} already logged every ${formatDurationSeconds(logStatisticsInterval)}`
- )
- } else if (logConfiguration.enabled === true) {
- logger.info(
- `${this.logPrefix()} log interval is set to ${logStatisticsInterval}. Not logging statistics`
- )
- }
- }
-
- private stopLogStatisticsInterval (): void {
- if (this.displayInterval != null) {
- clearInterval(this.displayInterval)
- delete this.displayInterval
- }
- }
-
private addPerformanceEntryToStatistics (entry: PerformanceEntry): void {
// Initialize command statistics
if (!this.statistics.statisticsData.has(entry.name)) {
Constants.DEFAULT_CIRCULAR_BUFFER_CAPACITY
)
}
- this.statistics.statisticsData
- .get(entry.name)
- ?.measurementTimeSeries?.push({ timestamp: entry.startTime, value: entry.duration })
+ this.statistics.statisticsData.get(entry.name)?.measurementTimeSeries?.push({
+ timestamp: entry.startTime,
+ value: entry.duration,
+ })
const timeMeasurementValues = extractTimeSeriesValues(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.statistics.statisticsData.get(entry.name)!.measurementTimeSeries!
+ this.statistics.statisticsData.get(entry.name)!
+ .measurementTimeSeries as CircularBuffer<TimestampedData>
)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.statistics.statisticsData.get(entry.name)!.avgTimeMeasurement = mean(timeMeasurementValues)
+ this.statistics.statisticsData.get(entry.name)!.avgTimeMeasurement =
+ average(timeMeasurementValues)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.statistics.statisticsData.get(entry.name)!.medTimeMeasurement =
median(timeMeasurementValues)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.statistics.statisticsData.get(entry.name)!.ninetyFiveThPercentileTimeMeasurement =
- nthPercentile(timeMeasurementValues, 95)
+ percentile(timeMeasurementValues, 95)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.statistics.statisticsData.get(entry.name)!.stdDevTimeMeasurement = stdDeviation(
+ this.statistics.statisticsData.get(entry.name)!.stdTimeMeasurement = std(
timeMeasurementValues,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.statistics.statisticsData.get(entry.name)!.avgTimeMeasurement
}
}
- private static readonly logPrefix = (): string => {
- return logPrefix(' Performance statistics')
+ private initializePerformanceObserver (): void {
+ this.performanceObserver = new PerformanceObserver(performanceObserverList => {
+ const lastPerformanceEntry = performanceObserverList.getEntries()[0]
+ // logger.debug(
+ // `${this.logPrefix()} '${lastPerformanceEntry.name}' performance entry: %j`,
+ // lastPerformanceEntry
+ // )
+ this.addPerformanceEntryToStatistics(lastPerformanceEntry)
+ })
+ this.performanceObserver.observe({ entryTypes: ['measure'] })
}
private readonly logPrefix = (): string => {
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return logPrefix(` ${this.objName} | Performance statistics`)
}
+
+ private logStatistics (): void {
+ logger.info(this.logPrefix(), {
+ ...this.statistics,
+ statisticsData: JSON.parse(
+ JSONStringify(this.statistics.statisticsData, undefined, MapStringifyFormat.object)
+ ) as Map<IncomingRequestCommand | RequestCommand | string, StatisticsData>,
+ })
+ }
+
+ private startLogStatisticsInterval (): void {
+ const logConfiguration = Configuration.getConfigurationSection<LogConfiguration>(
+ ConfigurationSection.log
+ )
+ const logStatisticsInterval =
+ logConfiguration.enabled === true
+ ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ logConfiguration.statisticsInterval!
+ : 0
+ if (logStatisticsInterval > 0 && this.displayInterval == null) {
+ this.displayInterval = setInterval(() => {
+ this.logStatistics()
+ }, secondsToMilliseconds(logStatisticsInterval))
+ logger.info(
+ `${this.logPrefix()} logged every ${formatDurationSeconds(logStatisticsInterval)}`
+ )
+ } else if (this.displayInterval != null) {
+ logger.info(
+ `${this.logPrefix()} already logged every ${formatDurationSeconds(logStatisticsInterval)}`
+ )
+ } else if (logConfiguration.enabled === true) {
+ logger.info(
+ `${this.logPrefix()} log interval is set to ${logStatisticsInterval.toString()}. Not logging statistics`
+ )
+ }
+ }
+
+ private stopLogStatisticsInterval (): void {
+ if (this.displayInterval != null) {
+ clearInterval(this.displayInterval)
+ delete this.displayInterval
+ }
+ }
}
this.dbName = this.storageUri.pathname
}
- public storePerformanceStatistics (performanceStatistics: Statistics): void {
- this.setPerformanceStatistics(performanceStatistics)
- this.checkPerformanceRecordsFile()
- AsyncLock.runExclusive(AsyncLockType.performance, () => {
- writeSync(
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.fd!,
- JSONStringify([...this.getPerformanceStatistics()], 2, MapStringifyFormat.object),
- 0,
- 'utf8'
- )
- }).catch((error: unknown) => {
+ public close (): void {
+ this.clearPerformanceStatistics()
+ try {
+ if (this.fd != null) {
+ closeSync(this.fd)
+ delete this.fd
+ }
+ } catch (error) {
handleFileException(
this.dbName,
FileType.PerformanceRecords,
error as NodeJS.ErrnoException,
this.logPrefix
)
- })
+ }
}
public open (): void {
}
}
- public close (): void {
- this.clearPerformanceStatistics()
- try {
- if (this.fd != null) {
- closeSync(this.fd)
- delete this.fd
- }
- } catch (error) {
+ public storePerformanceStatistics (performanceStatistics: Statistics): void {
+ this.setPerformanceStatistics(performanceStatistics)
+ this.checkPerformanceRecordsFile()
+ AsyncLock.runExclusive(AsyncLockType.performance, () => {
+ writeSync(
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.fd!,
+ JSONStringify([...this.getPerformanceStatistics()], 2, MapStringifyFormat.object),
+ 0,
+ 'utf8'
+ )
+ }).catch((error: unknown) => {
handleFileException(
this.dbName,
FileType.PerformanceRecords,
error as NodeJS.ErrnoException,
this.logPrefix
)
- }
+ })
}
private checkPerformanceRecordsFile (): void {
// Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
-import { MikroORM as MariaDbORM, type Options as MariaDbOptions } from '@mikro-orm/mariadb'
-import { MikroORM as SqliteORM, type Options as SqliteOptions } from '@mikro-orm/sqlite'
+import { type Options as MariaDbOptions, MikroORM as MariaDbORM } from '@mikro-orm/mariadb'
+import { type Options as SqliteOptions, MikroORM as SqliteORM } from '@mikro-orm/sqlite'
import { type PerformanceRecord, type Statistics, StorageType } from '../../types/index.js'
import { Constants } from '../../utils/index.js'
import { Storage } from './Storage.js'
export class MikroOrmStorage extends Storage {
+ private orm?: MariaDbORM | SqliteORM
private readonly storageType: StorageType
- private orm?: SqliteORM | MariaDbORM
constructor (storageUri: string, logPrefix: string, storageType: StorageType) {
super(storageUri, logPrefix)
this.dbName = this.getDBName()
}
- public async storePerformanceStatistics (performanceStatistics: Statistics): Promise<void> {
+ public async close (): Promise<void> {
+ this.clearPerformanceStatistics()
try {
- this.setPerformanceStatistics(performanceStatistics)
- await this.orm?.em.upsert({
- ...performanceStatistics,
- statisticsData: Array.from(performanceStatistics.statisticsData, ([name, value]) => ({
- name,
- ...value
- }))
- } satisfies PerformanceRecord)
+ if (this.orm != null) {
+ await this.orm.close()
+ delete this.orm
+ }
} catch (error) {
- this.handleDBError(this.storageType, error as Error, Constants.PERFORMANCE_RECORDS_TABLE)
+ this.handleDBStorageError(this.storageType, error as Error)
}
}
try {
if (this.orm == null) {
switch (this.storageType) {
- case StorageType.SQLITE:
- this.orm = await SqliteORM.init(this.getOptions() as SqliteOptions)
- break
case StorageType.MARIA_DB:
case StorageType.MYSQL:
this.orm = await MariaDbORM.init(this.getOptions() as MariaDbOptions)
break
+ case StorageType.SQLITE:
+ this.orm = await SqliteORM.init(this.getOptions() as SqliteOptions)
+ break
}
}
} catch (error) {
- this.handleDBError(this.storageType, error as Error)
+ this.handleDBStorageError(this.storageType, error as Error)
}
}
- public async close (): Promise<void> {
- this.clearPerformanceStatistics()
+ public async storePerformanceStatistics (performanceStatistics: Statistics): Promise<void> {
try {
- if (this.orm != null) {
- await this.orm.close()
- delete this.orm
- }
+ this.setPerformanceStatistics(performanceStatistics)
+ await this.orm?.em.upsert({
+ ...performanceStatistics,
+ statisticsData: Array.from(performanceStatistics.statisticsData, ([name, value]) => ({
+ name,
+ ...value,
+ })),
+ } satisfies PerformanceRecord)
} catch (error) {
- this.handleDBError(this.storageType, error as Error)
+ this.handleDBStorageError(
+ this.storageType,
+ error as Error,
+ Constants.PERFORMANCE_RECORDS_TABLE
+ )
+ }
+ }
+
+ private getClientUrl (): string | undefined {
+ switch (this.storageType) {
+ case StorageType.MARIA_DB:
+ case StorageType.MYSQL:
+ case StorageType.SQLITE:
+ return this.storageUri.toString()
}
}
return this.storageUri.pathname.replace(/(?:^\/)|(?:\/$)/g, '')
}
- private getOptions (): SqliteOptions | MariaDbOptions {
+ private getOptions (): MariaDbOptions | SqliteOptions {
return {
+ clientUrl: this.getClientUrl(),
dbName: this.dbName,
entities: ['./dist/types/orm/entities/*.js'],
entitiesTs: ['./src/types/orm/entities/*.ts'],
- clientUrl: this.getClientUrl()
- }
- }
-
- private getClientUrl (): string | undefined {
- switch (this.storageType) {
- case StorageType.SQLITE:
- case StorageType.MARIA_DB:
- case StorageType.MYSQL:
- return this.storageUri.toString()
}
}
}
this.dbName = this.storageUri.pathname.replace(/(?:^\/)|(?:\/$)/g, '')
}
- public async storePerformanceStatistics (performanceStatistics: Statistics): Promise<void> {
+ public async close (): Promise<void> {
+ this.clearPerformanceStatistics()
try {
- this.setPerformanceStatistics(performanceStatistics)
- this.checkDBConnection()
- await this.client
- ?.db(this.dbName)
- .collection<Statistics>(Constants.PERFORMANCE_RECORDS_TABLE)
- .replaceOne({ id: performanceStatistics.id }, performanceStatistics, { upsert: true })
+ if (this.connected && this.client != null) {
+ await this.client.close()
+ this.connected = false
+ }
} catch (error) {
- this.handleDBError(StorageType.MONGO_DB, error as Error, Constants.PERFORMANCE_RECORDS_TABLE)
+ this.handleDBStorageError(StorageType.MONGO_DB, error as Error)
}
}
this.connected = true
}
} catch (error) {
- this.handleDBError(StorageType.MONGO_DB, error as Error)
+ this.handleDBStorageError(StorageType.MONGO_DB, error as Error)
}
}
- public async close (): Promise<void> {
- this.clearPerformanceStatistics()
+ public async storePerformanceStatistics (performanceStatistics: Statistics): Promise<void> {
try {
- if (this.connected && this.client != null) {
- await this.client.close()
- this.connected = false
- }
+ this.setPerformanceStatistics(performanceStatistics)
+ this.checkDBConnection()
+ await this.client
+ ?.db(this.dbName)
+ .collection<Statistics>(Constants.PERFORMANCE_RECORDS_TABLE)
+ .replaceOne({ id: performanceStatistics.id }, performanceStatistics, {
+ upsert: true,
+ })
} catch (error) {
- this.handleDBError(StorageType.MONGO_DB, error as Error)
+ this.handleDBStorageError(
+ StorageType.MONGO_DB,
+ error as Error,
+ Constants.PERFORMANCE_RECORDS_TABLE
+ )
}
}
private checkDBConnection (): void {
if (this.client == null) {
throw new BaseError(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`${this.logPrefix} ${this.getDBNameFromStorageType(
StorageType.MONGO_DB
)} client initialization failed while trying to issue a request`
}
if (!this.connected) {
throw new BaseError(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`${this.logPrefix} ${this.getDBNameFromStorageType(
StorageType.MONGO_DB
)} connection not opened while trying to issue a request`
// Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
import type { Statistics } from '../../types/index.js'
+
import { Storage } from './Storage.js'
export class None extends Storage {
super('none://none', 'none')
}
- public storePerformanceStatistics (performanceStatistics: Statistics): void {
- this.setPerformanceStatistics(performanceStatistics)
+ public close (): void {
+ this.clearPerformanceStatistics()
}
public open (): void {
/** Intentionally empty */
}
- public close (): void {
- this.clearPerformanceStatistics()
+ public storePerformanceStatistics (performanceStatistics: Statistics): void {
+ this.setPerformanceStatistics(performanceStatistics)
}
}
type EmptyObject,
type HandleErrorParams,
type Statistics,
- StorageType
+ StorageType,
} from '../../types/index.js'
-import { logger, setDefaultErrorParams } from '../../utils/index.js'
+import { logger } from '../../utils/index.js'
export abstract class Storage {
- protected readonly storageUri: URL
- protected readonly logPrefix: string
- protected dbName!: string
private static readonly performanceStatistics = new Map<string, Statistics>()
+ protected dbName!: string
+ protected readonly logPrefix: string
+ protected readonly storageUri: URL
constructor (storageUri: string, logPrefix: string) {
this.storageUri = new URL(storageUri)
this.logPrefix = logPrefix
}
- protected handleDBError (
+ public abstract close (): Promise<void> | void
+
+ public getPerformanceStatistics (): IterableIterator<Statistics> {
+ return Storage.performanceStatistics.values()
+ }
+
+ public abstract open (): Promise<void> | void
+
+ public abstract storePerformanceStatistics (
+ performanceStatistics: Statistics
+ ): Promise<void> | void
+
+ protected clearPerformanceStatistics (): void {
+ Storage.performanceStatistics.clear()
+ }
+
+ protected getDBNameFromStorageType (type: StorageType): DBName | undefined {
+ switch (type) {
+ case StorageType.MARIA_DB:
+ return DBName.MARIA_DB
+ case StorageType.MONGO_DB:
+ return DBName.MONGO_DB
+ case StorageType.MYSQL:
+ return DBName.MYSQL
+ case StorageType.SQLITE:
+ return DBName.SQLITE
+ }
+ }
+
+ protected handleDBStorageError (
type: StorageType,
error: Error,
table?: string,
- params: HandleErrorParams<EmptyObject> = { throwError: false, consoleOut: false }
+ params: HandleErrorParams<EmptyObject> = {
+ consoleOut: false,
+ throwError: false,
+ }
): void {
- setDefaultErrorParams(params, { throwError: false, consoleOut: false })
+ params = {
+ ...{
+ consoleOut: false,
+ throwError: false,
+ },
+ ...params,
+ }
const inTableOrCollectionStr = table != null && ` in table or collection '${table}'`
logger.error(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`${this.logPrefix} ${this.getDBNameFromStorageType(type)} error '${
error.message
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
}'${inTableOrCollectionStr}:`,
error
)
}
}
- protected getDBNameFromStorageType (type: StorageType): DBName | undefined {
- switch (type) {
- case StorageType.SQLITE:
- return DBName.SQLITE
- case StorageType.MARIA_DB:
- return DBName.MARIA_DB
- case StorageType.MYSQL:
- return DBName.MYSQL
- case StorageType.MONGO_DB:
- return DBName.MONGO_DB
- }
- }
-
- public getPerformanceStatistics (): IterableIterator<Statistics> {
- return Storage.performanceStatistics.values()
- }
-
protected setPerformanceStatistics (performanceStatistics: Statistics): void {
Storage.performanceStatistics.set(performanceStatistics.id, performanceStatistics)
}
-
- protected clearPerformanceStatistics (): void {
- Storage.performanceStatistics.clear()
- }
-
- public abstract open (): void | Promise<void>
- public abstract close (): void | Promise<void>
- public abstract storePerformanceStatistics (
- performanceStatistics: Statistics
- ): void | Promise<void>
}
// Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
+import type { Storage } from './Storage.js'
+
import { BaseError } from '../../exception/index.js'
import { StorageType } from '../../types/index.js'
import { JsonFileStorage } from './JsonFileStorage.js'
import { MikroOrmStorage } from './MikroOrmStorage.js'
import { MongoDBStorage } from './MongoDBStorage.js'
import { None } from './None.js'
-import type { Storage } from './Storage.js'
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class StorageFactory {
case StorageType.JSON_FILE:
storageInstance = new JsonFileStorage(connectionUri, logPrefix)
break
- case StorageType.MONGO_DB:
- storageInstance = new MongoDBStorage(connectionUri, logPrefix)
- break
- case StorageType.SQLITE:
case StorageType.MARIA_DB:
case StorageType.MYSQL:
+ case StorageType.SQLITE:
storageInstance = new MikroOrmStorage(connectionUri, logPrefix, type)
break
+ case StorageType.MONGO_DB:
+ storageInstance = new MongoDBStorage(connectionUri, logPrefix)
+ break
case StorageType.NONE:
storageInstance = new None()
break
-const fs = require('node:fs')
-
const { MongoClient } = require('mongodb')
+const fs = require('node:fs')
// This script deletes charging stations
// Filter charging stations by id pattern
// Mongo Connection and Query
if (config?.mongoConnectionString) {
- // eslint-disable-next-line n/handle-callback-err
- MongoClient.connect(config.mongoConnectionString, async function (_err, client) {
+ MongoClient.connect(config.mongoConnectionString, async (_err, client) => {
const db = client.db()
for await (const tenantID of config.tenantIDs) {
-const fs = require('node:fs')
-
const { MongoClient } = require('mongodb')
+const fs = require('node:fs')
// This script sets charging stations public or private
// Filter charging stations by id pattern
// Mongo Connection and Query
if (config?.mongoConnectionString) {
- // eslint-disable-next-line n/handle-callback-err
- MongoClient.connect(config.mongoConnectionString, async function (_err, client) {
+ MongoClient.connect(config.mongoConnectionString, async (_err, client) => {
const db = client.db()
for await (const tenantID of config.tenantIDs) {
import type { JsonObject } from './JsonType.js'
export enum IdTagDistribution {
+ CONNECTOR_AFFINITY = 'connector-affinity',
RANDOM = 'random',
ROUND_ROBIN = 'round-robin',
- CONNECTOR_AFFINITY = 'connector-affinity'
}
export interface AutomaticTransactionGeneratorConfiguration extends JsonObject {
enable: boolean
- minDuration: number
+ idTagDistribution?: IdTagDistribution
+ maxDelayBetweenTwoTransactions: number
maxDuration: number
minDelayBetweenTwoTransactions: number
- maxDelayBetweenTwoTransactions: number
+ minDuration: number
probabilityOfStart: number
- stopAfterHours: number
- stopAbsoluteDuration: boolean
requireAuthorize?: boolean
- idTagDistribution?: IdTagDistribution
+ stopAbsoluteDuration: boolean
+ stopAfterHours: number
+}
+
+export interface ChargingStationAutomaticTransactionGeneratorConfiguration {
+ automaticTransactionGenerator?: AutomaticTransactionGeneratorConfiguration
+ automaticTransactionGeneratorStatuses?: Status[]
}
export interface Status {
- start: boolean
- startDate?: Date
- lastRunDate?: Date
- stopDate?: Date
- stoppedDate?: Date
- authorizeRequests: number
acceptedAuthorizeRequests: number
- rejectedAuthorizeRequests: number
- startTransactionRequests: number
acceptedStartTransactionRequests: number
- rejectedStartTransactionRequests: number
- stopTransactionRequests: number
acceptedStopTransactionRequests: number
+ authorizeRequests: number
+ lastRunDate?: Date
+ rejectedAuthorizeRequests: number
+ rejectedStartTransactionRequests: number
rejectedStopTransactionRequests: number
skippedConsecutiveTransactions: number
skippedTransactions: number
-}
-
-export interface ChargingStationAutomaticTransactionGeneratorConfiguration {
- automaticTransactionGenerator?: AutomaticTransactionGeneratorConfiguration
- automaticTransactionGeneratorStatuses?: Status[]
+ start: boolean
+ startDate?: Date
+ startTransactionRequests: number
+ stopDate?: Date
+ stoppedDate?: Date
+ stopTransactionRequests: number
}
import type { ConnectorStatus } from './ConnectorStatus.js'
import type { EvseStatus } from './Evse.js'
-interface ConnectorsConfiguration {
+export type ChargingStationConfiguration =
+ ChargingStationAutomaticTransactionGeneratorConfiguration &
+ ChargingStationInfoConfiguration &
+ ChargingStationOcppConfiguration &
+ ConnectorsConfiguration &
+ EvsesConfiguration & {
+ configurationHash?: string
+ }
+
+export type EvseStatusConfiguration = Omit<EvseStatus, 'connectors'> & {
connectorsStatus?: ConnectorStatus[]
}
-export type EvseStatusConfiguration = Omit<EvseStatus, 'connectors'> & {
+interface ConnectorsConfiguration {
connectorsStatus?: ConnectorStatus[]
}
interface EvsesConfiguration {
evsesStatus?: EvseStatusConfiguration[]
}
-
-export type ChargingStationConfiguration = ChargingStationInfoConfiguration &
-ChargingStationOcppConfiguration &
-ChargingStationAutomaticTransactionGeneratorConfiguration &
-ConnectorsConfiguration &
-EvsesConfiguration & {
- configurationHash?: string
-}
export enum ChargingStationEvents {
+ accepted = 'accepted',
added = 'added',
+ connected = 'connected',
+ connectorStatusChanged = 'connectorStatusChanged',
deleted = 'deleted',
+ disconnected = 'disconnected',
+ pending = 'pending',
+ rejected = 'rejected',
started = 'started',
stopped = 'stopped',
updated = 'updated',
- registered = 'registered',
- accepted = 'accepted',
- rejected = 'rejected',
- disconnected = 'disconnected',
- connectorStatusChanged = 'connectorStatusChanged'
}
import type { FirmwareStatus } from './ocpp/Requests.js'
export type ChargingStationInfo = Omit<
-ChargingStationTemplate,
-| 'Connectors'
-| 'Evses'
-| 'Configuration'
-| 'AutomaticTransactionGenerator'
-| 'numberOfConnectors'
-| 'power'
-| 'powerUnit'
-| 'chargeBoxSerialNumberPrefix'
-| 'chargePointSerialNumberPrefix'
-| 'meterSerialNumberPrefix'
+ ChargingStationTemplate,
+ | 'AutomaticTransactionGenerator'
+ | 'chargeBoxSerialNumberPrefix'
+ | 'chargePointSerialNumberPrefix'
+ | 'Configuration'
+ | 'Connectors'
+ | 'Evses'
+ | 'meterSerialNumberPrefix'
+ | 'numberOfConnectors'
+ | 'power'
+ | 'powerUnit'
> & {
+ chargeBoxSerialNumber?: string
+ chargePointSerialNumber?: string
+ chargingStationId?: string
+ firmwareStatus?: FirmwareStatus
hashId: string
- templateIndex: number
- templateName: string
/** @deprecated Use `hashId` instead. */
infoHash?: string
- chargingStationId?: string
- chargeBoxSerialNumber?: string
- chargePointSerialNumber?: string
- meterSerialNumber?: string
- maximumPower?: number // Always in Watt
maximumAmperage?: number // Always in Ampere
- firmwareStatus?: FirmwareStatus
+ maximumPower?: number // Always in Watt
+ meterSerialNumber?: string
+ templateIndex: number
+ templateName: string
}
export interface ChargingStationInfoConfiguration {
import type { JsonObject } from './JsonType.js'
import type { OCPPConfigurationKey } from './ocpp/Configuration.js'
-export interface ConfigurationKey extends OCPPConfigurationKey {
- visible?: boolean
- reboot?: boolean
-}
-
export interface ChargingStationOcppConfiguration extends JsonObject {
configurationKey?: ConfigurationKey[]
}
+
+export interface ConfigurationKey extends OCPPConfigurationKey {
+ reboot?: boolean
+ visible?: boolean
+}
import type { ClientRequestArgs } from 'node:http'
-
import type { ClientOptions } from 'ws'
import type { AutomaticTransactionGeneratorConfiguration } from './AutomaticTransactionGenerator.js'
FirmwareStatus,
IncomingRequestCommand,
MessageTrigger,
- RequestCommand
+ RequestCommand,
} from './ocpp/Requests.js'
+export enum AmpereUnits {
+ AMPERE = 'A',
+ CENTI_AMPERE = 'cA',
+ DECI_AMPERE = 'dA',
+ MILLI_AMPERE = 'mA',
+}
+
export enum CurrentType {
AC = 'AC',
- DC = 'DC'
+ DC = 'DC',
}
export enum PowerUnits {
+ KILO_WATT = 'kW',
WATT = 'W',
- KILO_WATT = 'kW'
-}
-
-export enum AmpereUnits {
- MILLI_AMPERE = 'mA',
- CENTI_AMPERE = 'cA',
- DECI_AMPERE = 'dA',
- AMPERE = 'A'
}
export enum Voltage {
VOLTAGE_110 = 110,
VOLTAGE_230 = 230,
VOLTAGE_400 = 400,
- VOLTAGE_800 = 800
-}
-
-export type WsOptions = ClientOptions & ClientRequestArgs
-
-export interface FirmwareUpgrade extends JsonObject {
- versionUpgrade?: {
- patternGroup?: number
- step?: number
- }
- reset?: boolean
- failureStatus?: FirmwareStatus
-}
-
-interface CommandsSupport extends JsonObject {
- incomingCommands: Record<IncomingRequestCommand, boolean>
- outgoingCommands?: Record<RequestCommand, boolean>
+ VOLTAGE_800 = 800,
}
enum x509CertificateType {
- V2GRootCertificate = 'V2GRootCertificate',
- MORootCertificate = 'MORootCertificate',
+ ChargingStationCertificate = 'ChargingStationCertificate',
CSMSRootCertificate = 'CSMSRootCertificate',
ManufacturerRootCertificate = 'ManufacturerRootCertificate',
- ChargingStationCertificate = 'ChargingStationCertificate',
- V2GCertificate = 'V2GCertificate'
+ MORootCertificate = 'MORootCertificate',
+ V2GCertificate = 'V2GCertificate',
+ V2GRootCertificate = 'V2GRootCertificate',
}
export interface ChargingStationTemplate {
- templateHash?: string
- supervisionUrls?: string | string[]
- supervisionUrlOcppConfiguration?: boolean
- supervisionUrlOcppKey?: string
- supervisionUser?: string
- supervisionPassword?: string
- autoStart?: boolean
- ocppVersion?: OCPPVersion
- ocppProtocol?: OCPPProtocol
- ocppStrictCompliance?: boolean
- ocppPersistentConfiguration?: boolean
- stationInfoPersistentConfiguration?: boolean
+ amperageLimitationOcppKey?: string
+ amperageLimitationUnit?: AmpereUnits
+ AutomaticTransactionGenerator?: AutomaticTransactionGeneratorConfiguration
automaticTransactionGeneratorPersistentConfiguration?: boolean
- wsOptions?: WsOptions
- idTagsFile?: string
+ autoReconnectMaxRetries?: number
+ autoRegister?: boolean
+ autoStart?: boolean
baseName: string
- nameSuffix?: string
- fixedName?: boolean
+ beginEndMeterValues?: boolean
+ chargeBoxSerialNumberPrefix?: string
chargePointModel: string
- chargePointVendor: string
chargePointSerialNumberPrefix?: string
- chargeBoxSerialNumberPrefix?: string
- firmwareVersionPattern?: string
- firmwareVersion?: string
+ chargePointVendor: string
+ commandsSupport?: CommandsSupport
+ Configuration?: ChargingStationOcppConfiguration
+ Connectors?: Record<string, ConnectorStatus>
+ currentOutType?: CurrentType
+ customValueLimitationMeterValues?: boolean
+ enableStatistics?: boolean
+ Evses?: Record<string, EvseTemplate>
firmwareUpgrade?: FirmwareUpgrade
+ firmwareVersion?: string
+ firmwareVersionPattern?: string
+ fixedName?: boolean
iccid?: string
+ idTagsFile?: string
imsi?: string
+ mainVoltageMeterValues?: boolean
+ messageTriggerSupport?: Record<MessageTrigger, boolean>
+ meteringPerTransaction?: boolean
meterSerialNumberPrefix?: string
meterType?: string
+ /** @deprecated Replaced by remoteAuthorization. */
+ mustAuthorizeAtRemoteStart?: boolean
+ nameSuffix?: string
+ numberOfConnectors?: number | number[]
+ numberOfPhases?: number
+ ocppPersistentConfiguration?: boolean
+ ocppProtocol?: OCPPProtocol
+ ocppStrictCompliance?: boolean
+ ocppVersion?: OCPPVersion
+ outOfOrderEndMeterValues?: boolean
+ /** @deprecated Replaced by ocppStrictCompliance. */
+ payloadSchemaValidation?: boolean
+ phaseLineToLineVoltageMeterValues?: boolean
power?: number | number[]
- powerUnit?: PowerUnits
powerSharedByConnectors?: boolean
- currentOutType?: CurrentType
- voltageOut?: Voltage
- numberOfPhases?: number
- numberOfConnectors?: number | number[]
- useConnectorId0?: boolean
+ powerUnit?: PowerUnits
randomConnectors?: boolean
- resetTime?: number
- autoRegister?: boolean
- autoReconnectMaxRetries?: number
reconnectExponentialDelay?: boolean
registrationMaxRetries?: number
- enableStatistics?: boolean
remoteAuthorization?: boolean
- /** @deprecated Replaced by remoteAuthorization. */
- mustAuthorizeAtRemoteStart?: boolean
- /** @deprecated Replaced by ocppStrictCompliance. */
- payloadSchemaValidation?: boolean
- amperageLimitationOcppKey?: string
- amperageLimitationUnit?: AmpereUnits
- beginEndMeterValues?: boolean
- outOfOrderEndMeterValues?: boolean
- meteringPerTransaction?: boolean
- transactionDataMeterValues?: boolean
+ resetTime?: number
+ stationInfoPersistentConfiguration?: boolean
stopTransactionsOnStopped?: boolean
- mainVoltageMeterValues?: boolean
- phaseLineToLineVoltageMeterValues?: boolean
- customValueLimitationMeterValues?: boolean
- commandsSupport?: CommandsSupport
- messageTriggerSupport?: Record<MessageTrigger, boolean>
- Configuration?: ChargingStationOcppConfiguration
- AutomaticTransactionGenerator?: AutomaticTransactionGeneratorConfiguration
- Evses?: Record<string, EvseTemplate>
- Connectors?: Record<string, ConnectorStatus>
+ supervisionPassword?: string
+ supervisionUrlOcppConfiguration?: boolean
+ supervisionUrlOcppKey?: string
+ supervisionUrls?: string | string[]
+ supervisionUser?: string
+ templateHash?: string
+ transactionDataMeterValues?: boolean
+ useConnectorId0?: boolean
+ voltageOut?: Voltage
+ wsOptions?: WsOptions
x509Certificates?: Record<x509CertificateType, string>
}
+
+export interface FirmwareUpgrade extends JsonObject {
+ failureStatus?: FirmwareStatus
+ reset?: boolean
+ versionUpgrade?: {
+ patternGroup?: number
+ step?: number
+ }
+}
+
+export type WsOptions = ClientOptions & ClientRequestArgs
+
+interface CommandsSupport extends JsonObject {
+ incomingCommands: Record<IncomingRequestCommand, boolean>
+ outgoingCommands?: Record<RequestCommand, boolean>
+}
import type { WorkerData } from '../worker/index.js'
import type { ChargingStationAutomaticTransactionGeneratorConfiguration } from './AutomaticTransactionGenerator.js'
-import { ChargingStationEvents } from './ChargingStationEvents.js'
import type { ChargingStationInfo } from './ChargingStationInfo.js'
import type { ChargingStationOcppConfiguration } from './ChargingStationOcppConfiguration.js'
import type { ConnectorStatus } from './ConnectorStatus.js'
import type { BootNotificationResponse } from './ocpp/Responses.js'
import type { Statistics } from './Statistics.js'
+import { ChargingStationEvents } from './ChargingStationEvents.js'
+
+enum ChargingStationMessageEvents {
+ performanceStatistics = 'performanceStatistics',
+}
+
+export interface ChargingStationData extends WorkerData {
+ automaticTransactionGenerator?: ChargingStationAutomaticTransactionGeneratorConfiguration
+ bootNotificationResponse?: BootNotificationResponse
+ connectors: ConnectorStatus[]
+ evses: EvseStatusWorkerType[]
+ ocppConfiguration: ChargingStationOcppConfiguration
+ started: boolean
+ stationInfo: ChargingStationInfo
+ supervisionUrl: string
+ wsState?:
+ | typeof WebSocket.CLOSED
+ | typeof WebSocket.CLOSING
+ | typeof WebSocket.CONNECTING
+ | typeof WebSocket.OPEN
+}
+
export interface ChargingStationOptions extends JsonObject {
- supervisionUrls?: string | string[]
- persistentConfiguration?: boolean
- autoStart?: boolean
autoRegister?: boolean
+ autoStart?: boolean
enableStatistics?: boolean
ocppStrictCompliance?: boolean
+ persistentConfiguration?: boolean
stopTransactionsOnStopped?: boolean
+ supervisionUrls?: string | string[]
}
export interface ChargingStationWorkerData extends WorkerData {
index: number
- templateFile: string
options?: ChargingStationOptions
+ templateFile: string
}
-export type EvseStatusWorkerType = Omit<EvseStatus, 'connectors'> & {
- connectors?: ConnectorStatus[]
-}
-
-export interface ChargingStationData extends WorkerData {
- started: boolean
- stationInfo: ChargingStationInfo
- connectors: ConnectorStatus[]
- evses: EvseStatusWorkerType[]
- ocppConfiguration: ChargingStationOcppConfiguration
- supervisionUrl: string
- wsState?:
- | typeof WebSocket.CONNECTING
- | typeof WebSocket.OPEN
- | typeof WebSocket.CLOSING
- | typeof WebSocket.CLOSED
- bootNotificationResponse?: BootNotificationResponse
- automaticTransactionGenerator?: ChargingStationAutomaticTransactionGeneratorConfiguration
+export interface ChargingStationWorkerMessage<T extends ChargingStationWorkerMessageData> {
+ data: T
+ event: ChargingStationWorkerMessageEvents
}
-enum ChargingStationMessageEvents {
- performanceStatistics = 'performanceStatistics'
-}
+export type ChargingStationWorkerMessageData = ChargingStationData | Statistics
export const ChargingStationWorkerMessageEvents = {
...ChargingStationEvents,
- ...ChargingStationMessageEvents
+ ...ChargingStationMessageEvents,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type ChargingStationWorkerMessageEvents =
| ChargingStationEvents
| ChargingStationMessageEvents
-export type ChargingStationWorkerMessageData = ChargingStationData | Statistics
-
-export interface ChargingStationWorkerMessage<T extends ChargingStationWorkerMessageData> {
- event: ChargingStationWorkerMessageEvents
- data: T
+export type EvseStatusWorkerType = Omit<EvseStatus, 'connectors'> & {
+ connectors?: ConnectorStatus[]
}
import type { ListenOptions } from 'node:net'
import type { ResourceLimits } from 'node:worker_threads'
-
import type { WorkerChoiceStrategy } from 'poolifier'
import type { WorkerProcessType } from '../worker/index.js'
import type { StorageType } from './Storage.js'
import type { ApplicationProtocol, AuthenticationType } from './UIProtocol.js'
-type ServerOptions = ListenOptions
+export enum ApplicationProtocolVersion {
+ VERSION_11 = '1.1',
+ VERSION_20 = '2.0',
+}
export enum ConfigurationSection {
log = 'log',
performanceStorage = 'performanceStorage',
+ uiServer = 'uiServer',
worker = 'worker',
- uiServer = 'uiServer'
}
export enum SupervisionUrlDistribution {
- ROUND_ROBIN = 'round-robin',
+ CHARGING_STATION_AFFINITY = 'charging-station-affinity',
RANDOM = 'random',
- CHARGING_STATION_AFFINITY = 'charging-station-affinity'
+ ROUND_ROBIN = 'round-robin',
}
-export interface StationTemplateUrl {
- file: string
- numberOfStations: number
- provisionedNumberOfStations?: number
+export interface ConfigurationData {
+ /** @deprecated Moved to charging station template. */
+ autoReconnectMaxRetries?: number
+ /** @deprecated Moved to worker configuration section. */
+ chargingStationsPerWorker?: number
+ /** @deprecated Moved to worker configuration section. */
+ elementAddDelay?: number
+ log?: LogConfiguration
+ /** @deprecated Moved to log configuration section. */
+ logConsole?: boolean
+ /** @deprecated Moved to log configuration section. */
+ logEnabled?: boolean
+ /** @deprecated Moved to log configuration section. */
+ logErrorFile?: string
+ /** @deprecated Moved to log configuration section. */
+ logFile?: string
+ /** @deprecated Moved to log configuration section. */
+ logFormat?: string
+ /** @deprecated Moved to log configuration section. */
+ logLevel?: string
+ /** @deprecated Moved to log configuration section. */
+ logMaxFiles?: number | string
+ /** @deprecated Moved to log configuration section. */
+ logMaxSize?: number | string
+ /** @deprecated Moved to log configuration section. */
+ logRotate?: boolean
+ /** @deprecated Moved to log configuration section. */
+ logStatisticsInterval?: number
+ performanceStorage?: StorageConfiguration
+ stationTemplateUrls: StationTemplateUrl[]
+ supervisionUrlDistribution?: SupervisionUrlDistribution
+ supervisionUrls?: string | string[]
+ uiServer?: UIServerConfiguration
+ worker?: WorkerConfiguration
+ /** @deprecated Moved to worker configuration section. */
+ workerPoolMaxSize?: number
+ /** @deprecated Moved to worker configuration section. */
+ workerPoolMinSize?: number
+ /** @deprecated Moved to worker configuration section. */
+ workerPoolStrategy?: WorkerChoiceStrategy
+ /** @deprecated Moved to worker configuration section. */
+ workerProcess?: WorkerProcessType
+ /** @deprecated Moved to worker configuration section. */
+ workerStartDelay?: number
}
+export type ElementsPerWorkerType = 'all' | 'auto' | number
+
export interface LogConfiguration {
+ console?: boolean
enabled?: boolean
- file?: string
errorFile?: string
- statisticsInterval?: number
- level?: string
- console?: boolean
+ file?: string
format?: string
+ level?: string
+ maxFiles?: number | string
+ maxSize?: number | string
rotate?: boolean
- maxFiles?: string | number
- maxSize?: string | number
+ statisticsInterval?: number
}
-export enum ApplicationProtocolVersion {
- VERSION_11 = 1.1,
- VERSION_20 = 2.0
+export interface StationTemplateUrl {
+ file: string
+ numberOfStations: number
+ provisionedNumberOfStations?: number
}
-export interface UIServerConfiguration {
+export interface StorageConfiguration {
enabled?: boolean
- type?: ApplicationProtocol
- version?: ApplicationProtocolVersion
- options?: ServerOptions
+ type?: StorageType
+ uri?: string
+}
+
+export interface UIServerConfiguration {
authentication?: {
enabled: boolean
+ password?: string
type: AuthenticationType
username?: string
- password?: string
}
-}
-
-export interface StorageConfiguration {
enabled?: boolean
- type?: StorageType
- uri?: string
+ options?: ServerOptions
+ type?: ApplicationProtocol
+ version?: ApplicationProtocolVersion
}
-export type ElementsPerWorkerType = number | 'auto' | 'all'
-
export interface WorkerConfiguration {
- processType?: WorkerProcessType
- startDelay?: number
+ elementAddDelay?: number
elementsPerWorker?: ElementsPerWorkerType
/** @deprecated Use `elementAddDelay` instead. */
elementStartDelay?: number
- elementAddDelay?: number
- poolMinSize?: number
poolMaxSize?: number
+ poolMinSize?: number
+ processType?: WorkerProcessType
resourceLimits?: ResourceLimits
+ startDelay?: number
}
-export interface ConfigurationData {
- supervisionUrls?: string | string[]
- supervisionUrlDistribution?: SupervisionUrlDistribution
- stationTemplateUrls: StationTemplateUrl[]
- log?: LogConfiguration
- worker?: WorkerConfiguration
- uiServer?: UIServerConfiguration
- performanceStorage?: StorageConfiguration
- /** @deprecated Moved to charging station template. */
- autoReconnectMaxRetries?: number
- /** @deprecated Moved to worker configuration section. */
- workerProcess?: WorkerProcessType
- /** @deprecated Moved to worker configuration section. */
- workerStartDelay?: number
- /** @deprecated Moved to worker configuration section. */
- elementAddDelay?: number
- /** @deprecated Moved to worker configuration section. */
- workerPoolMinSize?: number
- /** @deprecated Moved to worker configuration section. */
- workerPoolMaxSize?: number
- /** @deprecated Moved to worker configuration section. */
- workerPoolStrategy?: WorkerChoiceStrategy
- /** @deprecated Moved to worker configuration section. */
- chargingStationsPerWorker?: number
- /** @deprecated Moved to log configuration section. */
- logStatisticsInterval?: number
- /** @deprecated Moved to log configuration section. */
- logEnabled?: boolean
- /** @deprecated Moved to log configuration section. */
- logConsole?: boolean
- /** @deprecated Moved to log configuration section. */
- logFormat?: string
- /** @deprecated Moved to log configuration section. */
- logLevel?: string
- /** @deprecated Moved to log configuration section. */
- logRotate?: boolean
- /** @deprecated Moved to log configuration section. */
- logMaxFiles?: number | string
- /** @deprecated Moved to log configuration section. */
- logMaxSize?: number | string
- /** @deprecated Moved to log configuration section. */
- logFile?: string
- /** @deprecated Moved to log configuration section. */
- logErrorFile?: string
-}
+type ServerOptions = ListenOptions
import type { Reservation } from './ocpp/Reservation.js'
export interface ConnectorStatus {
+ authorizeIdTag?: string
availability: AvailabilityType
bootStatus?: ConnectorStatusEnum
- status?: ConnectorStatusEnum
- MeterValues: SampledValueTemplate[]
- authorizeIdTag?: string
+ chargingProfiles?: ChargingProfile[]
+ energyActiveImportRegisterValue?: number // In Wh
idTagAuthorized?: boolean
- localAuthorizeIdTag?: string
idTagLocalAuthorized?: boolean
- transactionRemoteStarted?: boolean
- transactionStarted?: boolean
- transactionStart?: Date
+ localAuthorizeIdTag?: string
+ MeterValues: SampledValueTemplate[]
+ reservation?: Reservation
+ status?: ConnectorStatusEnum
+ transactionBeginMeterValue?: MeterValue
+ transactionEnergyActiveImportRegisterValue?: number // In Wh
transactionId?: number
- transactionSetInterval?: NodeJS.Timeout
transactionIdTag?: string
- energyActiveImportRegisterValue?: number // In Wh
- transactionEnergyActiveImportRegisterValue?: number // In Wh
- transactionBeginMeterValue?: MeterValue
- chargingProfiles?: ChargingProfile[]
- reservation?: Reservation
+ transactionRemoteStarted?: boolean
+ transactionSetInterval?: NodeJS.Timeout
+ transactionStart?: Date
+ transactionStarted?: boolean
}
import type { JsonType } from './JsonType.js'
export interface HandleErrorParams<T extends JsonType> {
- throwError?: boolean
consoleOut?: boolean
errorResponse?: T
+ throwError?: boolean
}
import type { ConnectorStatus } from './ConnectorStatus.js'
import type { AvailabilityType } from './ocpp/Requests.js'
-export interface EvseTemplate {
- Connectors: Record<string, ConnectorStatus>
-}
-
export interface EvseStatus {
- connectors: Map<number, ConnectorStatus>
availability: AvailabilityType
+ connectors: Map<number, ConnectorStatus>
+}
+
+export interface EvseTemplate {
+ Connectors: Record<string, ConnectorStatus>
}
export enum FileType {
Authorization = 'authorization',
- Configuration = 'configuration',
ChargingStationConfiguration = 'charging station configuration',
ChargingStationTemplate = 'charging station template',
+ Configuration = 'configuration',
+ JsonSchema = 'json schema',
PerformanceRecords = 'performance records',
- JsonSchema = 'json schema'
}
-type JsonPrimitive = string | number | boolean | Date | null
-
export type JsonObject = {
[key in string]?: JsonType
}
-export type JsonType = JsonPrimitive | JsonType[] | JsonObject
+export type JsonType = JsonObject | JsonPrimitive | JsonType[]
+
+type JsonPrimitive = boolean | Date | null | number | string
export enum MapStringifyFormat {
array = 'array',
- object = 'object'
+ object = 'object',
}
import type { SampledValue } from './ocpp/MeterValues.js'
-export interface SampledValueTemplate extends SampledValue {
- fluctuationPercent?: number
- minimumValue?: number
-}
-
export interface MeasurandPerPhaseSampledValueTemplates {
L1?: SampledValueTemplate
L2?: SampledValueTemplate
L3?: SampledValueTemplate
}
+
+export interface SampledValueTemplate extends SampledValue {
+ fluctuationPercent?: number
+ minimumValue?: number
+}
export interface MeasurandValues {
+ allPhases: number
L1: number
L2: number
L3: number
- allPhases: number
}
import type { TemplateStatistics } from './Statistics.js'
export interface SimulatorState {
- version: string
configuration: ConfigurationData | undefined
started: boolean
templateStatistics: Map<string, TemplateStatistics>
+ version: string
}
import type { WorkerData } from '../worker/index.js'
import type { IncomingRequestCommand, RequestCommand } from './ocpp/Requests.js'
-export interface TimestampedData {
- timestamp: number
- value: number
+export interface Statistics extends WorkerData {
+ createdAt: Date
+ id: string
+ name: string
+ statisticsData: Map<IncomingRequestCommand | RequestCommand | string, StatisticsData>
+ updatedAt?: Date
+ uri: string
}
export type StatisticsData = Partial<{
- requestCount: number
- responseCount: number
- errorCount: number
- timeMeasurementCount: number
- measurementTimeSeries: CircularBuffer<TimestampedData>
+ avgTimeMeasurement: number
currentTimeMeasurement: number
- minTimeMeasurement: number
+ errorCount: number
maxTimeMeasurement: number
- totalTimeMeasurement: number
- avgTimeMeasurement: number
+ measurementTimeSeries: CircularBuffer<TimestampedData> | TimestampedData[]
medTimeMeasurement: number
+ minTimeMeasurement: number
ninetyFiveThPercentileTimeMeasurement: number
- stdDevTimeMeasurement: number
+ requestCount: number
+ responseCount: number
+ stdTimeMeasurement: number
+ timeMeasurementCount: number
+ totalTimeMeasurement: number
}>
-export interface Statistics extends WorkerData {
- id: string
- name: string
- uri: string
- createdAt: Date
- updatedAt?: Date
- statisticsData: Map<string | RequestCommand | IncomingRequestCommand, StatisticsData>
-}
-
export interface TemplateStatistics {
+ added: number
configured: number
+ indexes: Set<number>
provisioned: number
- added: number
started: number
- indexes: Set<number>
+}
+
+export interface TimestampedData {
+ timestamp: number
+ value: number
}
+export enum DBName {
+ MARIA_DB = 'MariaDB',
+ MONGO_DB = 'MongoDB',
+ MYSQL = 'MySQL',
+ SQLITE = 'SQLite',
+}
+
export enum StorageType {
- NONE = 'none',
JSON_FILE = 'jsonfile',
+ MARIA_DB = 'mariadb',
MONGO_DB = 'mongodb',
MYSQL = 'mysql',
- MARIA_DB = 'mariadb',
- SQLITE = 'sqlite'
-}
-
-export enum DBName {
- MONGO_DB = 'MongoDB',
- MYSQL = 'MySQL',
- MARIA_DB = 'MariaDB',
- SQLITE = 'SQLite'
+ NONE = 'none',
+ SQLITE = 'sqlite',
}
import type { JsonObject } from './JsonType.js'
import type { BroadcastChannelResponsePayload } from './WorkerBroadcastChannel.js'
-export enum Protocol {
- UI = 'ui'
-}
-
export enum ApplicationProtocol {
HTTP = 'http',
- WS = 'ws'
+ WS = 'ws',
}
export enum AuthenticationType {
BASIC_AUTH = 'basic-auth',
- PROTOCOL_BASIC_AUTH = 'protocol-basic-auth'
+ PROTOCOL_BASIC_AUTH = 'protocol-basic-auth',
+}
+
+export enum ProcedureName {
+ ADD_CHARGING_STATIONS = 'addChargingStations',
+ AUTHORIZE = 'authorize',
+ BOOT_NOTIFICATION = 'bootNotification',
+ CLOSE_CONNECTION = 'closeConnection',
+ DATA_TRANSFER = 'dataTransfer',
+ DELETE_CHARGING_STATIONS = 'deleteChargingStations',
+ DIAGNOSTICS_STATUS_NOTIFICATION = 'diagnosticsStatusNotification',
+ FIRMWARE_STATUS_NOTIFICATION = 'firmwareStatusNotification',
+ HEARTBEAT = 'heartbeat',
+ LIST_CHARGING_STATIONS = 'listChargingStations',
+ LIST_TEMPLATES = 'listTemplates',
+ METER_VALUES = 'meterValues',
+ OPEN_CONNECTION = 'openConnection',
+ PERFORMANCE_STATISTICS = 'performanceStatistics',
+ SET_SUPERVISION_URL = 'setSupervisionUrl',
+ SIMULATOR_STATE = 'simulatorState',
+ START_AUTOMATIC_TRANSACTION_GENERATOR = 'startAutomaticTransactionGenerator',
+ START_CHARGING_STATION = 'startChargingStation',
+ START_SIMULATOR = 'startSimulator',
+ START_TRANSACTION = 'startTransaction',
+ STATUS_NOTIFICATION = 'statusNotification',
+ STOP_AUTOMATIC_TRANSACTION_GENERATOR = 'stopAutomaticTransactionGenerator',
+ STOP_CHARGING_STATION = 'stopChargingStation',
+ STOP_SIMULATOR = 'stopSimulator',
+ STOP_TRANSACTION = 'stopTransaction',
+}
+
+export enum Protocol {
+ UI = 'ui',
}
export enum ProtocolVersion {
- '0.0.1' = '0.0.1'
+ '0.0.1' = '0.0.1',
+}
+export enum ResponseStatus {
+ FAILURE = 'failure',
+ SUCCESS = 'success',
}
export type ProtocolRequest = [
ProcedureName,
RequestPayload
]
-export type ProtocolResponse = [
- `${string}-${string}-${string}-${string}-${string}`,
- ResponsePayload
-]
export type ProtocolRequestHandler = (
uuid?: `${string}-${string}-${string}-${string}-${string}`,
procedureName?: ProcedureName,
payload?: RequestPayload
-) => undefined | Promise<undefined> | ResponsePayload | Promise<ResponsePayload>
+) => Promise<ResponsePayload> | Promise<undefined> | ResponsePayload | undefined
-export enum ProcedureName {
- SIMULATOR_STATE = 'simulatorState',
- START_SIMULATOR = 'startSimulator',
- STOP_SIMULATOR = 'stopSimulator',
- LIST_TEMPLATES = 'listTemplates',
- LIST_CHARGING_STATIONS = 'listChargingStations',
- ADD_CHARGING_STATIONS = 'addChargingStations',
- DELETE_CHARGING_STATIONS = 'deleteChargingStations',
- PERFORMANCE_STATISTICS = 'performanceStatistics',
- START_CHARGING_STATION = 'startChargingStation',
- STOP_CHARGING_STATION = 'stopChargingStation',
- OPEN_CONNECTION = 'openConnection',
- CLOSE_CONNECTION = 'closeConnection',
- START_AUTOMATIC_TRANSACTION_GENERATOR = 'startAutomaticTransactionGenerator',
- STOP_AUTOMATIC_TRANSACTION_GENERATOR = 'stopAutomaticTransactionGenerator',
- SET_SUPERVISION_URL = 'setSupervisionUrl',
- START_TRANSACTION = 'startTransaction',
- STOP_TRANSACTION = 'stopTransaction',
- AUTHORIZE = 'authorize',
- BOOT_NOTIFICATION = 'bootNotification',
- STATUS_NOTIFICATION = 'statusNotification',
- HEARTBEAT = 'heartbeat',
- METER_VALUES = 'meterValues',
- DATA_TRANSFER = 'dataTransfer',
- DIAGNOSTICS_STATUS_NOTIFICATION = 'diagnosticsStatusNotification',
- FIRMWARE_STATUS_NOTIFICATION = 'firmwareStatusNotification'
-}
+export type ProtocolResponse = [
+ `${string}-${string}-${string}-${string}-${string}`,
+ ResponsePayload
+]
export interface RequestPayload extends JsonObject {
- hashIds?: string[]
connectorIds?: number[]
-}
-
-export enum ResponseStatus {
- SUCCESS = 'success',
- FAILURE = 'failure'
+ hashIds?: string[]
}
export interface ResponsePayload extends JsonObject {
- status: ResponseStatus
- hashIdsSucceeded?: string[]
hashIdsFailed?: string[]
+ hashIdsSucceeded?: string[]
responsesFailed?: BroadcastChannelResponsePayload[]
+ status: ResponseStatus
}
1012: 'Service Restart',
1013: 'Try Again Later',
1014: 'Bad Gateway',
- 1015: 'TLS Handshake'
+ 1015: 'TLS Handshake',
})
+/* eslint-disable perfectionist/sort-enums */
export enum WebSocketCloseEventStatusCode {
CLOSE_NORMAL = 1000,
CLOSE_GOING_AWAY = 1001,
CLOSE_SERVICE_RESTART = 1012,
CLOSE_TRY_AGAIN_LATER = 1013,
CLOSE_BAD_GATEWAY = 1014,
- CLOSE_TLS_HANDSHAKE = 1015
+ CLOSE_TLS_HANDSHAKE = 1015,
}
+/* eslint-enable perfectionist/sort-enums */
export interface WSError extends Error {
code?: string
import type { RequestPayload, ResponsePayload } from './UIProtocol.js'
-export type BroadcastChannelRequest = [
- `${string}-${string}-${string}-${string}-${string}`,
- BroadcastChannelProcedureName,
- BroadcastChannelRequestPayload
-]
-export type BroadcastChannelResponse = [
- `${string}-${string}-${string}-${string}-${string}`,
- BroadcastChannelResponsePayload
-]
-
export enum BroadcastChannelProcedureName {
- START_CHARGING_STATION = 'startChargingStation',
- STOP_CHARGING_STATION = 'stopChargingStation',
+ AUTHORIZE = 'authorize',
+ BOOT_NOTIFICATION = 'bootNotification',
+ CLOSE_CONNECTION = 'closeConnection',
+ DATA_TRANSFER = 'dataTransfer',
DELETE_CHARGING_STATIONS = 'deleteChargingStations',
+ DIAGNOSTICS_STATUS_NOTIFICATION = 'diagnosticsStatusNotification',
+ FIRMWARE_STATUS_NOTIFICATION = 'firmwareStatusNotification',
+ HEARTBEAT = 'heartbeat',
+ METER_VALUES = 'meterValues',
OPEN_CONNECTION = 'openConnection',
- CLOSE_CONNECTION = 'closeConnection',
- START_AUTOMATIC_TRANSACTION_GENERATOR = 'startAutomaticTransactionGenerator',
- STOP_AUTOMATIC_TRANSACTION_GENERATOR = 'stopAutomaticTransactionGenerator',
SET_SUPERVISION_URL = 'setSupervisionUrl',
+ START_AUTOMATIC_TRANSACTION_GENERATOR = 'startAutomaticTransactionGenerator',
+ START_CHARGING_STATION = 'startChargingStation',
START_TRANSACTION = 'startTransaction',
- STOP_TRANSACTION = 'stopTransaction',
- AUTHORIZE = 'authorize',
- BOOT_NOTIFICATION = 'bootNotification',
STATUS_NOTIFICATION = 'statusNotification',
- HEARTBEAT = 'heartbeat',
- METER_VALUES = 'meterValues',
- DATA_TRANSFER = 'dataTransfer',
- DIAGNOSTICS_STATUS_NOTIFICATION = 'diagnosticsStatusNotification',
- FIRMWARE_STATUS_NOTIFICATION = 'firmwareStatusNotification'
+ STOP_AUTOMATIC_TRANSACTION_GENERATOR = 'stopAutomaticTransactionGenerator',
+ STOP_CHARGING_STATION = 'stopChargingStation',
+ STOP_TRANSACTION = 'stopTransaction',
}
+export type BroadcastChannelRequest = [
+ `${string}-${string}-${string}-${string}-${string}`,
+ BroadcastChannelProcedureName,
+ BroadcastChannelRequestPayload
+]
+
export interface BroadcastChannelRequestPayload extends RequestPayload {
connectorId?: number
transactionId?: number
}
+export type BroadcastChannelResponse = [
+ `${string}-${string}-${string}-${string}-${string}`,
+ BroadcastChannelResponsePayload
+]
+
export interface BroadcastChannelResponsePayload
- extends Omit<ResponsePayload, 'hashIdsSucceeded' | 'hashIdsFailed' | 'responsesFailed'> {
+ extends Omit<ResponsePayload, 'hashIdsFailed' | 'hashIdsSucceeded' | 'responsesFailed'> {
hashId: string | undefined
}
type AutomaticTransactionGeneratorConfiguration,
type ChargingStationAutomaticTransactionGeneratorConfiguration,
IdTagDistribution,
- type Status
+ type Status,
} from './AutomaticTransactionGenerator.js'
export type {
ChargingStationConfiguration,
- EvseStatusConfiguration
+ EvseStatusConfiguration,
} from './ChargingStationConfiguration.js'
export { ChargingStationEvents } from './ChargingStationEvents.js'
export type { ChargingStationInfo } from './ChargingStationInfo.js'
export type {
ChargingStationOcppConfiguration,
- ConfigurationKey
+ ConfigurationKey,
} from './ChargingStationOcppConfiguration.js'
export {
AmpereUnits,
type FirmwareUpgrade,
PowerUnits,
Voltage,
- type WsOptions
+ type WsOptions,
} from './ChargingStationTemplate.js'
export {
type ChargingStationData,
type ChargingStationWorkerMessage,
type ChargingStationWorkerMessageData,
ChargingStationWorkerMessageEvents,
- type EvseStatusWorkerType
+ type EvseStatusWorkerType,
} from './ChargingStationWorker.js'
export {
ApplicationProtocolVersion,
type StorageConfiguration,
SupervisionUrlDistribution,
type UIServerConfiguration,
- type WorkerConfiguration
+ type WorkerConfiguration,
} from './ConfigurationData.js'
export type { ConnectorStatus } from './ConnectorStatus.js'
export type { EmptyObject } from './EmptyObject.js'
export { MapStringifyFormat } from './MapStringifyFormat.js'
export type {
MeasurandPerPhaseSampledValueTemplates,
- SampledValueTemplate
+ SampledValueTemplate,
} from './MeasurandPerPhaseSampledValueTemplates.js'
export type { MeasurandValues } from './MeasurandValues.js'
export { OCPP16ChargePointErrorCode } from './ocpp/1.6/ChargePointErrorCode.js'
OCPP16ChargingProfilePurposeType,
OCPP16ChargingRateUnitType,
type OCPP16ChargingSchedule,
- type OCPP16ChargingSchedulePeriod
+ type OCPP16ChargingSchedulePeriod,
} from './ocpp/1.6/ChargingProfile.js'
export {
OCPP16StandardParametersKey,
- OCPP16SupportedFeatureProfiles
+ OCPP16SupportedFeatureProfiles,
} from './ocpp/1.6/Configuration.js'
export { OCPP16DiagnosticsStatus } from './ocpp/1.6/DiagnosticsStatus.js'
export {
type OCPP16MeterValuesRequest,
type OCPP16MeterValuesResponse,
OCPP16MeterValueUnit,
- type OCPP16SampledValue
+ type OCPP16SampledValue,
} from './ocpp/1.6/MeterValues.js'
export {
type ChangeConfigurationRequest,
type OCPP16ClearCacheRequest,
type OCPP16ClearChargingProfileRequest,
type OCPP16DataTransferRequest,
- OCPP16DataTransferVendorId,
type OCPP16DiagnosticsStatusNotificationRequest,
OCPP16FirmwareStatus,
type OCPP16FirmwareStatusNotificationRequest,
type RemoteStopTransactionRequest,
type ResetRequest,
type SetChargingProfileRequest,
- type UnlockConnectorRequest
+ type UnlockConnectorRequest,
} from './ocpp/1.6/Requests.js'
export {
type ChangeConfigurationResponse,
OCPP16TriggerMessageStatus,
type OCPP16UpdateFirmwareResponse,
type SetChargingProfileResponse,
- type UnlockConnectorResponse
+ type UnlockConnectorResponse,
} from './ocpp/1.6/Responses.js'
export {
OCPP16AuthorizationStatus,
type OCPP16StartTransactionResponse,
OCPP16StopTransactionReason,
type OCPP16StopTransactionRequest,
- type OCPP16StopTransactionResponse
+ type OCPP16StopTransactionResponse,
} from './ocpp/1.6/Transaction.js'
export { BootReasonEnumType, OCPP20ConnectorStatusEnumType } from './ocpp/2.0/Common.js'
export {
type OCPP20HeartbeatRequest,
OCPP20IncomingRequestCommand,
OCPP20RequestCommand,
- type OCPP20StatusNotificationRequest
+ type OCPP20StatusNotificationRequest,
} from './ocpp/2.0/Requests.js'
export type {
OCPP20BootNotificationResponse,
OCPP20ClearCacheResponse,
OCPP20HeartbeatResponse,
- OCPP20StatusNotificationResponse
+ OCPP20StatusNotificationResponse,
} from './ocpp/2.0/Responses.js'
export { OCPP20OptionalVariableName } from './ocpp/2.0/Variables.js'
export { ChargePointErrorCode } from './ocpp/ChargePointErrorCode.js'
export {
type ChargingProfile,
ChargingProfileKindType,
+ ChargingProfilePurposeType,
ChargingRateUnitType,
type ChargingSchedulePeriod,
- RecurrencyKindType
+ RecurrencyKindType,
} from './ocpp/ChargingProfile.js'
export { type GenericResponse, GenericStatus, RegistrationStatusEnumType } from './ocpp/Common.js'
export {
type OCPPConfigurationKey,
StandardParametersKey,
SupportedFeatureProfiles,
- VendorParametersKey
+ VendorParametersKey,
} from './ocpp/Configuration.js'
export { ConnectorStatusEnum, type ConnectorStatusTransition } from './ocpp/ConnectorStatusEnum.js'
export { ErrorType } from './ocpp/ErrorType.js'
MeterValueMeasurand,
MeterValuePhase,
MeterValueUnit,
- type SampledValue
+ type SampledValue,
} from './ocpp/MeterValues.js'
export { OCPPVersion } from './ocpp/OCPPVersion.js'
export {
type RequestParams,
type ResponseCallback,
type ResponseType,
- type StatusNotificationRequest
+ type StatusNotificationRequest,
} from './ocpp/Requests.js'
export {
type Reservation,
type ReservationKey,
- ReservationTerminationReason
+ ReservationTerminationReason,
} from './ocpp/Reservation.js'
export {
AvailabilityStatus,
type ResponseHandler,
type StatusNotificationResponse,
TriggerMessageStatus,
- UnlockStatus
+ UnlockStatus,
} from './ocpp/Responses.js'
export {
AuthorizationStatus,
type StartTransactionResponse,
StopTransactionReason,
type StopTransactionRequest,
- type StopTransactionResponse
+ type StopTransactionResponse,
} from './ocpp/Transaction.js'
export { PerformanceRecord } from './orm/entities/PerformanceRecord.js'
export type { SimulatorState } from './SimulatorState.js'
Statistics,
StatisticsData,
TemplateStatistics,
- TimestampedData
+ TimestampedData,
} from './Statistics.js'
export { DBName, StorageType } from './Storage.js'
export {
ProtocolVersion,
type RequestPayload,
type ResponsePayload,
- ResponseStatus
+ ResponseStatus,
} from './UIProtocol.js'
export {
WebSocketCloseEventStatusCode,
WebSocketCloseEventStatusString,
- type WSError
+ type WSError,
} from './WebSocket.js'
export {
BroadcastChannelProcedureName,
type BroadcastChannelRequestPayload,
type BroadcastChannelResponse,
type BroadcastChannelResponsePayload,
- type MessageEvent
+ type MessageEvent,
} from './WorkerBroadcastChannel.js'
READER_FAILURE = 'ReaderFailure',
RESET_FAILURE = 'ResetFailure',
UNDER_VOLTAGE = 'UnderVoltage',
- WEAK_SIGNAL = 'WeakSignal'
+ WEAK_SIGNAL = 'WeakSignal',
}
export enum OCPP16ChargePointStatus {
Available = 'Available',
- Preparing = 'Preparing',
Charging = 'Charging',
- SuspendedEVSE = 'SuspendedEVSE',
- SuspendedEV = 'SuspendedEV',
+ Faulted = 'Faulted',
Finishing = 'Finishing',
+ Preparing = 'Preparing',
Reserved = 'Reserved',
+ SuspendedEV = 'SuspendedEV',
+ SuspendedEVSE = 'SuspendedEVSE',
Unavailable = 'Unavailable',
- Faulted = 'Faulted'
}
import type { JsonObject } from '../../JsonType.js'
+export enum OCPP16ChargingProfileKindType {
+ ABSOLUTE = 'Absolute',
+ RECURRING = 'Recurring',
+ RELATIVE = 'Relative',
+}
+
+export enum OCPP16ChargingProfilePurposeType {
+ CHARGE_POINT_MAX_PROFILE = 'ChargePointMaxProfile',
+ TX_DEFAULT_PROFILE = 'TxDefaultProfile',
+ TX_PROFILE = 'TxProfile',
+}
+
+export enum OCPP16ChargingRateUnitType {
+ AMPERE = 'A',
+ WATT = 'W',
+}
+
+export enum OCPP16RecurrencyKindType {
+ DAILY = 'Daily',
+ WEEKLY = 'Weekly',
+}
+
export interface OCPP16ChargingProfile extends JsonObject {
chargingProfileId: number
- transactionId?: number
- stackLevel: number
- chargingProfilePurpose: OCPP16ChargingProfilePurposeType
chargingProfileKind: OCPP16ChargingProfileKindType
+ chargingProfilePurpose: OCPP16ChargingProfilePurposeType
+ chargingSchedule: OCPP16ChargingSchedule
recurrencyKind?: OCPP16RecurrencyKindType
+ stackLevel: number
+ transactionId?: number
validFrom?: Date
validTo?: Date
- chargingSchedule: OCPP16ChargingSchedule
}
export interface OCPP16ChargingSchedule extends JsonObject {
- startSchedule?: Date
- duration?: number
chargingRateUnit: OCPP16ChargingRateUnitType
chargingSchedulePeriod: OCPP16ChargingSchedulePeriod[]
+ duration?: number
minChargeRate?: number
+ startSchedule?: Date
}
export interface OCPP16ChargingSchedulePeriod extends JsonObject {
- startPeriod: number
limit: number
numberPhases?: number
-}
-
-export enum OCPP16ChargingRateUnitType {
- WATT = 'W',
- AMPERE = 'A'
-}
-
-export enum OCPP16ChargingProfileKindType {
- ABSOLUTE = 'Absolute',
- RECURRING = 'Recurring',
- RELATIVE = 'Relative'
-}
-
-export enum OCPP16ChargingProfilePurposeType {
- CHARGE_POINT_MAX_PROFILE = 'ChargePointMaxProfile',
- TX_DEFAULT_PROFILE = 'TxDefaultProfile',
- TX_PROFILE = 'TxProfile'
-}
-
-export enum OCPP16RecurrencyKindType {
- DAILY = 'Daily',
- WEEKLY = 'Weekly'
+ startPeriod: number
}
-export enum OCPP16SupportedFeatureProfiles {
- Core = 'Core',
- FirmwareManagement = 'FirmwareManagement',
- LocalAuthListManagement = 'LocalAuthListManagement',
- Reservation = 'Reservation',
- SmartCharging = 'SmartCharging',
- RemoteTrigger = 'RemoteTrigger'
-}
-
export enum OCPP16StandardParametersKey {
AllowOfflineTxForUnknownId = 'AllowOfflineTxForUnknownId',
AuthorizationCacheEnabled = 'AuthorizationCacheEnabled',
AuthorizeRemoteTxRequests = 'AuthorizeRemoteTxRequests',
BlinkRepeat = 'BlinkRepeat',
+ ChargeProfileMaxStackLevel = 'ChargeProfileMaxStackLevel',
+ ChargingScheduleAllowedChargingRateUnit = 'ChargingScheduleAllowedChargingRateUnit',
+ ChargingScheduleMaxPeriods = 'ChargingScheduleMaxPeriods',
ClockAlignedDataInterval = 'ClockAlignedDataInterval',
ConnectionTimeOut = 'ConnectionTimeOut',
+ ConnectorPhaseRotation = 'ConnectorPhaseRotation',
+ ConnectorPhaseRotationMaxLength = 'ConnectorPhaseRotationMaxLength',
+ ConnectorSwitch3to1PhaseSupported = 'ConnectorSwitch3to1PhaseSupported',
GetConfigurationMaxKeys = 'GetConfigurationMaxKeys',
HeartbeatInterval = 'HeartbeatInterval',
HeartBeatInterval = 'HeartBeatInterval',
LightIntensity = 'LightIntensity',
+ LocalAuthListEnabled = 'LocalAuthListEnabled',
+ LocalAuthListMaxLength = 'LocalAuthListMaxLength',
LocalAuthorizeOffline = 'LocalAuthorizeOffline',
LocalPreAuthorize = 'LocalPreAuthorize',
+ MaxChargingProfilesInstalled = 'MaxChargingProfilesInstalled',
MaxEnergyOnInvalidId = 'MaxEnergyOnInvalidId',
MeterValuesAlignedData = 'MeterValuesAlignedData',
MeterValuesAlignedDataMaxLength = 'MeterValuesAlignedDataMaxLength',
+ MeterValueSampleInterval = 'MeterValueSampleInterval',
MeterValuesSampledData = 'MeterValuesSampledData',
MeterValuesSampledDataMaxLength = 'MeterValuesSampledDataMaxLength',
- MeterValueSampleInterval = 'MeterValueSampleInterval',
MinimumStatusDuration = 'MinimumStatusDuration',
NumberOfConnectors = 'NumberOfConnectors',
+ ReserveConnectorZeroSupported = 'ReserveConnectorZeroSupported',
ResetRetries = 'ResetRetries',
- ConnectorPhaseRotation = 'ConnectorPhaseRotation',
- ConnectorPhaseRotationMaxLength = 'ConnectorPhaseRotationMaxLength',
+ SendLocalListMaxLength = 'SendLocalListMaxLength',
StopTransactionOnEVSideDisconnect = 'StopTransactionOnEVSideDisconnect',
StopTransactionOnInvalidId = 'StopTransactionOnInvalidId',
StopTxnAlignedData = 'StopTxnAlignedData',
TransactionMessageRetryInterval = 'TransactionMessageRetryInterval',
UnlockConnectorOnEVSideDisconnect = 'UnlockConnectorOnEVSideDisconnect',
WebSocketPingInterval = 'WebSocketPingInterval',
- LocalAuthListEnabled = 'LocalAuthListEnabled',
- LocalAuthListMaxLength = 'LocalAuthListMaxLength',
- SendLocalListMaxLength = 'SendLocalListMaxLength',
- ReserveConnectorZeroSupported = 'ReserveConnectorZeroSupported',
- ChargeProfileMaxStackLevel = 'ChargeProfileMaxStackLevel',
- ChargingScheduleAllowedChargingRateUnit = 'ChargingScheduleAllowedChargingRateUnit',
- ChargingScheduleMaxPeriods = 'ChargingScheduleMaxPeriods',
- ConnectorSwitch3to1PhaseSupported = 'ConnectorSwitch3to1PhaseSupported',
- MaxChargingProfilesInstalled = 'MaxChargingProfilesInstalled'
+}
+
+export enum OCPP16SupportedFeatureProfiles {
+ Core = 'Core',
+ FirmwareManagement = 'FirmwareManagement',
+ LocalAuthListManagement = 'LocalAuthListManagement',
+ RemoteTrigger = 'RemoteTrigger',
+ Reservation = 'Reservation',
+ SmartCharging = 'SmartCharging',
}
export enum OCPP16VendorParametersKey {
- ConnectionUrl = 'ConnectionUrl'
+ ConnectionUrl = 'ConnectionUrl',
}
Idle = 'Idle',
Uploaded = 'Uploaded',
UploadFailed = 'UploadFailed',
- Uploading = 'Uploading'
+ Uploading = 'Uploading',
}
import type { EmptyObject } from '../../EmptyObject.js'
import type { JsonObject } from '../../JsonType.js'
-export enum OCPP16MeterValueUnit {
- WATT_HOUR = 'Wh',
- KILO_WATT_HOUR = 'kWh',
- VAR_HOUR = 'varh',
- KILO_VAR_HOUR = 'kvarh',
- WATT = 'W',
- KILO_WATT = 'kW',
- VOLT_AMP = 'VA',
- KILO_VOLT_AMP = 'kVA',
- VAR = 'var',
- KILO_VAR = 'kvar',
- AMP = 'A',
- VOLT = 'V',
- TEMP_CELSIUS = 'Celsius',
- TEMP_FAHRENHEIT = 'Fahrenheit',
- TEMP_KELVIN = 'K',
- PERCENT = 'Percent'
-}
-
export enum OCPP16MeterValueContext {
INTERRUPTION_BEGIN = 'Interruption.Begin',
INTERRUPTION_END = 'Interruption.End',
SAMPLE_PERIODIC = 'Sample.Periodic',
TRANSACTION_BEGIN = 'Transaction.Begin',
TRANSACTION_END = 'Transaction.End',
- TRIGGER = 'Trigger'
+ TRIGGER = 'Trigger',
+}
+
+export enum OCPP16MeterValueLocation {
+ BODY = 'Body',
+ CABLE = 'Cable',
+ EV = 'EV',
+ INLET = 'Inlet',
+ OUTLET = 'Outlet',
}
export enum OCPP16MeterValueMeasurand {
CURRENT_EXPORT = 'Current.Export',
CURRENT_IMPORT = 'Current.Import',
CURRENT_OFFERED = 'Current.Offered',
- ENERGY_ACTIVE_EXPORT_REGISTER = 'Energy.Active.Export.Register',
- ENERGY_ACTIVE_IMPORT_REGISTER = 'Energy.Active.Import.Register',
- ENERGY_REACTIVE_EXPORT_REGISTER = 'Energy.Reactive.Export.Register',
- ENERGY_REACTIVE_IMPORT_REGISTER = 'Energy.Reactive.Import.Register',
ENERGY_ACTIVE_EXPORT_INTERVAL = 'Energy.Active.Export.Interval',
+ ENERGY_ACTIVE_EXPORT_REGISTER = 'Energy.Active.Export.Register',
ENERGY_ACTIVE_IMPORT_INTERVAL = 'Energy.Active.Import.Interval',
+ ENERGY_ACTIVE_IMPORT_REGISTER = 'Energy.Active.Import.Register',
ENERGY_REACTIVE_EXPORT_INTERVAL = 'Energy.Reactive.Export.Interval',
+ ENERGY_REACTIVE_EXPORT_REGISTER = 'Energy.Reactive.Export.Register',
ENERGY_REACTIVE_IMPORT_INTERVAL = 'Energy.Reactive.Import.Interval',
+ ENERGY_REACTIVE_IMPORT_REGISTER = 'Energy.Reactive.Import.Register',
+ FAN_RPM = 'RPM',
FREQUENCY = 'Frequency',
POWER_ACTIVE_EXPORT = 'Power.Active.Export',
POWER_ACTIVE_IMPORT = 'Power.Active.Import',
POWER_OFFERED = 'Power.Offered',
POWER_REACTIVE_EXPORT = 'Power.Reactive.Export',
POWER_REACTIVE_IMPORT = 'Power.Reactive.Import',
- FAN_RPM = 'RPM',
STATE_OF_CHARGE = 'SoC',
TEMPERATURE = 'Temperature',
- VOLTAGE = 'Voltage'
-}
-
-export enum OCPP16MeterValueLocation {
- BODY = 'Body',
- CABLE = 'Cable',
- EV = 'EV',
- INLET = 'Inlet',
- OUTLET = 'Outlet'
+ VOLTAGE = 'Voltage',
}
export enum OCPP16MeterValuePhase {
L1 = 'L1',
- L2 = 'L2',
- L3 = 'L3',
- N = 'N',
+ L1_L2 = 'L1-L2',
L1_N = 'L1-N',
+ L2 = 'L2',
+ L2_L3 = 'L2-L3',
L2_N = 'L2-N',
+ L3 = 'L3',
+ L3_L1 = 'L3-L1',
L3_N = 'L3-N',
- L1_L2 = 'L1-L2',
- L2_L3 = 'L2-L3',
- L3_L1 = 'L3-L1'
+ N = 'N',
}
-enum OCPP16MeterValueFormat {
- RAW = 'Raw',
- SIGNED_DATA = 'SignedData'
+export enum OCPP16MeterValueUnit {
+ AMP = 'A',
+ KILO_VAR = 'kvar',
+ KILO_VAR_HOUR = 'kvarh',
+ KILO_VOLT_AMP = 'kVA',
+ KILO_WATT = 'kW',
+ KILO_WATT_HOUR = 'kWh',
+ PERCENT = 'Percent',
+ TEMP_CELSIUS = 'Celsius',
+ TEMP_FAHRENHEIT = 'Fahrenheit',
+ TEMP_KELVIN = 'K',
+ VAR = 'var',
+ VAR_HOUR = 'varh',
+ VOLT = 'V',
+ VOLT_AMP = 'VA',
+ WATT = 'W',
+ WATT_HOUR = 'Wh',
}
-export interface OCPP16SampledValue extends JsonObject {
- value: string
- unit?: OCPP16MeterValueUnit
- context?: OCPP16MeterValueContext
- measurand?: OCPP16MeterValueMeasurand
- phase?: OCPP16MeterValuePhase
- location?: OCPP16MeterValueLocation
- format?: OCPP16MeterValueFormat
+enum OCPP16MeterValueFormat {
+ RAW = 'Raw',
+ SIGNED_DATA = 'SignedData',
}
export interface OCPP16MeterValue extends JsonObject {
- timestamp: Date
sampledValue: OCPP16SampledValue[]
+ timestamp: Date
}
export interface OCPP16MeterValuesRequest extends JsonObject {
connectorId: number
- transactionId?: number
meterValue: OCPP16MeterValue[]
+ transactionId?: number
}
export type OCPP16MeterValuesResponse = EmptyObject
+
+export interface OCPP16SampledValue extends JsonObject {
+ context?: OCPP16MeterValueContext
+ format?: OCPP16MeterValueFormat
+ location?: OCPP16MeterValueLocation
+ measurand?: OCPP16MeterValueMeasurand
+ phase?: OCPP16MeterValuePhase
+ unit?: OCPP16MeterValueUnit
+ value: string
+}
import type {
OCPP16ChargingProfile,
OCPP16ChargingProfilePurposeType,
- OCPP16ChargingRateUnitType
+ OCPP16ChargingRateUnitType,
} from './ChargingProfile.js'
import type { OCPP16StandardParametersKey, OCPP16VendorParametersKey } from './Configuration.js'
import type { OCPP16DiagnosticsStatus } from './DiagnosticsStatus.js'
-export enum OCPP16RequestCommand {
- BOOT_NOTIFICATION = 'BootNotification',
- HEARTBEAT = 'Heartbeat',
- STATUS_NOTIFICATION = 'StatusNotification',
- AUTHORIZE = 'Authorize',
- START_TRANSACTION = 'StartTransaction',
- STOP_TRANSACTION = 'StopTransaction',
- METER_VALUES = 'MeterValues',
- DIAGNOSTICS_STATUS_NOTIFICATION = 'DiagnosticsStatusNotification',
- FIRMWARE_STATUS_NOTIFICATION = 'FirmwareStatusNotification',
- DATA_TRANSFER = 'DataTransfer'
+export enum OCPP16AvailabilityType {
+ Inoperative = 'Inoperative',
+ Operative = 'Operative',
+}
+
+export enum OCPP16FirmwareStatus {
+ Downloaded = 'Downloaded',
+ DownloadFailed = 'DownloadFailed',
+ Downloading = 'Downloading',
+ Idle = 'Idle',
+ InstallationFailed = 'InstallationFailed',
+ Installed = 'Installed',
+ Installing = 'Installing',
}
export enum OCPP16IncomingRequestCommand {
- RESET = 'Reset',
- CLEAR_CACHE = 'ClearCache',
+ CANCEL_RESERVATION = 'CancelReservation',
CHANGE_AVAILABILITY = 'ChangeAvailability',
- UNLOCK_CONNECTOR = 'UnlockConnector',
- GET_CONFIGURATION = 'GetConfiguration',
CHANGE_CONFIGURATION = 'ChangeConfiguration',
- GET_COMPOSITE_SCHEDULE = 'GetCompositeSchedule',
- SET_CHARGING_PROFILE = 'SetChargingProfile',
+ CLEAR_CACHE = 'ClearCache',
CLEAR_CHARGING_PROFILE = 'ClearChargingProfile',
+ DATA_TRANSFER = 'DataTransfer',
+ GET_COMPOSITE_SCHEDULE = 'GetCompositeSchedule',
+ GET_CONFIGURATION = 'GetConfiguration',
+ GET_DIAGNOSTICS = 'GetDiagnostics',
REMOTE_START_TRANSACTION = 'RemoteStartTransaction',
REMOTE_STOP_TRANSACTION = 'RemoteStopTransaction',
- GET_DIAGNOSTICS = 'GetDiagnostics',
+ RESERVE_NOW = 'ReserveNow',
+ RESET = 'Reset',
+ SET_CHARGING_PROFILE = 'SetChargingProfile',
TRIGGER_MESSAGE = 'TriggerMessage',
- DATA_TRANSFER = 'DataTransfer',
+ UNLOCK_CONNECTOR = 'UnlockConnector',
UPDATE_FIRMWARE = 'UpdateFirmware',
- RESERVE_NOW = 'ReserveNow',
- CANCEL_RESERVATION = 'CancelReservation'
}
-export type OCPP16HeartbeatRequest = EmptyObject
-
-export interface OCPP16BootNotificationRequest extends JsonObject {
- chargePointVendor: string
- chargePointModel: string
- chargePointSerialNumber?: string
- chargeBoxSerialNumber?: string
- firmwareVersion?: string
- iccid?: string
- imsi?: string
- meterType?: string
- meterSerialNumber?: string
+export enum OCPP16MessageTrigger {
+ BootNotification = 'BootNotification',
+ DiagnosticsStatusNotification = 'DiagnosticsStatusNotification',
+ FirmwareStatusNotification = 'FirmwareStatusNotification',
+ Heartbeat = 'Heartbeat',
+ MeterValues = 'MeterValues',
+ StatusNotification = 'StatusNotification',
}
-export interface OCPP16StatusNotificationRequest extends JsonObject {
- connectorId: number
- errorCode: OCPP16ChargePointErrorCode
- status: OCPP16ChargePointStatus
- info?: string
- timestamp?: Date
- vendorId?: string
- vendorErrorCode?: string
+export enum OCPP16RequestCommand {
+ AUTHORIZE = 'Authorize',
+ BOOT_NOTIFICATION = 'BootNotification',
+ DATA_TRANSFER = 'DataTransfer',
+ DIAGNOSTICS_STATUS_NOTIFICATION = 'DiagnosticsStatusNotification',
+ FIRMWARE_STATUS_NOTIFICATION = 'FirmwareStatusNotification',
+ HEARTBEAT = 'Heartbeat',
+ METER_VALUES = 'MeterValues',
+ START_TRANSACTION = 'StartTransaction',
+ STATUS_NOTIFICATION = 'StatusNotification',
+ STOP_TRANSACTION = 'StopTransaction',
}
-export type OCPP16ClearCacheRequest = EmptyObject
-
-type OCPP16ConfigurationKey = string | OCPP16StandardParametersKey | OCPP16VendorParametersKey
+enum ResetType {
+ HARD = 'Hard',
+ SOFT = 'Soft',
+}
export interface ChangeConfigurationRequest extends JsonObject {
key: OCPP16ConfigurationKey
value: string
}
-export interface RemoteStartTransactionRequest extends JsonObject {
- connectorId: number
- idTag: string
- chargingProfile?: OCPP16ChargingProfile
-}
-
-export interface RemoteStopTransactionRequest extends JsonObject {
- transactionId: number
-}
-
-export interface UnlockConnectorRequest extends JsonObject {
- connectorId: number
-}
-
export interface GetConfigurationRequest extends JsonObject {
key?: OCPP16ConfigurationKey[]
}
-enum ResetType {
- HARD = 'Hard',
- SOFT = 'Soft'
-}
-
-export interface ResetRequest extends JsonObject {
- type: ResetType
-}
-
-export interface OCPP16GetCompositeScheduleRequest extends JsonObject {
- connectorId: number
- duration: number
- chargingRateUnit?: OCPP16ChargingRateUnitType
+export interface GetDiagnosticsRequest extends JsonObject {
+ location: string
+ retries?: number
+ retryInterval?: number
+ startTime?: Date
+ stopTime?: Date
}
-export interface SetChargingProfileRequest extends JsonObject {
- connectorId: number
- csChargingProfiles: OCPP16ChargingProfile
+export interface OCPP16BootNotificationRequest extends JsonObject {
+ chargeBoxSerialNumber?: string
+ chargePointModel: string
+ chargePointSerialNumber?: string
+ chargePointVendor: string
+ firmwareVersion?: string
+ iccid?: string
+ imsi?: string
+ meterSerialNumber?: string
+ meterType?: string
}
-export enum OCPP16AvailabilityType {
- Inoperative = 'Inoperative',
- Operative = 'Operative'
+export interface OCPP16CancelReservationRequest extends JsonObject {
+ reservationId: number
}
export interface OCPP16ChangeAvailabilityRequest extends JsonObject {
type: OCPP16AvailabilityType
}
+export type OCPP16ClearCacheRequest = EmptyObject
+
export interface OCPP16ClearChargingProfileRequest extends JsonObject {
- id?: number
- connectorId?: number
chargingProfilePurpose?: OCPP16ChargingProfilePurposeType
+ connectorId?: number
+ id?: number
stackLevel?: number
}
-export interface OCPP16UpdateFirmwareRequest extends JsonObject {
- location: string
- retrieveDate: Date
- retries?: number
- retryInterval?: number
+export interface OCPP16DataTransferRequest extends JsonObject {
+ data?: string
+ messageId?: string
+ vendorId: string
}
-export enum OCPP16FirmwareStatus {
- Downloaded = 'Downloaded',
- DownloadFailed = 'DownloadFailed',
- Downloading = 'Downloading',
- Idle = 'Idle',
- InstallationFailed = 'InstallationFailed',
- Installing = 'Installing',
- Installed = 'Installed'
+export interface OCPP16DiagnosticsStatusNotificationRequest extends JsonObject {
+ status: OCPP16DiagnosticsStatus
}
export interface OCPP16FirmwareStatusNotificationRequest extends JsonObject {
status: OCPP16FirmwareStatus
}
-export interface GetDiagnosticsRequest extends JsonObject {
- location: string
- retries?: number
- retryInterval?: number
- startTime?: Date
- stopTime?: Date
+export interface OCPP16GetCompositeScheduleRequest extends JsonObject {
+ chargingRateUnit?: OCPP16ChargingRateUnitType
+ connectorId: number
+ duration: number
}
-export interface OCPP16DiagnosticsStatusNotificationRequest extends JsonObject {
- status: OCPP16DiagnosticsStatus
+export type OCPP16HeartbeatRequest = EmptyObject
+
+export interface OCPP16ReserveNowRequest extends JsonObject {
+ connectorId: number
+ expiryDate: Date
+ idTag: string
+ parentIdTag?: string
+ reservationId: number
}
-export enum OCPP16MessageTrigger {
- BootNotification = 'BootNotification',
- DiagnosticsStatusNotification = 'DiagnosticsStatusNotification',
- FirmwareStatusNotification = 'FirmwareStatusNotification',
- Heartbeat = 'Heartbeat',
- MeterValues = 'MeterValues',
- StatusNotification = 'StatusNotification'
+export interface OCPP16StatusNotificationRequest extends JsonObject {
+ connectorId: number
+ errorCode: OCPP16ChargePointErrorCode
+ info?: string
+ status: OCPP16ChargePointStatus
+ timestamp?: Date
+ vendorErrorCode?: string
+ vendorId?: string
}
export interface OCPP16TriggerMessageRequest extends JsonObject {
+ connectorId?: number
requestedMessage: OCPP16MessageTrigger
+}
+
+export interface OCPP16UpdateFirmwareRequest extends JsonObject {
+ location: string
+ retries?: number
+ retrieveDate: Date
+ retryInterval?: number
+}
+
+export interface RemoteStartTransactionRequest extends JsonObject {
+ chargingProfile?: OCPP16ChargingProfile
connectorId?: number
+ idTag: string
}
-export enum OCPP16DataTransferVendorId {}
+export interface RemoteStopTransactionRequest extends JsonObject {
+ transactionId: number
+}
-export interface OCPP16DataTransferRequest extends JsonObject {
- vendorId: string
- messageId?: string
- data?: string
+export interface ResetRequest extends JsonObject {
+ type: ResetType
}
-export interface OCPP16ReserveNowRequest extends JsonObject {
+export interface SetChargingProfileRequest extends JsonObject {
connectorId: number
- expiryDate: Date
- idTag: string
- parentIdTag?: string
- reservationId: number
+ csChargingProfiles: OCPP16ChargingProfile
}
-export interface OCPP16CancelReservationRequest extends JsonObject {
- reservationId: number
+export interface UnlockConnectorRequest extends JsonObject {
+ connectorId: number
}
+
+type OCPP16ConfigurationKey = OCPP16StandardParametersKey | OCPP16VendorParametersKey | string
import type { OCPPConfigurationKey } from '../Configuration.js'
import type { OCPP16ChargingSchedule } from './ChargingProfile.js'
-export interface OCPP16HeartbeatResponse extends JsonObject {
- currentTime: Date
+export enum OCPP16AvailabilityStatus {
+ ACCEPTED = 'Accepted',
+ REJECTED = 'Rejected',
+ SCHEDULED = 'Scheduled',
}
-export enum OCPP16UnlockStatus {
- UNLOCKED = 'Unlocked',
- UNLOCK_FAILED = 'UnlockFailed',
- NOT_SUPPORTED = 'NotSupported'
+export enum OCPP16ChargingProfileStatus {
+ ACCEPTED = 'Accepted',
+ NOT_SUPPORTED = 'NotSupported',
+ REJECTED = 'Rejected',
}
-export interface UnlockConnectorResponse extends JsonObject {
- status: OCPP16UnlockStatus
+export enum OCPP16ClearChargingProfileStatus {
+ ACCEPTED = 'Accepted',
+ UNKNOWN = 'Unknown',
}
export enum OCPP16ConfigurationStatus {
ACCEPTED = 'Accepted',
- REJECTED = 'Rejected',
+ NOT_SUPPORTED = 'NotSupported',
REBOOT_REQUIRED = 'RebootRequired',
- NOT_SUPPORTED = 'NotSupported'
+ REJECTED = 'Rejected',
}
-export interface ChangeConfigurationResponse extends JsonObject {
- status: OCPP16ConfigurationStatus
+export enum OCPP16DataTransferStatus {
+ ACCEPTED = 'Accepted',
+ REJECTED = 'Rejected',
+ UNKNOWN_MESSAGE_ID = 'UnknownMessageId',
+ UNKNOWN_VENDOR_ID = 'UnknownVendorId',
}
-export interface OCPP16BootNotificationResponse extends JsonObject {
- status: RegistrationStatusEnumType
- currentTime: Date
- interval: number
+export enum OCPP16ReservationStatus {
+ ACCEPTED = 'Accepted',
+ FAULTED = 'Faulted',
+ NOT_SUPPORTED = 'NotSupported',
+ OCCUPIED = 'Occupied',
+ REJECTED = 'Rejected',
+ UNAVAILABLE = 'Unavailable',
}
-export type OCPP16StatusNotificationResponse = EmptyObject
+export enum OCPP16TriggerMessageStatus {
+ ACCEPTED = 'Accepted',
+ NOT_IMPLEMENTED = 'NotImplemented',
+ REJECTED = 'Rejected',
+}
-export interface GetConfigurationResponse extends JsonObject {
- configurationKey: OCPPConfigurationKey[]
- unknownKey: string[]
+export enum OCPP16UnlockStatus {
+ NOT_SUPPORTED = 'NotSupported',
+ UNLOCK_FAILED = 'UnlockFailed',
+ UNLOCKED = 'Unlocked',
}
-export enum OCPP16ChargingProfileStatus {
- ACCEPTED = 'Accepted',
- REJECTED = 'Rejected',
- NOT_SUPPORTED = 'NotSupported'
+export interface ChangeConfigurationResponse extends JsonObject {
+ status: OCPP16ConfigurationStatus
}
-export interface OCPP16GetCompositeScheduleResponse extends JsonObject {
- status: GenericStatus
- connectorId?: number
- scheduleStart?: Date
- chargingSchedule?: OCPP16ChargingSchedule
+export interface GetConfigurationResponse extends JsonObject {
+ configurationKey: OCPPConfigurationKey[]
+ unknownKey: string[]
}
-export interface SetChargingProfileResponse extends JsonObject {
- status: OCPP16ChargingProfileStatus
+export interface GetDiagnosticsResponse extends JsonObject {
+ fileName?: string
}
-export enum OCPP16AvailabilityStatus {
- ACCEPTED = 'Accepted',
- REJECTED = 'Rejected',
- SCHEDULED = 'Scheduled'
+export interface OCPP16BootNotificationResponse extends JsonObject {
+ currentTime: Date
+ interval: number
+ status: RegistrationStatusEnumType
}
export interface OCPP16ChangeAvailabilityResponse extends JsonObject {
status: OCPP16AvailabilityStatus
}
-export enum OCPP16ClearChargingProfileStatus {
- ACCEPTED = 'Accepted',
- UNKNOWN = 'Unknown'
-}
-
export interface OCPP16ClearChargingProfileResponse extends JsonObject {
status: OCPP16ClearChargingProfileStatus
}
-export type OCPP16UpdateFirmwareResponse = EmptyObject
+export interface OCPP16DataTransferResponse extends JsonObject {
+ data?: string
+ status: OCPP16DataTransferStatus
+}
+
+export type OCPP16DiagnosticsStatusNotificationResponse = EmptyObject
export type OCPP16FirmwareStatusNotificationResponse = EmptyObject
-export interface GetDiagnosticsResponse extends JsonObject {
- fileName?: string
+export interface OCPP16GetCompositeScheduleResponse extends JsonObject {
+ chargingSchedule?: OCPP16ChargingSchedule
+ connectorId?: number
+ scheduleStart?: Date
+ status: GenericStatus
}
-export type OCPP16DiagnosticsStatusNotificationResponse = EmptyObject
+export interface OCPP16HeartbeatResponse extends JsonObject {
+ currentTime: Date
+}
-export enum OCPP16TriggerMessageStatus {
- ACCEPTED = 'Accepted',
- REJECTED = 'Rejected',
- NOT_IMPLEMENTED = 'NotImplemented'
+export interface OCPP16ReserveNowResponse extends JsonObject {
+ status: OCPP16ReservationStatus
}
+export type OCPP16StatusNotificationResponse = EmptyObject
+
export interface OCPP16TriggerMessageResponse extends JsonObject {
status: OCPP16TriggerMessageStatus
}
-export enum OCPP16DataTransferStatus {
- ACCEPTED = 'Accepted',
- REJECTED = 'Rejected',
- UNKNOWN_MESSAGE_ID = 'UnknownMessageId',
- UNKNOWN_VENDOR_ID = 'UnknownVendorId'
-}
-
-export interface OCPP16DataTransferResponse extends JsonObject {
- status: OCPP16DataTransferStatus
- data?: string
-}
+export type OCPP16UpdateFirmwareResponse = EmptyObject
-export enum OCPP16ReservationStatus {
- ACCEPTED = 'Accepted',
- FAULTED = 'Faulted',
- OCCUPIED = 'Occupied',
- REJECTED = 'Rejected',
- UNAVAILABLE = 'Unavailable',
- NOT_SUPPORTED = 'NotSupported'
+export interface SetChargingProfileResponse extends JsonObject {
+ status: OCPP16ChargingProfileStatus
}
-export interface OCPP16ReserveNowResponse extends JsonObject {
- status: OCPP16ReservationStatus
+export interface UnlockConnectorResponse extends JsonObject {
+ status: OCPP16UnlockStatus
}
import type { JsonObject } from '../../JsonType.js'
import type { OCPP16MeterValue } from './MeterValues.js'
+export enum OCPP16AuthorizationStatus {
+ ACCEPTED = 'Accepted',
+ BLOCKED = 'Blocked',
+ CONCURRENT_TX = 'ConcurrentTx',
+ EXPIRED = 'Expired',
+ INVALID = 'Invalid',
+}
+
export enum OCPP16StopTransactionReason {
+ DE_AUTHORIZED = 'DeAuthorized',
EMERGENCY_STOP = 'EmergencyStop',
EV_DISCONNECTED = 'EVDisconnected',
HARD_RESET = 'HardReset',
REMOTE = 'Remote',
SOFT_RESET = 'SoftReset',
UNLOCK_COMMAND = 'UnlockCommand',
- DE_AUTHORIZED = 'DeAuthorized'
-}
-
-export enum OCPP16AuthorizationStatus {
- ACCEPTED = 'Accepted',
- BLOCKED = 'Blocked',
- EXPIRED = 'Expired',
- INVALID = 'Invalid',
- CONCURRENT_TX = 'ConcurrentTx'
-}
-
-interface IdTagInfo extends JsonObject {
- status: OCPP16AuthorizationStatus
- parentIdTag?: string
- expiryDate?: Date
}
export interface OCPP16AuthorizeRequest extends JsonObject {
connectorId: number
idTag: string
meterStart: number
- timestamp: Date
reservationId?: number
+ timestamp: Date
}
export interface OCPP16StartTransactionResponse extends JsonObject {
export interface OCPP16StopTransactionRequest extends JsonObject {
idTag?: string
meterStop: number
- timestamp: Date
- transactionId: number
reason?: OCPP16StopTransactionReason
+ timestamp: Date
transactionData?: OCPP16MeterValue[]
+ transactionId: number
}
export interface OCPP16StopTransactionResponse extends JsonObject {
idTagInfo?: IdTagInfo
}
+
+interface IdTagInfo extends JsonObject {
+ expiryDate?: Date
+ parentIdTag?: string
+ status: OCPP16AuthorizationStatus
+}
import type { JsonObject } from '../../JsonType.js'
import type { GenericStatus } from '../Common.js'
-export enum DataEnumType {
- string = 'string',
- decimal = 'decimal',
- integer = 'integer',
- dateTime = 'dateTime',
- boolean = 'boolean',
- OptionList = 'OptionList',
- SequenceList = 'SequenceList',
- MemberList = 'MemberList'
-}
-
export enum BootReasonEnumType {
ApplicationReset = 'ApplicationReset',
FirmwareUpdate = 'FirmwareUpdate',
ScheduledReset = 'ScheduledReset',
Triggered = 'Triggered',
Unknown = 'Unknown',
- Watchdog = 'Watchdog'
+ Watchdog = 'Watchdog',
}
-export enum OperationalStatusEnumType {
- Operative = 'Operative',
- Inoperative = 'Inoperative'
+export enum CertificateActionEnumType {
+ Install = 'Install',
+ Update = 'Update',
}
-export enum OCPP20ConnectorStatusEnumType {
- Available = 'Available',
- Occupied = 'Occupied',
- Reserved = 'Reserved',
- Unavailable = 'Unavailable',
- Faulted = 'Faulted'
+export enum CertificateSigningUseEnumType {
+ ChargingStationCertificate = 'ChargingStationCertificate',
+ V2GCertificate = 'V2GCertificate',
}
-export type GenericStatusEnumType = GenericStatus
+export enum DataEnumType {
+ boolean = 'boolean',
+ dateTime = 'dateTime',
+ decimal = 'decimal',
+ integer = 'integer',
+ MemberList = 'MemberList',
+ OptionList = 'OptionList',
+ SequenceList = 'SequenceList',
+ string = 'string',
+}
-export enum HashAlgorithmEnumType {
- SHA256 = 'SHA256',
- SHA384 = 'SHA384',
- SHA512 = 'SHA512'
+export enum DeleteCertificateStatusEnumType {
+ Accepted = 'Accepted',
+ Failed = 'Failed',
+ NotFound = 'NotFound',
}
export enum GetCertificateIdUseEnumType {
- V2GRootCertificate = 'V2GRootCertificate',
- MORootCertificate = 'MORootCertificate',
CSMSRootCertificate = 'CSMSRootCertificate',
+ ManufacturerRootCertificate = 'ManufacturerRootCertificate',
+ MORootCertificate = 'MORootCertificate',
V2GCertificateChain = 'V2GCertificateChain',
- ManufacturerRootCertificate = 'ManufacturerRootCertificate'
+ V2GRootCertificate = 'V2GRootCertificate',
}
export enum GetCertificateStatusEnumType {
Accepted = 'Accepted',
- Failed = 'Failed'
+ Failed = 'Failed',
}
export enum GetInstalledCertificateStatusEnumType {
Accepted = 'Accepted',
- NotFound = 'NotFound'
+ NotFound = 'NotFound',
+}
+
+export enum HashAlgorithmEnumType {
+ SHA256 = 'SHA256',
+ SHA384 = 'SHA384',
+ SHA512 = 'SHA512',
}
export enum InstallCertificateStatusEnumType {
Accepted = 'Accepted',
+ Failed = 'Failed',
Rejected = 'Rejected',
- Failed = 'Failed'
}
export enum InstallCertificateUseEnumType {
- V2GRootCertificate = 'V2GRootCertificate',
- MORootCertificate = 'MORootCertificate',
CSMSRootCertificate = 'CSMSRootCertificate',
- ManufacturerRootCertificate = 'ManufacturerRootCertificate'
+ ManufacturerRootCertificate = 'ManufacturerRootCertificate',
+ MORootCertificate = 'MORootCertificate',
+ V2GRootCertificate = 'V2GRootCertificate',
}
-export enum DeleteCertificateStatusEnumType {
- Accepted = 'Accepted',
- Failed = 'Failed',
- NotFound = 'NotFound'
+export enum OCPP20ConnectorStatusEnumType {
+ Available = 'Available',
+ Faulted = 'Faulted',
+ Occupied = 'Occupied',
+ Reserved = 'Reserved',
+ Unavailable = 'Unavailable',
}
-export enum CertificateActionEnumType {
- Install = 'Install',
- Update = 'Update'
+export enum OperationalStatusEnumType {
+ Inoperative = 'Inoperative',
+ Operative = 'Operative',
}
-export enum CertificateSigningUseEnumType {
- ChargingStationCertificate = 'ChargingStationCertificate',
- V2GCertificate = 'V2GCertificate'
+export interface CertificateHashDataChainType extends JsonObject {
+ certificateHashData: CertificateHashDataType
+ certificateType: GetCertificateIdUseEnumType
+ childCertificateHashData?: CertificateHashDataType
}
-export type CertificateSignedStatusEnumType = GenericStatusEnumType
-
export interface CertificateHashDataType extends JsonObject {
hashAlgorithm: HashAlgorithmEnumType
- issuerNameHash: string
issuerKeyHash: string
+ issuerNameHash: string
serialNumber: string
}
-export interface CertificateHashDataChainType extends JsonObject {
- certificateType: GetCertificateIdUseEnumType
- certificateHashData: CertificateHashDataType
- childCertificateHashData?: CertificateHashDataType
+export type CertificateSignedStatusEnumType = GenericStatusEnumType
+
+export interface EVSEType extends JsonObject {
+ connectorId?: string
+ id: number
}
+export type GenericStatusEnumType = GenericStatus
+
export interface OCSPRequestDataType extends JsonObject {
hashAlgorithm: HashAlgorithmEnumType
- issuerNameHash: string
issuerKeyHash: string
- serialNumber: string
+ issuerNameHash: string
responderURL: string
+ serialNumber: string
}
export interface StatusInfoType extends JsonObject {
- reasonCode: string
additionalInfo?: string
-}
-
-export interface EVSEType extends JsonObject {
- id: number
- connectorId?: string
+ reasonCode: string
}
import type {
BootReasonEnumType,
InstallCertificateUseEnumType,
- OCPP20ConnectorStatusEnumType
+ OCPP20ConnectorStatusEnumType,
} from './Common.js'
import type { OCPP20SetVariableDataType } from './Variables.js'
-export enum OCPP20RequestCommand {
- BOOT_NOTIFICATION = 'BootNotification',
- HEARTBEAT = 'Heartbeat',
- STATUS_NOTIFICATION = 'StatusNotification'
-}
-
export enum OCPP20IncomingRequestCommand {
CLEAR_CACHE = 'ClearCache',
REQUEST_START_TRANSACTION = 'RequestStartTransaction',
- REQUEST_STOP_TRANSACTION = 'RequestStopTransaction'
+ REQUEST_STOP_TRANSACTION = 'RequestStopTransaction',
}
-interface ModemType extends JsonObject {
- iccid?: string
- imsi?: string
-}
-
-interface ChargingStationType extends JsonObject {
- serialNumber?: string
- model: string
- vendorName: string
- firmwareVersion?: string
- modem?: ModemType
+export enum OCPP20RequestCommand {
+ BOOT_NOTIFICATION = 'BootNotification',
+ HEARTBEAT = 'Heartbeat',
+ STATUS_NOTIFICATION = 'StatusNotification',
}
export interface OCPP20BootNotificationRequest extends JsonObject {
- reason: BootReasonEnumType
chargingStation: ChargingStationType
+ reason: BootReasonEnumType
}
+export type OCPP20ClearCacheRequest = EmptyObject
+
export type OCPP20HeartbeatRequest = EmptyObject
-export type OCPP20ClearCacheRequest = EmptyObject
+export interface OCPP20InstallCertificateRequest extends JsonObject {
+ certificate: string
+ certificateType: InstallCertificateUseEnumType
+}
+
+export interface OCPP20SetVariablesRequest extends JsonObject {
+ setVariableData: OCPP20SetVariableDataType[]
+}
export interface OCPP20StatusNotificationRequest extends JsonObject {
- timestamp: Date
+ connectorId: number
connectorStatus: OCPP20ConnectorStatusEnumType
evseId: number
- connectorId: number
+ timestamp: Date
}
-export interface OCPP20SetVariablesRequest extends JsonObject {
- setVariableData: OCPP20SetVariableDataType[]
+interface ChargingStationType extends JsonObject {
+ firmwareVersion?: string
+ model: string
+ modem?: ModemType
+ serialNumber?: string
+ vendorName: string
}
-export interface OCPP20InstallCertificateRequest extends JsonObject {
- certificateType: InstallCertificateUseEnumType
- certificate: string
+interface ModemType extends JsonObject {
+ iccid?: string
+ imsi?: string
}
import type {
GenericStatusEnumType,
InstallCertificateStatusEnumType,
- StatusInfoType
+ StatusInfoType,
} from './Common.js'
import type { OCPP20SetVariableResultType } from './Variables.js'
export interface OCPP20BootNotificationResponse extends JsonObject {
currentTime: Date
- status: RegistrationStatusEnumType
interval: number
+ status: RegistrationStatusEnumType
statusInfo?: StatusInfoType
}
-export interface OCPP20HeartbeatResponse extends JsonObject {
- currentTime: Date
-}
-
export interface OCPP20ClearCacheResponse extends JsonObject {
status: GenericStatusEnumType
statusInfo?: StatusInfoType
}
-export type OCPP20StatusNotificationResponse = EmptyObject
-
-export interface OCPP20SetVariablesResponse extends JsonObject {
- setVariableResult: OCPP20SetVariableResultType[]
+export interface OCPP20HeartbeatResponse extends JsonObject {
+ currentTime: Date
}
export interface OCPP20InstallCertificateResponse extends JsonObject {
status: InstallCertificateStatusEnumType
statusInfo?: StatusInfoType
}
+
+export interface OCPP20SetVariablesResponse extends JsonObject {
+ setVariableResult: OCPP20SetVariableResultType[]
+}
+
+export type OCPP20StatusNotificationResponse = EmptyObject
import type { JsonObject } from '../../JsonType.js'
import type { EVSEType, StatusInfoType } from './Common.js'
-enum OCPP20ComponentName {
- AlignedDataCtrlr = 'AlignedDataCtrlr',
- AuthCacheCtrlr = 'AuthCacheCtrlr',
- AuthCtrlr = 'AuthCtrlr',
- CHAdeMOCtrlr = 'CHAdeMOCtrlr',
- ClockCtrlr = 'ClockCtrlr',
- CustomizationCtrlr = 'CustomizationCtrlr',
- DeviceDataCtrlr = 'DeviceDataCtrlr',
- DisplayMessageCtrlr = 'DisplayMessageCtrlr',
- ISO15118Ctrlr = 'ISO15118Ctrlr',
- LocalAuthListCtrlr = 'LocalAuthListCtrlr',
- MonitoringCtrlr = 'MonitoringCtrlr',
- OCPPCommCtrlr = 'OCPPCommCtrlr',
- ReservationCtrlr = 'ReservationCtrlr',
- SampledDataCtrlr = 'SampledDataCtrlr',
- SecurityCtrlr = 'SecurityCtrlr',
- SmartChargingCtrlr = 'SmartChargingCtrlr',
- TariffCostCtrlr = 'TariffCostCtrlr',
- TxCtrlr = 'TxCtrlr'
+export enum OCPP20OptionalVariableName {
+ HeartbeatInterval = 'HeartbeatInterval',
+ WebSocketPingInterval = 'WebSocketPingInterval',
}
export enum OCPP20RequiredVariableName {
- MessageTimeout = 'MessageTimeout',
+ AuthorizeRemoteStart = 'AuthorizeRemoteStart',
+ BytesPerMessage = 'BytesPerMessage',
+ CertificateEntries = 'CertificateEntries',
+ DateTime = 'DateTime',
+ EVConnectionTimeOut = 'EVConnectionTimeOut',
FileTransferProtocols = 'FileTransferProtocols',
+ ItemsPerMessage = 'ItemsPerMessage',
+ LocalAuthorizeOffline = 'LocalAuthorizeOffline',
+ LocalPreAuthorize = 'LocalPreAuthorize',
+ MessageAttemptInterval = 'MessageAttemptInterval',
+ MessageAttempts = 'TransactionEvent',
+ MessageTimeout = 'MessageTimeout',
NetworkConfigurationPriority = 'NetworkConfigurationPriority',
NetworkProfileConnectionAttempts = 'NetworkProfileConnectionAttempts',
OfflineThreshold = 'OfflineThreshold',
- MessageAttempts = 'TransactionEvent',
- MessageAttemptInterval = 'MessageAttemptInterval',
- UnlockOnEVSideDisconnect = 'UnlockOnEVSideDisconnect',
- ResetRetries = 'ResetRetries',
- ItemsPerMessage = 'ItemsPerMessage',
- BytesPerMessage = 'BytesPerMessage',
- DateTime = 'DateTime',
- TimeSource = 'TimeSource',
OrganizationName = 'OrganizationName',
- CertificateEntries = 'CertificateEntries',
+ ResetRetries = 'ResetRetries',
SecurityProfile = 'SecurityProfile',
- AuthorizeRemoteStart = 'AuthorizeRemoteStart',
- LocalAuthorizeOffline = 'LocalAuthorizeOffline',
- LocalPreAuthorize = 'LocalPreAuthorize',
- EVConnectionTimeOut = 'EVConnectionTimeOut',
StopTxOnEVSideDisconnect = 'StopTxOnEVSideDisconnect',
- TxStartPoint = 'TxStartPoint',
- TxStopPoint = 'TxStopPoint',
StopTxOnInvalidId = 'StopTxOnInvalidId',
+ TimeSource = 'TimeSource',
TxEndedMeasurands = 'TxEndedMeasurands',
TxStartedMeasurands = 'TxStartedMeasurands',
+ TxStartPoint = 'TxStartPoint',
+ TxStopPoint = 'TxStopPoint',
+ TxUpdatedInterval = 'TxUpdatedInterval',
TxUpdatedMeasurands = 'TxUpdatedMeasurands',
- TxUpdatedInterval = 'TxUpdatedInterval'
-}
-
-export enum OCPP20OptionalVariableName {
- HeartbeatInterval = 'HeartbeatInterval',
- WebSocketPingInterval = 'WebSocketPingInterval'
+ UnlockOnEVSideDisconnect = 'UnlockOnEVSideDisconnect',
}
export enum OCPP20VendorVariableName {
- ConnectionUrl = 'ConnectionUrl'
+ ConnectionUrl = 'ConnectionUrl',
}
enum AttributeEnumType {
Actual = 'Actual',
- Target = 'Target',
+ MaxSet = 'MaxSet',
MinSet = 'MinSet',
- MaxSet = 'MaxSet'
+ Target = 'Target',
}
-interface ComponentType extends JsonObject {
- name: string | OCPP20ComponentName
- instance?: string
- evse?: EVSEType
+enum OCPP20ComponentName {
+ AlignedDataCtrlr = 'AlignedDataCtrlr',
+ AuthCacheCtrlr = 'AuthCacheCtrlr',
+ AuthCtrlr = 'AuthCtrlr',
+ CHAdeMOCtrlr = 'CHAdeMOCtrlr',
+ ClockCtrlr = 'ClockCtrlr',
+ CustomizationCtrlr = 'CustomizationCtrlr',
+ DeviceDataCtrlr = 'DeviceDataCtrlr',
+ DisplayMessageCtrlr = 'DisplayMessageCtrlr',
+ ISO15118Ctrlr = 'ISO15118Ctrlr',
+ LocalAuthListCtrlr = 'LocalAuthListCtrlr',
+ MonitoringCtrlr = 'MonitoringCtrlr',
+ OCPPCommCtrlr = 'OCPPCommCtrlr',
+ ReservationCtrlr = 'ReservationCtrlr',
+ SampledDataCtrlr = 'SampledDataCtrlr',
+ SecurityCtrlr = 'SecurityCtrlr',
+ SmartChargingCtrlr = 'SmartChargingCtrlr',
+ TariffCostCtrlr = 'TariffCostCtrlr',
+ TxCtrlr = 'TxCtrlr',
}
-type VariableName =
- | string
- | OCPP20RequiredVariableName
- | OCPP20OptionalVariableName
- | OCPP20VendorVariableName
+enum SetVariableStatusEnumType {
+ Accepted = 'Accepted',
+ NotSupportedAttributeType = 'NotSupportedAttributeType',
+ RebootRequired = 'RebootRequired',
+ Rejected = 'Rejected',
+ UnknownComponent = 'UnknownComponent',
+ UnknownVariable = 'UnknownVariable',
+}
-interface VariableType extends JsonObject {
- name: VariableName
- instance?: string
+export interface OCPP20ComponentVariableType extends JsonObject {
+ component: ComponentType
+ variable?: VariableType
}
export interface OCPP20SetVariableDataType extends JsonObject {
variable: VariableType
}
-enum SetVariableStatusEnumType {
- Accepted = 'Accepted',
- Rejected = 'Rejected',
- UnknownComponent = 'UnknownComponent',
- UnknownVariable = 'UnknownVariable',
- NotSupportedAttributeType = 'NotSupportedAttributeType',
- RebootRequired = 'RebootRequired'
-}
-
export interface OCPP20SetVariableResultType extends JsonObject {
- attributeType?: AttributeEnumType
attributeStatus: SetVariableStatusEnumType
+ attributeStatusInfo?: StatusInfoType
+ attributeType?: AttributeEnumType
component: ComponentType
variable: VariableType
- attributeStatusInfo?: StatusInfoType
}
-export interface OCPP20ComponentVariableType extends JsonObject {
- component: ComponentType
- variable?: VariableType
+interface ComponentType extends JsonObject {
+ evse?: EVSEType
+ instance?: string
+ name: OCPP20ComponentName | string
+}
+
+type VariableName =
+ | OCPP20OptionalVariableName
+ | OCPP20RequiredVariableName
+ | OCPP20VendorVariableName
+ | string
+
+interface VariableType extends JsonObject {
+ instance?: string
+ name: VariableName
}
import { OCPP16ChargePointErrorCode } from './1.6/ChargePointErrorCode.js'
export const ChargePointErrorCode = {
- ...OCPP16ChargePointErrorCode
+ ...OCPP16ChargePointErrorCode,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type ChargePointErrorCode = OCPP16ChargePointErrorCode
import {
type OCPP16ChargingProfile,
OCPP16ChargingProfileKindType,
+ OCPP16ChargingProfilePurposeType,
OCPP16ChargingRateUnitType,
type OCPP16ChargingSchedulePeriod,
- OCPP16RecurrencyKindType
+ OCPP16RecurrencyKindType,
} from './1.6/ChargingProfile.js'
export type ChargingProfile = OCPP16ChargingProfile
export type ChargingSchedulePeriod = OCPP16ChargingSchedulePeriod
+export const ChargingProfilePurposeType = {
+ ...OCPP16ChargingProfilePurposeType,
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type ChargingProfilePurposeType = OCPP16ChargingProfilePurposeType
+
export const ChargingProfileKindType = {
- ...OCPP16ChargingProfileKindType
+ ...OCPP16ChargingProfileKindType,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type ChargingProfileKindType = OCPP16ChargingProfileKindType
export const RecurrencyKindType = {
- ...OCPP16RecurrencyKindType
+ ...OCPP16RecurrencyKindType,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type RecurrencyKindType = OCPP16RecurrencyKindType
export const ChargingRateUnitType = {
- ...OCPP16ChargingRateUnitType
+ ...OCPP16ChargingRateUnitType,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type ChargingRateUnitType = OCPP16ChargingRateUnitType
export enum GenericStatus {
Accepted = 'Accepted',
- Rejected = 'Rejected'
-}
-
-export interface GenericResponse extends JsonObject {
- status: GenericStatus
+ Rejected = 'Rejected',
}
export enum RegistrationStatusEnumType {
ACCEPTED = 'Accepted',
PENDING = 'Pending',
- REJECTED = 'Rejected'
+ REJECTED = 'Rejected',
+}
+
+export interface GenericResponse extends JsonObject {
+ status: GenericStatus
}
import type { JsonObject } from '../JsonType.js'
+
import {
OCPP16StandardParametersKey,
OCPP16SupportedFeatureProfiles,
- OCPP16VendorParametersKey
+ OCPP16VendorParametersKey,
} from './1.6/Configuration.js'
import {
OCPP20OptionalVariableName,
OCPP20RequiredVariableName,
- OCPP20VendorVariableName
+ OCPP20VendorVariableName,
} from './2.0/Variables.js'
+export enum ConnectorPhaseRotation {
+ NotApplicable = 'NotApplicable',
+ RST = 'RST',
+ RTS = 'RTS',
+ SRT = 'SRT',
+ STR = 'STR',
+ TRS = 'TRS',
+ TSR = 'TSR',
+ Unknown = 'Unknown',
+}
+
+export type ConfigurationKeyType = StandardParametersKey | string | VendorParametersKey
+
+export interface OCPPConfigurationKey extends JsonObject {
+ key: ConfigurationKeyType
+ readonly: boolean
+ value?: string
+}
+
export const StandardParametersKey = {
...OCPP16StandardParametersKey,
...OCPP20RequiredVariableName,
- ...OCPP20OptionalVariableName
+ ...OCPP20OptionalVariableName,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type StandardParametersKey = OCPP16StandardParametersKey
export const VendorParametersKey = {
...OCPP16VendorParametersKey,
- ...OCPP20VendorVariableName
+ ...OCPP20VendorVariableName,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type VendorParametersKey = OCPP16VendorParametersKey
export const SupportedFeatureProfiles = {
- ...OCPP16SupportedFeatureProfiles
+ ...OCPP16SupportedFeatureProfiles,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type SupportedFeatureProfiles = OCPP16SupportedFeatureProfiles
-
-export enum ConnectorPhaseRotation {
- NotApplicable = 'NotApplicable',
- Unknown = 'Unknown',
- RST = 'RST',
- RTS = 'RTS',
- SRT = 'SRT',
- STR = 'STR',
- TRS = 'TRS',
- TSR = 'TSR'
-}
-
-export type ConfigurationKeyType = string | StandardParametersKey | VendorParametersKey
-
-export interface OCPPConfigurationKey extends JsonObject {
- key: ConfigurationKeyType
- readonly: boolean
- value?: string
-}
export const ConnectorStatusEnum = {
...OCPP16ChargePointStatus,
- ...OCPP20ConnectorStatusEnumType
+ ...OCPP20ConnectorStatusEnumType,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type ConnectorStatusEnum = OCPP16ChargePointStatus | OCPP20ConnectorStatusEnumType
export enum ErrorType {
+ // Payload for Action is syntactically incorrect or not conform the PDU structure for Action
+ FORMAT_VIOLATION = 'FormatViolation',
+ /** @deprecated use FORMAT_VIOLATION instead */
+ FORMATION_VIOLATION = 'FormationViolation',
+ // Any other error not covered by the other ones
+ GENERIC_ERROR = 'GenericError',
+ // An internal error occurred and the receiver was not able to process the requested Action successfully
+ INTERNAL_ERROR = 'InternalError',
// Requested Action is not known by receiver
NOT_IMPLEMENTED = 'NotImplemented',
// Requested Action is recognized but not supported by the receiver
NOT_SUPPORTED = 'NotSupported',
- // An internal error occurred and the receiver was not able to process the requested Action successfully
- INTERNAL_ERROR = 'InternalError',
+ // Payload for Action is syntactically correct but at least one of the fields violates occurrence constraints
+ OCCURRENCE_CONSTRAINT_VIOLATION = 'OccurrenceConstraintViolation',
+ // Payload is syntactically correct but at least one field contains an invalid value
+ PROPERTY_CONSTRAINT_VIOLATION = 'PropertyConstraintViolation',
// Payload for Action is incomplete
PROTOCOL_ERROR = 'ProtocolError',
// During the processing of Action a security issue occurred preventing receiver from completing the Action successfully
SECURITY_ERROR = 'SecurityError',
- // Payload for Action is syntactically incorrect or not conform the PDU structure for Action
- FORMATION_VIOLATION = 'FormationViolation',
- FORMAT_VIOLATION = 'FormatViolation',
- // Payload is syntactically correct but at least one field contains an invalid value
- PROPERTY_CONSTRAINT_VIOLATION = 'PropertyConstraintViolation',
- // Payload for Action is syntactically correct but at least one of the fields violates occurrence constraints
- OCCURRENCE_CONSTRAINT_VIOLATION = 'OccurrenceConstraintViolation',
+ // eslint-disable-next-line @cspell/spellchecker
// Payload for Action is syntactically correct but at least one of the fields violates data type constraints (e.g. "somestring" = 12)
TYPE_CONSTRAINT_VIOLATION = 'TypeConstraintViolation',
- // Any other error not covered by the previous ones
- GENERIC_ERROR = 'GenericError'
}
+/* eslint-disable perfectionist/sort-enums */
export enum MessageType {
CALL_MESSAGE = 2, // Caller to Callee
CALL_RESULT_MESSAGE = 3, // Callee to Caller
- CALL_ERROR_MESSAGE = 4 // Callee to Caller
+ CALL_ERROR_MESSAGE = 4, // Callee to Caller
}
+/* eslint-enable perfectionist/sort-enums */
OCPP16MeterValueMeasurand,
OCPP16MeterValuePhase,
OCPP16MeterValueUnit,
- type OCPP16SampledValue
+ type OCPP16SampledValue,
} from './1.6/MeterValues.js'
+export type MeterValue = OCPP16MeterValue
+
export const MeterValueUnit = {
- ...OCPP16MeterValueUnit
+ ...OCPP16MeterValueUnit,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type MeterValueUnit = OCPP16MeterValueUnit
export const MeterValueContext = {
- ...OCPP16MeterValueContext
+ ...OCPP16MeterValueContext,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type MeterValueContext = OCPP16MeterValueContext
-export const MeterValueMeasurand = {
- ...OCPP16MeterValueMeasurand
+export const MeterValueLocation = {
+ ...OCPP16MeterValueLocation,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
-export type MeterValueMeasurand = OCPP16MeterValueMeasurand
+export type MeterValueLocation = OCPP16MeterValueLocation
-export const MeterValueLocation = {
- ...OCPP16MeterValueLocation
+export const MeterValueMeasurand = {
+ ...OCPP16MeterValueMeasurand,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
-export type MeterValueLocation = OCPP16MeterValueLocation
+export type MeterValueMeasurand = OCPP16MeterValueMeasurand
export const MeterValuePhase = {
- ...OCPP16MeterValuePhase
+ ...OCPP16MeterValuePhase,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type MeterValuePhase = OCPP16MeterValuePhase
export type SampledValue = OCPP16SampledValue
-
-export type MeterValue = OCPP16MeterValue
export enum OCPPProtocol {
- JSON = 'json'
+ JSON = 'json',
}
export enum OCPPVersion {
VERSION_16 = '1.6',
VERSION_20 = '2.0',
- VERSION_201 = '2.0.1'
+ VERSION_201 = '2.0.1',
}
import type { ChargingStation } from '../../charging-station/index.js'
import type { OCPPError } from '../../exception/index.js'
import type { JsonType } from '../JsonType.js'
-import { OCPP16DiagnosticsStatus } from './1.6/DiagnosticsStatus.js'
import type { OCPP16MeterValuesRequest } from './1.6/MeterValues.js'
+import type { MessageType } from './MessageType.js'
+
+import { OCPP16DiagnosticsStatus } from './1.6/DiagnosticsStatus.js'
import {
OCPP16AvailabilityType,
type OCPP16BootNotificationRequest,
OCPP16MessageTrigger,
OCPP16RequestCommand,
type OCPP16ReserveNowRequest,
- type OCPP16StatusNotificationRequest
+ type OCPP16StatusNotificationRequest,
} from './1.6/Requests.js'
import { OperationalStatusEnumType } from './2.0/Common.js'
import {
type OCPP20BootNotificationRequest,
OCPP20IncomingRequestCommand,
OCPP20RequestCommand,
- type OCPP20StatusNotificationRequest
+ type OCPP20StatusNotificationRequest,
} from './2.0/Requests.js'
-import type { MessageType } from './MessageType.js'
-export const RequestCommand = {
- ...OCPP16RequestCommand,
- ...OCPP20RequestCommand
-} as const
-// eslint-disable-next-line @typescript-eslint/no-redeclare
-export type RequestCommand = OCPP16RequestCommand | OCPP20RequestCommand
+export type BootNotificationRequest = OCPP16BootNotificationRequest | OCPP20BootNotificationRequest
-export type OutgoingRequest = [MessageType.CALL_MESSAGE, string, RequestCommand, JsonType]
+export type CachedRequest = [
+ ResponseCallback,
+ ErrorCallback,
+ IncomingRequestCommand | RequestCommand,
+ JsonType
+]
-export interface RequestParams {
- skipBufferingOnError?: boolean
- triggerMessage?: boolean
- throwError?: boolean
-}
+export type DataTransferRequest = OCPP16DataTransferRequest
+
+export type DiagnosticsStatusNotificationRequest = OCPP16DiagnosticsStatusNotificationRequest
+
+export type ErrorCallback = (ocppError: OCPPError, requestStatistic?: boolean) => void
+
+export type FirmwareStatusNotificationRequest = OCPP16FirmwareStatusNotificationRequest
+
+export type HeartbeatRequest = OCPP16HeartbeatRequest
+
+export type IncomingRequest = [MessageType.CALL_MESSAGE, string, IncomingRequestCommand, JsonType]
+
+export type OutgoingRequest = [MessageType.CALL_MESSAGE, string, RequestCommand, JsonType]
export const IncomingRequestCommand = {
...OCPP16IncomingRequestCommand,
- ...OCPP20IncomingRequestCommand
+ ...OCPP20IncomingRequestCommand,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type IncomingRequestCommand = OCPP16IncomingRequestCommand | OCPP20IncomingRequestCommand
-export type IncomingRequest = [MessageType.CALL_MESSAGE, string, IncomingRequestCommand, JsonType]
-
export type IncomingRequestHandler = (
chargingStation: ChargingStation,
commandPayload: JsonType
) => JsonType | Promise<JsonType>
-export type ResponseCallback = (payload: JsonType, requestPayload: JsonType) => void
-
-export type ErrorCallback = (ocppError: OCPPError, requestStatistic?: boolean) => void
+export const RequestCommand = {
+ ...OCPP16RequestCommand,
+ ...OCPP20RequestCommand,
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type RequestCommand = OCPP16RequestCommand | OCPP20RequestCommand
-export type CachedRequest = [
- ResponseCallback,
- ErrorCallback,
- RequestCommand | IncomingRequestCommand,
- JsonType
-]
+export interface RequestParams {
+ skipBufferingOnError?: boolean
+ throwError?: boolean
+ triggerMessage?: boolean
+}
export const MessageTrigger = {
- ...OCPP16MessageTrigger
+ ...OCPP16MessageTrigger,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type MessageTrigger = OCPP16MessageTrigger
-export type BootNotificationRequest = OCPP16BootNotificationRequest | OCPP20BootNotificationRequest
+export type MeterValuesRequest = OCPP16MeterValuesRequest
-export type HeartbeatRequest = OCPP16HeartbeatRequest
+export type ResponseCallback = (payload: JsonType, requestPayload: JsonType) => void
export type StatusNotificationRequest =
| OCPP16StatusNotificationRequest
| OCPP20StatusNotificationRequest
-export type MeterValuesRequest = OCPP16MeterValuesRequest
-
-export type DataTransferRequest = OCPP16DataTransferRequest
-
-export type DiagnosticsStatusNotificationRequest = OCPP16DiagnosticsStatusNotificationRequest
-
-export type FirmwareStatusNotificationRequest = OCPP16FirmwareStatusNotificationRequest
-
export const AvailabilityType = {
...OCPP16AvailabilityType,
- ...OperationalStatusEnumType
+ ...OperationalStatusEnumType,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type AvailabilityType = OCPP16AvailabilityType | OperationalStatusEnumType
+export type CancelReservationRequest = OCPP16CancelReservationRequest
+
export const DiagnosticsStatus = {
- ...OCPP16DiagnosticsStatus
+ ...OCPP16DiagnosticsStatus,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type DiagnosticsStatus = OCPP16DiagnosticsStatus
export const FirmwareStatus = {
- ...OCPP16FirmwareStatus
+ ...OCPP16FirmwareStatus,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type FirmwareStatus = OCPP16FirmwareStatus
-export type ResponseType = JsonType | OCPPError
-
export type ReserveNowRequest = OCPP16ReserveNowRequest
-export type CancelReservationRequest = OCPP16CancelReservationRequest
+export type ResponseType = JsonType | OCPPError
import type { OCPP16ReserveNowRequest } from './1.6/Requests.js'
-export type Reservation = OCPP16ReserveNowRequest
-
-export type ReservationKey = keyof Reservation
-
export enum ReservationTerminationReason {
- EXPIRED = 'Expired',
- TRANSACTION_STARTED = 'TransactionStarted',
CONNECTOR_STATE_CHANGED = 'ConnectorStateChanged',
+ EXPIRED = 'Expired',
+ REPLACE_EXISTING = 'ReplaceExisting',
RESERVATION_CANCELED = 'ReservationCanceled',
- REPLACE_EXISTING = 'ReplaceExisting'
+ TRANSACTION_STARTED = 'TransactionStarted',
}
+
+export type Reservation = OCPP16ReserveNowRequest
+
+export type ReservationKey = keyof Reservation
import type { ChargingStation } from '../../charging-station/index.js'
import type { JsonType } from '../JsonType.js'
import type { OCPP16MeterValuesResponse } from './1.6/MeterValues.js'
+import type { OCPP20BootNotificationResponse, OCPP20ClearCacheResponse } from './2.0/Responses.js'
+import type { ErrorType } from './ErrorType.js'
+import type { MessageType } from './MessageType.js'
+
import {
OCPP16AvailabilityStatus,
type OCPP16BootNotificationResponse,
OCPP16ReservationStatus,
type OCPP16StatusNotificationResponse,
OCPP16TriggerMessageStatus,
- OCPP16UnlockStatus
+ OCPP16UnlockStatus,
} from './1.6/Responses.js'
-import type { OCPP20BootNotificationResponse, OCPP20ClearCacheResponse } from './2.0/Responses.js'
import { type GenericResponse, GenericStatus } from './Common.js'
-import type { ErrorType } from './ErrorType.js'
-import type { MessageType } from './MessageType.js'
-
-export type Response = [MessageType.CALL_RESULT_MESSAGE, string, JsonType]
-
-export type ErrorResponse = [MessageType.CALL_ERROR_MESSAGE, string, ErrorType, string, JsonType]
-
-export type ResponseHandler = (
- chargingStation: ChargingStation,
- payload: JsonType,
- requestPayload?: JsonType
-) => void | Promise<void>
export type BootNotificationResponse =
| OCPP16BootNotificationResponse
| OCPP20BootNotificationResponse
-export type HeartbeatResponse = OCPP16HeartbeatResponse
+export type CancelReservationResponse = GenericResponse
export type ClearCacheResponse = GenericResponse | OCPP20ClearCacheResponse
-export type StatusNotificationResponse = OCPP16StatusNotificationResponse
-
-export type MeterValuesResponse = OCPP16MeterValuesResponse
-
export type DataTransferResponse = OCPP16DataTransferResponse
export type DiagnosticsStatusNotificationResponse = OCPP16DiagnosticsStatusNotificationResponse
+export type ErrorResponse = [MessageType.CALL_ERROR_MESSAGE, string, ErrorType, string, JsonType]
+
export type FirmwareStatusNotificationResponse = OCPP16FirmwareStatusNotificationResponse
+export type HeartbeatResponse = OCPP16HeartbeatResponse
+
+export type MeterValuesResponse = OCPP16MeterValuesResponse
+
+export type Response = [MessageType.CALL_RESULT_MESSAGE, string, JsonType]
+
+export type ResponseHandler = (
+ chargingStation: ChargingStation,
+ payload: JsonType,
+ requestPayload?: JsonType
+) => Promise<void> | void
+
+export type StatusNotificationResponse = OCPP16StatusNotificationResponse
+
export const AvailabilityStatus = {
- ...OCPP16AvailabilityStatus
+ ...OCPP16AvailabilityStatus,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type AvailabilityStatus = OCPP16AvailabilityStatus
export const ChargingProfileStatus = {
- ...OCPP16ChargingProfileStatus
+ ...OCPP16ChargingProfileStatus,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type ChargingProfileStatus = OCPP16ChargingProfileStatus
export const ClearChargingProfileStatus = {
- ...OCPP16ClearChargingProfileStatus
+ ...OCPP16ClearChargingProfileStatus,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type ClearChargingProfileStatus = OCPP16ClearChargingProfileStatus
export const ConfigurationStatus = {
- ...OCPP16ConfigurationStatus
+ ...OCPP16ConfigurationStatus,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type ConfigurationStatus = OCPP16ConfigurationStatus
export const UnlockStatus = {
- ...OCPP16UnlockStatus
+ ...OCPP16UnlockStatus,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type UnlockStatus = OCPP16UnlockStatus
export const TriggerMessageStatus = {
- ...OCPP16TriggerMessageStatus
+ ...OCPP16TriggerMessageStatus,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type TriggerMessageStatus = OCPP16TriggerMessageStatus
export const DataTransferStatus = {
- ...OCPP16DataTransferStatus
+ ...OCPP16DataTransferStatus,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type DataTransferStatus = OCPP16DataTransferStatus
-export type ReservationStatus = OCPP16ReservationStatus
-// eslint-disable-next-line @typescript-eslint/no-redeclare
export const ReservationStatus = {
- ...OCPP16ReservationStatus
+ ...OCPP16ReservationStatus,
} as const
-
-export type CancelReservationStatus = GenericStatus
// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type ReservationStatus = OCPP16ReservationStatus
+
export const CancelReservationStatus = {
- ...GenericStatus
+ ...GenericStatus,
} as const
-
-export type CancelReservationResponse = GenericResponse
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type CancelReservationStatus = GenericStatus
type OCPP16StartTransactionResponse,
OCPP16StopTransactionReason,
type OCPP16StopTransactionRequest,
- type OCPP16StopTransactionResponse
+ type OCPP16StopTransactionResponse,
} from './1.6/Transaction.js'
export const AuthorizationStatus = {
- ...OCPP16AuthorizationStatus
+ ...OCPP16AuthorizationStatus,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type AuthorizationStatus = OCPP16AuthorizationStatus
export type AuthorizeResponse = OCPP16AuthorizeResponse
+export type StartTransactionRequest = OCPP16StartTransactionRequest
+
+export type StartTransactionResponse = OCPP16StartTransactionResponse
+
export const StopTransactionReason = {
- ...OCPP16StopTransactionReason
+ ...OCPP16StopTransactionReason,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type StopTransactionReason = OCPP16StopTransactionReason
-export type StartTransactionRequest = OCPP16StartTransactionRequest
-
-export type StartTransactionResponse = OCPP16StartTransactionResponse
-
export type StopTransactionRequest = OCPP16StopTransactionRequest
export type StopTransactionResponse = OCPP16StopTransactionResponse
import { Entity, PrimaryKey, Property } from '@mikro-orm/core'
interface StatisticsData {
- name: string
- requestCount: number
- responseCount: number
+ avgTimeMeasurement: number
+ currentTimeMeasurement: number
errorCount: number
- timeMeasurementCount: number
- measurementTimeSeries: Array<{
+ maxTimeMeasurement: number
+ measurementTimeSeries: {
timestamp: number
value: number
- }>
- currentTimeMeasurement: number
- minTimeMeasurement: number
- maxTimeMeasurement: number
- totalTimeMeasurement: number
- avgTimeMeasurement: number
+ }[]
medTimeMeasurement: number
+ minTimeMeasurement: number
+ name: string
ninetyFiveThPercentileTimeMeasurement: number
- stdDevTimeMeasurement: number
+ requestCount: number
+ responseCount: number
+ stdTimeMeasurement: number
+ timeMeasurementCount: number
+ totalTimeMeasurement: number
}
@Entity()
export class PerformanceRecord {
- @PrimaryKey()
- id!: string
-
@Property()
- name!: string
+ createdAt!: Date
+
+ @PrimaryKey()
+ id!: string
@Property()
- uri!: string
+ name!: string
@Property()
- createdAt!: Date
+ statisticsData!: Partial<StatisticsData>[]
@Property()
- updatedAt?: Date
+ updatedAt?: Date
@Property()
- statisticsData!: Array<Partial<StatisticsData>>
+ uri!: string
}
import { Queue } from 'mnemonist'
-import { Constants } from './Constants.js'
+import { isAsyncFunction } from './Utils.js'
export enum AsyncLockType {
configuration = 'configuration',
- performance = 'performance'
+ performance = 'performance',
}
-type ResolveType = (value: void | PromiseLike<void>) => void
+type ResolveType = (value: PromiseLike<void> | void) => void
export class AsyncLock {
private static readonly asyncLocks = new Map<AsyncLockType, AsyncLock>()
this.resolveQueue = new Queue<ResolveType>()
}
- public static async runExclusive<T>(type: AsyncLockType, fn: () => T | Promise<T>): Promise<T> {
- return await AsyncLock.acquire(type)
- .then(fn)
- .finally(() => {
- AsyncLock.release(type).catch(Constants.EMPTY_FUNCTION)
- })
+ public static async runExclusive<T>(type: AsyncLockType, fn: () => Promise<T> | T): Promise<T> {
+ try {
+ await AsyncLock.acquire(type)
+ if (isAsyncFunction(fn)) {
+ return await fn()
+ } else {
+ return fn() as T
+ }
+ } finally {
+ await AsyncLock.release(type)
+ }
}
private static async acquire (type: AsyncLockType): Promise<void> {
})
}
+ private static getAsyncLock (type: AsyncLockType): AsyncLock {
+ if (!AsyncLock.asyncLocks.has(type)) {
+ AsyncLock.asyncLocks.set(type, new AsyncLock())
+ }
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return AsyncLock.asyncLocks.get(type)!
+ }
+
private static async release (type: AsyncLockType): Promise<void> {
const asyncLock = AsyncLock.getAsyncLock(type)
if (asyncLock.resolveQueue.size === 0 && asyncLock.acquired) {
asyncLock.acquired = false
return
}
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const queuedResolve = asyncLock.resolveQueue.dequeue()!
await new Promise<void>(resolve => {
- queuedResolve()
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ asyncLock.resolveQueue.dequeue()!()
resolve()
})
}
-
- private static getAsyncLock (type: AsyncLockType): AsyncLock {
- if (!AsyncLock.asyncLocks.has(type)) {
- AsyncLock.asyncLocks.set(type, new AsyncLock())
- }
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- return AsyncLock.asyncLocks.get(type)!
- }
}
ChargingStationAutomaticTransactionGeneratorConfiguration,
ConnectorStatus,
EvseStatusConfiguration,
- EvseStatusWorkerType
+ EvseStatusWorkerType,
} from '../types/index.js'
export const buildChargingStationAutomaticTransactionGeneratorConfiguration = (
automaticTransactionGenerator: chargingStation.getAutomaticTransactionGeneratorConfiguration(),
...(chargingStation.automaticTransactionGenerator?.connectorsStatus != null && {
automaticTransactionGeneratorStatuses: [
- ...chargingStation.automaticTransactionGenerator.connectorsStatus.values()
- ]
- })
+ ...chargingStation.automaticTransactionGenerator.connectorsStatus.values(),
+ ],
+ }),
}
}
)
}
-export const enum OutputFormat {
+export enum OutputFormat {
configuration = 'configuration',
- worker = 'worker'
+ worker = 'worker',
}
export const buildEvsesStatus = (
chargingStation: ChargingStation,
outputFormat: OutputFormat = OutputFormat.configuration
-): Array<EvseStatusWorkerType | EvseStatusConfiguration> => {
+): (EvseStatusConfiguration | EvseStatusWorkerType)[] => {
// eslint-disable-next-line array-callback-return
return [...chargingStation.evses.values()].map(evseStatus => {
const connectorsStatus = [...evseStatus.connectors.values()].map(
)
let status: EvseStatusConfiguration
switch (outputFormat) {
- case OutputFormat.worker:
- return {
- ...evseStatus,
- connectors: connectorsStatus
- }
case OutputFormat.configuration:
status = {
...evseStatus,
- connectorsStatus
+ connectorsStatus,
}
delete (status as EvseStatusWorkerType).connectors
return status
+ case OutputFormat.worker:
+ return {
+ ...evseStatus,
+ connectors: connectorsStatus,
+ }
}
})
}
-import { type FSWatcher, readFileSync, watch } from 'node:fs'
+import chalk from 'chalk'
+import { existsSync, type FSWatcher, readFileSync, watch } from 'node:fs'
import { dirname, join } from 'node:path'
import { env } from 'node:process'
import { fileURLToPath } from 'node:url'
-import chalk from 'chalk'
-import { mergeDeepRight, once } from 'rambda'
-
import {
ApplicationProtocol,
ApplicationProtocolVersion,
StorageType,
SupervisionUrlDistribution,
type UIServerConfiguration,
- type WorkerConfiguration
+ type WorkerConfiguration,
} from '../types/index.js'
import {
DEFAULT_ELEMENT_ADD_DELAY,
DEFAULT_POOL_MAX_SIZE,
DEFAULT_POOL_MIN_SIZE,
DEFAULT_WORKER_START_DELAY,
- WorkerProcessType
+ WorkerProcessType,
} from '../worker/index.js'
import {
buildPerformanceUriFilePath,
checkWorkerProcessType,
getDefaultPerformanceStorageUri,
handleFileException,
- logPrefix
+ logPrefix,
} from './ConfigurationUtils.js'
import { Constants } from './Constants.js'
-import { hasOwnProp, isCFEnvironment } from './Utils.js'
+import { has, isCFEnvironment, mergeDeepRight, once } from './Utils.js'
type ConfigurationSectionType =
| LogConfiguration
| StorageConfiguration
- | WorkerConfiguration
| UIServerConfiguration
+ | WorkerConfiguration
+
+const defaultUIServerConfiguration: UIServerConfiguration = {
+ enabled: false,
+ options: {
+ host: Constants.DEFAULT_UI_SERVER_HOST,
+ port: Constants.DEFAULT_UI_SERVER_PORT,
+ },
+ type: ApplicationProtocol.WS,
+ version: ApplicationProtocolVersion.VERSION_11,
+}
+
+const defaultStorageConfiguration: StorageConfiguration = {
+ enabled: true,
+ type: StorageType.NONE,
+}
+
+const defaultLogConfiguration: LogConfiguration = {
+ enabled: true,
+ errorFile: 'logs/error.log',
+ file: 'logs/combined.log',
+ format: 'simple',
+ level: 'info',
+ rotate: true,
+ statisticsInterval: Constants.DEFAULT_LOG_STATISTICS_INTERVAL,
+}
+
+const defaultWorkerConfiguration: WorkerConfiguration = {
+ elementAddDelay: DEFAULT_ELEMENT_ADD_DELAY,
+ elementsPerWorker: 'auto',
+ poolMaxSize: DEFAULT_POOL_MAX_SIZE,
+ poolMinSize: DEFAULT_POOL_MIN_SIZE,
+ processType: WorkerProcessType.workerSet,
+ startDelay: DEFAULT_WORKER_START_DELAY,
+}
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class Configuration {
public static configurationChangeCallback?: () => Promise<void>
- private static readonly configurationFile = join(
- dirname(fileURLToPath(import.meta.url)),
- 'assets',
- 'config.json'
- )
-
- private static configurationFileReloading = false
private static configurationData?: ConfigurationData
+ private static configurationFile: string | undefined
+ private static configurationFileReloading = false
private static configurationFileWatcher?: FSWatcher
- private static readonly configurationSectionCache = new Map<
- ConfigurationSection,
- ConfigurationSectionType
- >([
- [ConfigurationSection.log, Configuration.buildLogSection()],
- [ConfigurationSection.performanceStorage, Configuration.buildPerformanceStorageSection()],
- [ConfigurationSection.worker, Configuration.buildWorkerSection()],
- [ConfigurationSection.uiServer, Configuration.buildUIServerSection()]
- ])
+ private static configurationSectionCache: Map<ConfigurationSection, ConfigurationSectionType>
+
+ static {
+ const configurationFile = join(dirname(fileURLToPath(import.meta.url)), 'assets', 'config.json')
+ if (existsSync(configurationFile)) {
+ Configuration.configurationFile = configurationFile
+ } else {
+ console.error(
+ `${chalk.green(logPrefix())} ${chalk.red(
+ "Configuration file './src/assets/config.json' not found, using default configuration"
+ )}`
+ )
+ Configuration.configurationData = {
+ log: defaultLogConfiguration,
+ performanceStorage: defaultStorageConfiguration,
+ stationTemplateUrls: [
+ {
+ file: 'siemens.station-template.json',
+ numberOfStations: 1,
+ },
+ ],
+ supervisionUrlDistribution: SupervisionUrlDistribution.ROUND_ROBIN,
+ supervisionUrls: 'ws://localhost:8180/steve/websocket/CentralSystemService',
+ uiServer: defaultUIServerConfiguration,
+ worker: defaultWorkerConfiguration,
+ }
+ }
+ Configuration.configurationSectionCache = new Map<
+ ConfigurationSection,
+ ConfigurationSectionType
+ >([
+ [ConfigurationSection.log, Configuration.buildLogSection()],
+ [ConfigurationSection.performanceStorage, Configuration.buildPerformanceStorageSection()],
+ [ConfigurationSection.uiServer, Configuration.buildUIServerSection()],
+ [ConfigurationSection.worker, Configuration.buildWorkerSection()],
+ ])
+ }
private constructor () {
// This is intentional
}
+ public static getConfigurationData (): ConfigurationData | undefined {
+ if (
+ Configuration.configurationData == null &&
+ Configuration.configurationFile != null &&
+ Configuration.configurationFile.trim().length > 0
+ ) {
+ try {
+ Configuration.configurationData = JSON.parse(
+ readFileSync(Configuration.configurationFile, 'utf8')
+ ) as ConfigurationData
+ Configuration.configurationFileWatcher ??= Configuration.getConfigurationFileWatcher()
+ } catch (error) {
+ handleFileException(
+ Configuration.configurationFile,
+ FileType.Configuration,
+ error as NodeJS.ErrnoException,
+ logPrefix()
+ )
+ }
+ }
+ return Configuration.configurationData
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
public static getConfigurationSection<T extends ConfigurationSectionType>(
sectionName: ConfigurationSection
): T {
return Configuration.getConfigurationData()?.stationTemplateUrls
}
+ public static getSupervisionUrlDistribution (): SupervisionUrlDistribution | undefined {
+ return has('supervisionUrlDistribution', Configuration.getConfigurationData())
+ ? Configuration.getConfigurationData()?.supervisionUrlDistribution
+ : SupervisionUrlDistribution.ROUND_ROBIN
+ }
+
public static getSupervisionUrls (): string | string[] | undefined {
if (
Configuration.getConfigurationData()?.['supervisionURLs' as keyof ConfigurationData] != null
return Configuration.getConfigurationData()?.supervisionUrls
}
- public static getSupervisionUrlDistribution (): SupervisionUrlDistribution | undefined {
- return hasOwnProp(Configuration.getConfigurationData(), 'supervisionUrlDistribution')
- ? Configuration.getConfigurationData()?.supervisionUrlDistribution
- : SupervisionUrlDistribution.ROUND_ROBIN
+ public static workerDynamicPoolInUse (): boolean {
+ return (
+ Configuration.getConfigurationSection<WorkerConfiguration>(ConfigurationSection.worker)
+ .processType === WorkerProcessType.dynamicPool
+ )
}
public static workerPoolInUse (): boolean {
)
}
- public static workerDynamicPoolInUse (): boolean {
- return (
- Configuration.getConfigurationSection<WorkerConfiguration>(ConfigurationSection.worker)
- .processType === WorkerProcessType.dynamicPool
- )
- }
-
- private static isConfigurationSectionCached (sectionName: ConfigurationSection): boolean {
- return Configuration.configurationSectionCache.has(sectionName)
- }
-
- private static cacheConfigurationSection (sectionName: ConfigurationSection): void {
- switch (sectionName) {
- case ConfigurationSection.log:
- Configuration.configurationSectionCache.set(sectionName, Configuration.buildLogSection())
- break
- case ConfigurationSection.performanceStorage:
- Configuration.configurationSectionCache.set(
- sectionName,
- Configuration.buildPerformanceStorageSection()
- )
- break
- case ConfigurationSection.worker:
- Configuration.configurationSectionCache.set(sectionName, Configuration.buildWorkerSection())
- break
- case ConfigurationSection.uiServer:
- Configuration.configurationSectionCache.set(
- sectionName,
- Configuration.buildUIServerSection()
- )
- break
- default:
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- throw new Error(`Unknown configuration section '${sectionName}'`)
- }
- }
-
- private static buildUIServerSection (): UIServerConfiguration {
- let uiServerConfiguration: UIServerConfiguration = {
- enabled: false,
- type: ApplicationProtocol.WS,
- version: ApplicationProtocolVersion.VERSION_11,
- options: {
- host: Constants.DEFAULT_UI_SERVER_HOST,
- port: Constants.DEFAULT_UI_SERVER_PORT
- }
- }
- if (hasOwnProp(Configuration.getConfigurationData(), ConfigurationSection.uiServer)) {
- uiServerConfiguration = mergeDeepRight(
- uiServerConfiguration,
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- Configuration.getConfigurationData()!.uiServer!
- )
+ private static buildLogSection (): LogConfiguration {
+ const deprecatedLogConfiguration: LogConfiguration = {
+ ...(has('logEnabled', Configuration.getConfigurationData()) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ enabled: Configuration.getConfigurationData()?.logEnabled,
+ }),
+ ...(has('logFile', Configuration.getConfigurationData()) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ file: Configuration.getConfigurationData()?.logFile,
+ }),
+ ...(has('logErrorFile', Configuration.getConfigurationData()) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ errorFile: Configuration.getConfigurationData()?.logErrorFile,
+ }),
+ ...(has('logStatisticsInterval', Configuration.getConfigurationData()) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ statisticsInterval: Configuration.getConfigurationData()?.logStatisticsInterval,
+ }),
+ ...(has('logLevel', Configuration.getConfigurationData()) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ level: Configuration.getConfigurationData()?.logLevel,
+ }),
+ ...(has('logConsole', Configuration.getConfigurationData()) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ console: Configuration.getConfigurationData()?.logConsole,
+ }),
+ ...(has('logFormat', Configuration.getConfigurationData()) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ format: Configuration.getConfigurationData()?.logFormat,
+ }),
+ ...(has('logRotate', Configuration.getConfigurationData()) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ rotate: Configuration.getConfigurationData()?.logRotate,
+ }),
+ ...(has('logMaxFiles', Configuration.getConfigurationData()) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ maxFiles: Configuration.getConfigurationData()?.logMaxFiles,
+ }),
+ ...(has('logMaxSize', Configuration.getConfigurationData()) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ maxSize: Configuration.getConfigurationData()?.logMaxSize,
+ }),
}
- if (isCFEnvironment()) {
- delete uiServerConfiguration.options?.host
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- uiServerConfiguration.options!.port = parseInt(env.PORT!)
+ const logConfiguration: LogConfiguration = {
+ ...defaultLogConfiguration,
+ ...deprecatedLogConfiguration,
+ ...(has(ConfigurationSection.log, Configuration.getConfigurationData()) &&
+ Configuration.getConfigurationData()?.log),
}
- return uiServerConfiguration
+ return logConfiguration
}
private static buildPerformanceStorageSection (): StorageConfiguration {
let storageConfiguration: StorageConfiguration
switch (Configuration.getConfigurationData()?.performanceStorage?.type) {
- case StorageType.SQLITE:
+ case StorageType.JSON_FILE:
storageConfiguration = {
enabled: false,
- type: StorageType.SQLITE,
- uri: getDefaultPerformanceStorageUri(StorageType.SQLITE)
+ type: StorageType.JSON_FILE,
+ uri: getDefaultPerformanceStorageUri(StorageType.JSON_FILE),
}
break
- case StorageType.JSON_FILE:
+ case StorageType.SQLITE:
storageConfiguration = {
enabled: false,
- type: StorageType.JSON_FILE,
- uri: getDefaultPerformanceStorageUri(StorageType.JSON_FILE)
+ type: StorageType.SQLITE,
+ uri: getDefaultPerformanceStorageUri(StorageType.SQLITE),
}
break
case StorageType.NONE:
default:
- storageConfiguration = {
- enabled: true,
- type: StorageType.NONE
- }
+ storageConfiguration = defaultStorageConfiguration
break
}
- if (hasOwnProp(Configuration.getConfigurationData(), ConfigurationSection.performanceStorage)) {
+ if (has(ConfigurationSection.performanceStorage, Configuration.getConfigurationData())) {
storageConfiguration = {
...storageConfiguration,
...Configuration.getConfigurationData()?.performanceStorage,
uri: buildPerformanceUriFilePath(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
new URL(Configuration.getConfigurationData()!.performanceStorage!.uri!).pathname
- )
- })
+ ),
+ }),
}
}
return storageConfiguration
}
- private static buildLogSection (): LogConfiguration {
- const defaultLogConfiguration: LogConfiguration = {
- enabled: true,
- file: 'logs/combined.log',
- errorFile: 'logs/error.log',
- statisticsInterval: Constants.DEFAULT_LOG_STATISTICS_INTERVAL,
- level: 'info',
- format: 'simple',
- rotate: true
- }
- const deprecatedLogConfiguration: LogConfiguration = {
- ...(hasOwnProp(Configuration.getConfigurationData(), 'logEnabled') && {
- enabled: Configuration.getConfigurationData()?.logEnabled
- }),
- ...(hasOwnProp(Configuration.getConfigurationData(), 'logFile') && {
- file: Configuration.getConfigurationData()?.logFile
- }),
- ...(hasOwnProp(Configuration.getConfigurationData(), 'logErrorFile') && {
- errorFile: Configuration.getConfigurationData()?.logErrorFile
- }),
- ...(hasOwnProp(Configuration.getConfigurationData(), 'logStatisticsInterval') && {
- statisticsInterval: Configuration.getConfigurationData()?.logStatisticsInterval
- }),
- ...(hasOwnProp(Configuration.getConfigurationData(), 'logLevel') && {
- level: Configuration.getConfigurationData()?.logLevel
- }),
- ...(hasOwnProp(Configuration.getConfigurationData(), 'logConsole') && {
- console: Configuration.getConfigurationData()?.logConsole
- }),
- ...(hasOwnProp(Configuration.getConfigurationData(), 'logFormat') && {
- format: Configuration.getConfigurationData()?.logFormat
- }),
- ...(hasOwnProp(Configuration.getConfigurationData(), 'logRotate') && {
- rotate: Configuration.getConfigurationData()?.logRotate
- }),
- ...(hasOwnProp(Configuration.getConfigurationData(), 'logMaxFiles') && {
- maxFiles: Configuration.getConfigurationData()?.logMaxFiles
- }),
- ...(hasOwnProp(Configuration.getConfigurationData(), 'logMaxSize') && {
- maxSize: Configuration.getConfigurationData()?.logMaxSize
- })
+ private static buildUIServerSection (): UIServerConfiguration {
+ let uiServerConfiguration: UIServerConfiguration = defaultUIServerConfiguration
+ if (has(ConfigurationSection.uiServer, Configuration.getConfigurationData())) {
+ uiServerConfiguration = mergeDeepRight(
+ uiServerConfiguration,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ Configuration.getConfigurationData()!.uiServer!
+ )
}
- const logConfiguration: LogConfiguration = {
- ...defaultLogConfiguration,
- ...deprecatedLogConfiguration,
- ...(hasOwnProp(Configuration.getConfigurationData(), ConfigurationSection.log) &&
- Configuration.getConfigurationData()?.log)
+ if (isCFEnvironment()) {
+ delete uiServerConfiguration.options?.host
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ uiServerConfiguration.options!.port = Number.parseInt(env.PORT!)
}
- return logConfiguration
+ return uiServerConfiguration
}
private static buildWorkerSection (): WorkerConfiguration {
- const defaultWorkerConfiguration: WorkerConfiguration = {
- processType: WorkerProcessType.workerSet,
- startDelay: DEFAULT_WORKER_START_DELAY,
- elementsPerWorker: 'auto',
- elementAddDelay: DEFAULT_ELEMENT_ADD_DELAY,
- poolMinSize: DEFAULT_POOL_MIN_SIZE,
- poolMaxSize: DEFAULT_POOL_MAX_SIZE
- }
-
const deprecatedWorkerConfiguration: WorkerConfiguration = {
- ...(hasOwnProp(Configuration.getConfigurationData(), 'workerProcess') && {
- processType: Configuration.getConfigurationData()?.workerProcess
+ ...(has('workerProcess', Configuration.getConfigurationData()) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ processType: Configuration.getConfigurationData()?.workerProcess,
}),
- ...(hasOwnProp(Configuration.getConfigurationData(), 'workerStartDelay') && {
- startDelay: Configuration.getConfigurationData()?.workerStartDelay
+ ...(has('workerStartDelay', Configuration.getConfigurationData()) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ startDelay: Configuration.getConfigurationData()?.workerStartDelay,
}),
- ...(hasOwnProp(Configuration.getConfigurationData(), 'chargingStationsPerWorker') && {
- elementsPerWorker: Configuration.getConfigurationData()?.chargingStationsPerWorker
+ ...(has('chargingStationsPerWorker', Configuration.getConfigurationData()) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ elementsPerWorker: Configuration.getConfigurationData()?.chargingStationsPerWorker,
}),
- ...(hasOwnProp(Configuration.getConfigurationData(), 'elementAddDelay') && {
- elementAddDelay: Configuration.getConfigurationData()?.elementAddDelay
+ ...(has('elementAddDelay', Configuration.getConfigurationData()) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ elementAddDelay: Configuration.getConfigurationData()?.elementAddDelay,
}),
- ...(hasOwnProp(Configuration.getConfigurationData()?.worker, 'elementStartDelay') && {
- elementAddDelay: Configuration.getConfigurationData()?.worker?.elementStartDelay
+ ...(has('elementStartDelay', Configuration.getConfigurationData()?.worker) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ elementAddDelay: Configuration.getConfigurationData()?.worker?.elementStartDelay,
}),
- ...(hasOwnProp(Configuration.getConfigurationData(), 'workerPoolMinSize') && {
- poolMinSize: Configuration.getConfigurationData()?.workerPoolMinSize
+ ...(has('workerPoolMinSize', Configuration.getConfigurationData()) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ poolMinSize: Configuration.getConfigurationData()?.workerPoolMinSize,
+ }),
+ ...(has('workerPoolMaxSize', Configuration.getConfigurationData()) && {
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ poolMaxSize: Configuration.getConfigurationData()?.workerPoolMaxSize,
}),
- ...(hasOwnProp(Configuration.getConfigurationData(), 'workerPoolMaxSize') && {
- poolMaxSize: Configuration.getConfigurationData()?.workerPoolMaxSize
- })
}
- hasOwnProp(Configuration.getConfigurationData(), 'workerPoolStrategy') &&
+ has('workerPoolStrategy', Configuration.getConfigurationData()) &&
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
delete Configuration.getConfigurationData()?.workerPoolStrategy
const workerConfiguration: WorkerConfiguration = {
...defaultWorkerConfiguration,
...deprecatedWorkerConfiguration,
- ...(hasOwnProp(Configuration.getConfigurationData(), ConfigurationSection.worker) &&
- Configuration.getConfigurationData()?.worker)
+ ...(has(ConfigurationSection.worker, Configuration.getConfigurationData()) &&
+ Configuration.getConfigurationData()?.worker),
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
checkWorkerProcessType(workerConfiguration.processType!)
return workerConfiguration
}
+ private static cacheConfigurationSection (sectionName: ConfigurationSection): void {
+ switch (sectionName) {
+ case ConfigurationSection.log:
+ Configuration.configurationSectionCache.set(sectionName, Configuration.buildLogSection())
+ break
+ case ConfigurationSection.performanceStorage:
+ Configuration.configurationSectionCache.set(
+ sectionName,
+ Configuration.buildPerformanceStorageSection()
+ )
+ break
+ case ConfigurationSection.uiServer:
+ Configuration.configurationSectionCache.set(
+ sectionName,
+ Configuration.buildUIServerSection()
+ )
+ break
+ case ConfigurationSection.worker:
+ Configuration.configurationSectionCache.set(sectionName, Configuration.buildWorkerSection())
+ break
+ default:
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ throw new Error(`Unknown configuration section '${sectionName}'`)
+ }
+ }
+
private static checkDeprecatedConfigurationKeys (): void {
// connection timeout
Configuration.warnDeprecatedConfigurationKey(
] as StationTemplateUrl[])
Configuration.getConfigurationData()?.stationTemplateUrls.forEach(
(stationTemplateUrl: StationTemplateUrl) => {
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (stationTemplateUrl['numberOfStation' as keyof StationTemplateUrl] != null) {
console.error(
`${chalk.green(logPrefix())} ${chalk.red(
"Use 'uri' instead"
)
// uiServer section
- if (hasOwnProp(Configuration.getConfigurationData(), 'uiWebSocketServer')) {
+ if (has('uiWebSocketServer', Configuration.getConfigurationData())) {
console.error(
`${chalk.green(logPrefix())} ${chalk.red(
`Deprecated configuration section 'uiWebSocketServer' usage. Use '${ConfigurationSection.uiServer}' instead`
}
}
- private static warnDeprecatedConfigurationKey (
- key: string,
- configurationSection?: ConfigurationSection,
- logMsgToAppend = ''
- ): void {
+ private static getConfigurationFileWatcher (): FSWatcher | undefined {
if (
- configurationSection != null &&
- Configuration.getConfigurationData()?.[configurationSection as keyof ConfigurationData] !=
- null &&
- (
- Configuration.getConfigurationData()?.[
- configurationSection as keyof ConfigurationData
- ] as Record<string, unknown>
- )[key] != null
+ Configuration.configurationFile == null ||
+ Configuration.configurationFile.trim().length === 0
) {
- console.error(
- `${chalk.green(logPrefix())} ${chalk.red(
- `Deprecated configuration key '${key}' usage in section '${configurationSection}'${
- logMsgToAppend.trim().length > 0 ? `. ${logMsgToAppend}` : ''
- }`
- )}`
- )
- } else if (Configuration.getConfigurationData()?.[key as keyof ConfigurationData] != null) {
- console.error(
- `${chalk.green(logPrefix())} ${chalk.red(
- `Deprecated configuration key '${key}' usage${
- logMsgToAppend.trim().length > 0 ? `. ${logMsgToAppend}` : ''
- }`
- )}`
- )
+ return
}
- }
-
- public static getConfigurationData (): ConfigurationData | undefined {
- if (Configuration.configurationData == null) {
- try {
- Configuration.configurationData = JSON.parse(
- readFileSync(Configuration.configurationFile, 'utf8')
- ) as ConfigurationData
- if (Configuration.configurationFileWatcher == null) {
- Configuration.configurationFileWatcher = Configuration.getConfigurationFileWatcher()
- }
- } catch (error) {
- handleFileException(
- Configuration.configurationFile,
- FileType.Configuration,
- error as NodeJS.ErrnoException,
- logPrefix()
- )
- }
- }
- return Configuration.configurationData
- }
-
- private static getConfigurationFileWatcher (): FSWatcher | undefined {
try {
return watch(Configuration.configurationFile, (event, filename): void => {
if (
const consoleWarnOnce = once(console.warn)
consoleWarnOnce(
`${chalk.green(logPrefix())} ${chalk.yellow(
- `${FileType.Configuration} ${this.configurationFile} file have changed, reload`
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `${FileType.Configuration} ${Configuration.configurationFile} file have changed, reload`
)}`
)
delete Configuration.configurationData
Configuration.configurationSectionCache.clear()
if (Configuration.configurationChangeCallback != null) {
Configuration.configurationChangeCallback()
- .catch((error: unknown) => {
- throw typeof error === 'string' ? new Error(error) : error
- })
.finally(() => {
Configuration.configurationFileReloading = false
})
+ .catch((error: unknown) => {
+ throw typeof error === 'string' ? new Error(error) : error
+ })
} else {
Configuration.configurationFileReloading = false
}
)
}
}
+
+ private static isConfigurationSectionCached (sectionName: ConfigurationSection): boolean {
+ return Configuration.configurationSectionCache.has(sectionName)
+ }
+
+ private static warnDeprecatedConfigurationKey (
+ key: string,
+ configurationSection?: ConfigurationSection,
+ logMsgToAppend = ''
+ ): void {
+ if (
+ configurationSection != null &&
+ Configuration.getConfigurationData()?.[configurationSection as keyof ConfigurationData] !=
+ null &&
+ (
+ Configuration.getConfigurationData()?.[
+ configurationSection as keyof ConfigurationData
+ ] as Record<string, unknown>
+ )[key] != null
+ ) {
+ console.error(
+ `${chalk.green(logPrefix())} ${chalk.red(
+ `Deprecated configuration key '${key}' usage in section '${configurationSection}'${
+ logMsgToAppend.trim().length > 0 ? `. ${logMsgToAppend}` : ''
+ }`
+ )}`
+ )
+ } else if (Configuration.getConfigurationData()?.[key as keyof ConfigurationData] != null) {
+ console.error(
+ `${chalk.green(logPrefix())} ${chalk.red(
+ `Deprecated configuration key '${key}' usage${
+ logMsgToAppend.trim().length > 0 ? `. ${logMsgToAppend}` : ''
+ }`
+ )}`
+ )
+ }
+ }
}
+import chalk from 'chalk'
import { dirname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
-import chalk from 'chalk'
-
import { type ElementsPerWorkerType, type FileType, StorageType } from '../types/index.js'
import { WorkerProcessType } from '../worker/index.js'
import { Constants } from './Constants.js'
const prefix = isNotEmptyString(logPfx) ? `${logPfx} ` : ''
let logMsg: string
switch (error.code) {
- case 'ENOENT':
- logMsg = `${fileType} file ${file} not found: `
+ case 'EACCES':
+ logMsg = `${fileType} file ${file} access denied: `
break
case 'EEXIST':
logMsg = `${fileType} file ${file} already exists: `
break
- case 'EACCES':
- logMsg = `${fileType} file ${file} access denied: `
+ case 'ENOENT':
+ logMsg = `${fileType} file ${file} not found: `
break
case 'EPERM':
logMsg = `${fileType} file ${file} permission denied: `
!Number.isSafeInteger(elementsPerWorker)
) {
throw new SyntaxError(
- `Invalid number of elements per worker '${elementsPerWorker}' defined in configuration`
+ `Invalid number of elements per worker '${elementsPerWorker.toString()}' defined in configuration`
)
}
if (Number.isSafeInteger(elementsPerWorker) && (elementsPerWorker as number) <= 0) {
throw RangeError(
- `Invalid negative or zero number of elements per worker '${elementsPerWorker}' defined in configuration`
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `Invalid negative or zero number of elements per worker '${elementsPerWorker?.toString()}' defined in configuration`
)
}
}
type IncomingRequestCommand,
OCPPVersion,
type RequestCommand,
- VendorParametersKey
+ VendorParametersKey,
} from '../types/index.js'
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class Constants {
- // See https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
- private static readonly SEMVER_PATTERN =
- '^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$'
-
- private static readonly DEFAULT_CHARGING_STATION_RESET_TIME = 30000 // Ms
-
- static readonly DEFAULT_STATION_INFO: Partial<ChargingStationInfo> = Object.freeze({
- enableStatistics: false,
- autoStart: true,
- remoteAuthorization: true,
- currentOutType: CurrentType.AC,
- mainVoltageMeterValues: true,
- phaseLineToLineVoltageMeterValues: false,
- customValueLimitationMeterValues: true,
- ocppStrictCompliance: true,
- outOfOrderEndMeterValues: false,
- beginEndMeterValues: false,
- meteringPerTransaction: true,
- transactionDataMeterValues: false,
- supervisionUrlOcppConfiguration: false,
- supervisionUrlOcppKey: VendorParametersKey.ConnectionUrl,
- useConnectorId0: true,
- ocppVersion: OCPPVersion.VERSION_16,
- firmwareVersionPattern: Constants.SEMVER_PATTERN,
- firmwareUpgrade: {
- versionUpgrade: {
- step: 1
- },
- reset: true
- },
- ocppPersistentConfiguration: true,
- stationInfoPersistentConfiguration: true,
- automaticTransactionGeneratorPersistentConfiguration: true,
- resetTime: Constants.DEFAULT_CHARGING_STATION_RESET_TIME,
- autoReconnectMaxRetries: -1,
- registrationMaxRetries: -1,
- reconnectExponentialDelay: false,
- stopTransactionsOnStopped: true
- })
-
- static readonly DEFAULT_BOOT_NOTIFICATION_INTERVAL = 60000 // Ms
- static readonly DEFAULT_HEARTBEAT_INTERVAL = 60000 // Ms
- static readonly DEFAULT_METER_VALUES_INTERVAL = 60000 // Ms
-
- static readonly DEFAULT_ATG_WAIT_TIME = 1000 // Ms
static readonly DEFAULT_ATG_CONFIGURATION: AutomaticTransactionGeneratorConfiguration =
Object.freeze({
enable: false,
- minDuration: 60,
+ maxDelayBetweenTwoTransactions: 30,
maxDuration: 120,
minDelayBetweenTwoTransactions: 15,
- maxDelayBetweenTwoTransactions: 30,
+ minDuration: 60,
probabilityOfStart: 1,
+ stopAbsoluteDuration: false,
stopAfterHours: 0.25,
- stopAbsoluteDuration: false
})
- static readonly DEFAULT_CIRCULAR_BUFFER_CAPACITY = 385
+ static readonly DEFAULT_ATG_WAIT_TIME = 1000 // Ms
+
+ static readonly DEFAULT_BOOT_NOTIFICATION_INTERVAL = 60000 // Ms
+ static readonly DEFAULT_CIRCULAR_BUFFER_CAPACITY = 386
+ static readonly DEFAULT_CONNECTION_TIMEOUT = 30
+
+ static readonly DEFAULT_FLUCTUATION_PERCENT = 5
static readonly DEFAULT_HASH_ALGORITHM = 'sha384'
- static readonly DEFAULT_IDTAG = '00000000'
+ static readonly DEFAULT_HEARTBEAT_INTERVAL = 60000 // Ms
- static readonly DEFAULT_CONNECTION_TIMEOUT = 30
+ static readonly DEFAULT_IDTAG = '00000000'
static readonly DEFAULT_LOG_STATISTICS_INTERVAL = 60 // Seconds
- static readonly DEFAULT_FLUCTUATION_PERCENT = 5
+ static readonly DEFAULT_MESSAGE_BUFFER_FLUSH_INTERVAL = 60000 // Ms
+
+ static readonly DEFAULT_METER_VALUES_INTERVAL = 60000 // Ms
static readonly DEFAULT_PERFORMANCE_DIRECTORY = 'performance'
- static readonly DEFAULT_PERFORMANCE_RECORDS_FILENAME = 'performanceRecords.json'
+
static readonly DEFAULT_PERFORMANCE_RECORDS_DB_NAME = 'e-mobility-charging-stations-simulator'
- static readonly PERFORMANCE_RECORDS_TABLE = 'performance_records'
+ static readonly DEFAULT_PERFORMANCE_RECORDS_FILENAME = 'performanceRecords.json'
+ static readonly DEFAULT_STATION_INFO: Readonly<Partial<ChargingStationInfo>> = Object.freeze({
+ automaticTransactionGeneratorPersistentConfiguration: true,
+ autoReconnectMaxRetries: -1,
+ autoStart: true,
+ beginEndMeterValues: false,
+ currentOutType: CurrentType.AC,
+ customValueLimitationMeterValues: true,
+ enableStatistics: false,
+ firmwareUpgrade: {
+ reset: true,
+ versionUpgrade: {
+ step: 1,
+ },
+ },
+ // See https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
+ firmwareVersionPattern:
+ '^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$',
+ mainVoltageMeterValues: true,
+ meteringPerTransaction: true,
+ ocppPersistentConfiguration: true,
+ ocppStrictCompliance: true,
+ ocppVersion: OCPPVersion.VERSION_16,
+ outOfOrderEndMeterValues: false,
+ phaseLineToLineVoltageMeterValues: false,
+ reconnectExponentialDelay: false,
+ registrationMaxRetries: -1,
+ remoteAuthorization: true,
+ resetTime: 30000, // Ms
+ stationInfoPersistentConfiguration: true,
+ stopTransactionsOnStopped: true,
+ supervisionUrlOcppConfiguration: false,
+ supervisionUrlOcppKey: VendorParametersKey.ConnectionUrl,
+ transactionDataMeterValues: false,
+ useConnectorId0: true,
+ })
static readonly DEFAULT_UI_SERVER_HOST = 'localhost'
+
static readonly DEFAULT_UI_SERVER_PORT = 8080
+ static readonly EMPTY_FROZEN_OBJECT = Object.freeze({})
- static readonly UNKNOWN_OCPP_COMMAND = 'unknown OCPP command' as
- | RequestCommand
- | IncomingRequestCommand
+ static readonly EMPTY_FUNCTION = Object.freeze(() => {
+ /* This is intentional */
+ })
static readonly MAX_RANDOM_INTEGER = 281474976710655
- static readonly STOP_CHARGING_STATIONS_TIMEOUT = 60000 // Ms
+ static readonly PERFORMANCE_RECORDS_TABLE = 'performance_records'
- static readonly EMPTY_FROZEN_OBJECT = Object.freeze({})
- static readonly EMPTY_FUNCTION = Object.freeze(() => {
- /* This is intentional */
- })
+ static readonly STOP_CHARGING_STATIONS_TIMEOUT = 60000 // Ms
- static readonly DEFAULT_MESSAGE_BUFFER_FLUSH_INTERVAL = 60000 // Ms
+ static readonly UNKNOWN_OCPP_COMMAND = 'unknown OCPP command' as
+ | IncomingRequestCommand
+ | RequestCommand
private constructor () {
// This is intentional
// This is intentional
}
- static powerTotal (nbOfPhases: number, V: number, Iph: number, cosPhi = 1): number {
- return nbOfPhases * ACElectricUtils.powerPerPhase(V, Iph, cosPhi)
- }
-
- static powerPerPhase (V: number, Iph: number, cosPhi = 1): number {
- const powerPerPhase = V * Iph * cosPhi
- if (cosPhi === 1) {
- return powerPerPhase
+ static amperagePerPhaseFromPower (nbOfPhases: number, P: number, V: number, cosPhi = 1): number {
+ const amperage = ACElectricUtils.amperageTotalFromPower(P, V, cosPhi)
+ const amperagePerPhase = amperage / nbOfPhases
+ if (amperage % nbOfPhases === 0) {
+ return amperagePerPhase
}
- return Math.round(powerPerPhase)
+ return Math.round(amperagePerPhase)
}
static amperageTotal (nbOfPhases: number, Iph: number): number {
return Math.round(amperage)
}
- static amperagePerPhaseFromPower (nbOfPhases: number, P: number, V: number, cosPhi = 1): number {
- const amperage = ACElectricUtils.amperageTotalFromPower(P, V, cosPhi)
- const amperagePerPhase = amperage / nbOfPhases
- if (amperage % nbOfPhases === 0) {
- return amperagePerPhase
+ static powerPerPhase (V: number, Iph: number, cosPhi = 1): number {
+ const powerPerPhase = V * Iph * cosPhi
+ if (cosPhi === 1) {
+ return powerPerPhase
}
- return Math.round(amperagePerPhase)
+ return Math.round(powerPerPhase)
+ }
+
+ static powerTotal (nbOfPhases: number, V: number, Iph: number, cosPhi = 1): number {
+ return nbOfPhases * ACElectricUtils.powerPerPhase(V, Iph, cosPhi)
}
}
// This is intentional
}
- static power (V: number, I: number): number {
- return V * I
- }
-
static amperage (P: number, V: number): number {
const amperage = P / V
if (P % V === 0) {
}
return Math.round(amperage)
}
+
+ static power (V: number, I: number): number {
+ return V * I
+ }
}
-import process from 'node:process'
-
import chalk from 'chalk'
+import process from 'node:process'
import type { ChargingStation } from '../charging-station/index.js'
import type {
HandleErrorParams,
IncomingRequestCommand,
JsonType,
- RequestCommand
+ MessageType,
+ RequestCommand,
} from '../types/index.js'
+
+import { getMessageTypeString } from '../charging-station/ocpp/OCPPServiceUtils.js'
import { logger } from './Logger.js'
import { isNotEmptyString } from './Utils.js'
-const defaultErrorParams = {
- throwError: true,
- consoleOut: false
-} satisfies HandleErrorParams<EmptyObject>
+const moduleName = 'ErrorUtils'
export const handleUncaughtException = (): void => {
process.on('uncaughtException', (error: Error) => {
fileType: FileType,
error: NodeJS.ErrnoException,
logPrefix: string,
- params: HandleErrorParams<EmptyObject> = defaultErrorParams
+ params?: HandleErrorParams<EmptyObject>
): void => {
- setDefaultErrorParams(params)
+ params = {
+ ...{
+ consoleOut: false,
+ throwError: true,
+ },
+ ...params,
+ }
const prefix = isNotEmptyString(logPrefix) ? `${logPrefix} ` : ''
let logMsg: string
switch (error.code) {
- case 'ENOENT':
- logMsg = `${fileType} file ${file} not found:`
+ case 'EACCES':
+ logMsg = `${fileType} file ${file} access denied:`
break
case 'EEXIST':
logMsg = `${fileType} file ${file} already exists:`
break
- case 'EACCES':
- logMsg = `${fileType} file ${file} access denied:`
+ case 'ENOENT':
+ logMsg = `${fileType} file ${file} not found:`
break
case 'EPERM':
logMsg = `${fileType} file ${file} permission denied:`
export const handleSendMessageError = (
chargingStation: ChargingStation,
- commandName: RequestCommand | IncomingRequestCommand,
+ commandName: IncomingRequestCommand | RequestCommand,
+ messageType: MessageType,
error: Error,
- params: HandleErrorParams<EmptyObject> = { throwError: false, consoleOut: false }
+ params?: HandleErrorParams<EmptyObject>
): void => {
- setDefaultErrorParams(params, { throwError: false, consoleOut: false })
- logger.error(`${chargingStation.logPrefix()} Request command '${commandName}' error:`, error)
+ params = {
+ ...{
+ consoleOut: false,
+ throwError: false,
+ },
+ ...params,
+ }
+ logger.error(
+ `${chargingStation.logPrefix()} ${moduleName}.handleSendMessageError: Send ${getMessageTypeString(messageType)} command '${commandName}' error:`,
+ error
+ )
if (params.throwError === true) {
throw error
}
}
-export const setDefaultErrorParams = <T extends JsonType>(
- params: HandleErrorParams<T>,
- defaultParams: HandleErrorParams<T> = defaultErrorParams
-): HandleErrorParams<T> => {
- params = { ...defaultParams, ...params }
- return params
+export const handleIncomingRequestError = <T extends JsonType>(
+ chargingStation: ChargingStation,
+ commandName: IncomingRequestCommand,
+ error: Error,
+ params?: HandleErrorParams<T>
+): T | undefined => {
+ params = {
+ ...{
+ consoleOut: false,
+ throwError: true,
+ },
+ ...params,
+ }
+ logger.error(
+ `${chargingStation.logPrefix()} ${moduleName}.handleIncomingRequestError: Incoming request command '${commandName}' error:`,
+ error
+ )
+ if (params.throwError === false && params.errorResponse != null) {
+ return params.errorResponse
+ }
+ if (params.throwError === true && params.errorResponse == null) {
+ throw error
+ }
+ if (params.throwError === true && params.errorResponse != null) {
+ return params.errorResponse
+ }
}
import { type FSWatcher, readFileSync, watch, type WatchListener } from 'node:fs'
import type { FileType, JsonType } from '../types/index.js'
+
import { handleFileException } from './ErrorUtils.js'
import { logger } from './Logger.js'
import { isNotEmptyString } from './Utils.js'
(refreshedVariable = JSON.parse(readFileSync(file, 'utf8')) as T)
} catch (error) {
handleFileException(file, fileType, error as NodeJS.ErrnoException, logPrefix, {
- throwError: false
+ throwError: false,
})
}
}
return watch(file, listener)
} catch (error) {
handleFileException(file, fileType, error as NodeJS.ErrnoException, logPrefix, {
- throwError: false
+ throwError: false,
})
}
} else {
import type { FormatWrap } from 'logform'
+
import { createLogger, format, type transport } from 'winston'
-import TransportType from 'winston/lib/winston/transports/index.js'
import DailyRotateFile from 'winston-daily-rotate-file'
+import TransportType from 'winston/lib/winston/transports/index.js'
import { ConfigurationSection, type LogConfiguration } from '../types/index.js'
import { Configuration } from './Configuration.js'
),
level: 'error',
...(logMaxFiles != null && { maxFiles: logMaxFiles }),
- ...(logMaxSize != null && { maxSize: logMaxSize })
+ ...(logMaxSize != null && { maxSize: logMaxSize }),
}),
new DailyRotateFile({
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
filename: insertAt(logConfiguration.file!, '-%DATE%', logConfiguration.file!.indexOf('.log')),
...(logMaxFiles != null && { maxFiles: logMaxFiles }),
- ...(logMaxSize != null && { maxSize: logMaxSize })
- })
+ ...(logMaxSize != null && { maxSize: logMaxSize }),
+ }),
]
} else {
transports = [
new TransportType.File({
filename: logConfiguration.errorFile,
- level: 'error'
+ level: 'error',
}),
new TransportType.File({
- filename: logConfiguration.file
- })
+ filename: logConfiguration.file,
+ }),
]
}
-export const logger = createLogger({
- silent: logConfiguration.enabled === false,
- level: logConfiguration.level,
+const logger = createLogger({
format: format.combine(
format.splat(),
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
(format[logConfiguration.format! as keyof FormatWrap] as FormatWrap)()
),
- transports
+ level: logConfiguration.level,
+ silent: logConfiguration.enabled === false,
+ transports,
})
//
format.splat(),
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
(format[logConfiguration.format! as keyof FormatWrap] as FormatWrap)()
- )
+ ),
})
)
}
+
+export { logger }
-import { clone } from 'rambda'
+import { CircularBuffer } from 'mnemonist'
import type { ChargingStation } from '../charging-station/index.js'
+
import {
type ChargingStationData,
type ChargingStationWorkerMessage,
ChargingStationWorkerMessageEvents,
- type Statistics
+ type Statistics,
+ type TimestampedData,
} from '../types/index.js'
import {
buildChargingStationAutomaticTransactionGeneratorConfiguration,
buildConnectorsStatus,
buildEvsesStatus,
- OutputFormat
+ OutputFormat,
} from './ChargingStationConfigurationUtils.js'
export const buildAddedMessage = (
chargingStation: ChargingStation
): ChargingStationWorkerMessage<ChargingStationData> => {
return {
+ data: buildChargingStationDataPayload(chargingStation),
event: ChargingStationWorkerMessageEvents.added,
- data: buildChargingStationDataPayload(chargingStation)
}
}
chargingStation: ChargingStation
): ChargingStationWorkerMessage<ChargingStationData> => {
return {
+ data: buildChargingStationDataPayload(chargingStation),
event: ChargingStationWorkerMessageEvents.deleted,
- data: buildChargingStationDataPayload(chargingStation)
}
}
chargingStation: ChargingStation
): ChargingStationWorkerMessage<ChargingStationData> => {
return {
+ data: buildChargingStationDataPayload(chargingStation),
event: ChargingStationWorkerMessageEvents.started,
- data: buildChargingStationDataPayload(chargingStation)
}
}
chargingStation: ChargingStation
): ChargingStationWorkerMessage<ChargingStationData> => {
return {
+ data: buildChargingStationDataPayload(chargingStation),
event: ChargingStationWorkerMessageEvents.stopped,
- data: buildChargingStationDataPayload(chargingStation)
}
}
chargingStation: ChargingStation
): ChargingStationWorkerMessage<ChargingStationData> => {
return {
+ data: buildChargingStationDataPayload(chargingStation),
event: ChargingStationWorkerMessageEvents.updated,
- data: buildChargingStationDataPayload(chargingStation)
}
}
export const buildPerformanceStatisticsMessage = (
statistics: Statistics
): ChargingStationWorkerMessage<Statistics> => {
+ const statisticsData = [...statistics.statisticsData].map(([key, value]) => {
+ if (value.measurementTimeSeries instanceof CircularBuffer) {
+ value.measurementTimeSeries = value.measurementTimeSeries.toArray() as TimestampedData[]
+ }
+ return [key, value]
+ })
return {
+ data: {
+ createdAt: statistics.createdAt,
+ id: statistics.id,
+ name: statistics.name,
+ statisticsData,
+ updatedAt: statistics.updatedAt,
+ uri: statistics.uri,
+ },
event: ChargingStationWorkerMessageEvents.performanceStatistics,
- // FIXME: CircularBuffer is not structured-cloneable, rambda clone strips the whole statisticsData Map
- data: clone(statistics)
}
}
const buildChargingStationDataPayload = (chargingStation: ChargingStation): ChargingStationData => {
return {
- started: chargingStation.started,
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- stationInfo: chargingStation.stationInfo!,
+ bootNotificationResponse: chargingStation.bootNotificationResponse,
connectors: buildConnectorsStatus(chargingStation),
evses: buildEvsesStatus(chargingStation, OutputFormat.worker),
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
ocppConfiguration: chargingStation.ocppConfiguration!,
+ started: chargingStation.started,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ stationInfo: chargingStation.stationInfo!,
supervisionUrl: chargingStation.wsConnectionUrl.href,
wsState: chargingStation.wsConnection?.readyState,
- bootNotificationResponse: chargingStation.bootNotificationResponse,
...(chargingStation.automaticTransactionGenerator != null && {
automaticTransactionGenerator:
- buildChargingStationAutomaticTransactionGeneratorConfiguration(chargingStation)
- })
+ buildChargingStationAutomaticTransactionGeneratorConfiguration(chargingStation),
+ }),
}
}
-import { mean } from 'rambda'
+export const average = (dataSet: number[]): number => {
+ if (Array.isArray(dataSet) && dataSet.length === 0) {
+ return 0
+ }
+ if (Array.isArray(dataSet) && dataSet.length === 1) {
+ return dataSet[0]
+ }
+ return dataSet.reduce((accumulator, number) => accumulator + number, 0) / dataSet.length
+}
+
+export const median = (dataSet: number[]): number => {
+ if (Array.isArray(dataSet) && dataSet.length === 0) {
+ return 0
+ }
+ if (Array.isArray(dataSet) && dataSet.length === 1) {
+ return dataSet[0]
+ }
+ const sortedDataSet = dataSet.slice().sort((a, b) => a - b)
+ return (
+ (sortedDataSet[(sortedDataSet.length - 1) >> 1] + sortedDataSet[sortedDataSet.length >> 1]) / 2
+ )
+}
export const min = (...args: number[]): number =>
args.reduce((minimum, num) => (minimum < num ? minimum : num), Number.POSITIVE_INFINITY)
args.reduce((maximum, num) => (maximum > num ? maximum : num), Number.NEGATIVE_INFINITY)
// TODO: use order statistics tree https://en.wikipedia.org/wiki/Order_statistic_tree
-export const nthPercentile = (dataSet: number[], percentile: number): number => {
+export const percentile = (dataSet: number[], percentile: number): number => {
if (percentile < 0 && percentile > 100) {
throw new RangeError('Percentile is not between 0 and 100')
}
/**
* Computes the sample standard deviation of the given data set.
- *
* @param dataSet - Data set.
* @param dataSetAverage - Average of the data set.
* @returns The sample standard deviation of the given data set.
* @see https://en.wikipedia.org/wiki/Unbiased_estimation_of_standard_deviation
* @internal
*/
-export const stdDeviation = (dataSet: number[], dataSetAverage: number = mean(dataSet)): number => {
+export const std = (dataSet: number[], dataSetAverage: number = average(dataSet)): number => {
if (Array.isArray(dataSet) && (dataSet.length === 0 || dataSet.length === 1)) {
return 0
}
return Math.sqrt(
- dataSet.reduce((accumulator, num) => accumulator + Math.pow(num - dataSetAverage, 2), 0) /
+ dataSet.reduce((accumulator, num) => accumulator + (num - dataSetAverage) ** 2, 0) /
(dataSet.length - 1)
)
}
-import { getRandomValues, randomBytes, randomUUID } from 'node:crypto'
-import { env, nextTick } from 'node:process'
+import type { CircularBuffer } from 'mnemonist'
import {
formatDuration,
millisecondsToMinutes,
millisecondsToSeconds,
minutesToSeconds,
- secondsToMilliseconds
+ secondsToMilliseconds,
} from 'date-fns'
-import type { CircularBuffer } from 'mnemonist'
-import { is } from 'rambda'
+import { getRandomValues, randomBytes, randomUUID } from 'node:crypto'
+import { env } from 'node:process'
import {
type JsonType,
MapStringifyFormat,
type TimestampedData,
- WebSocketCloseEventStatusString
+ WebSocketCloseEventStatusString,
} from '../types/index.js'
+type NonEmptyArray<T> = [T, ...T[]]
+type ReadonlyNonEmptyArray<T> = readonly [T, ...(readonly T[])]
+
export const logPrefix = (prefixString = ''): string => {
return `${new Date().toLocaleString()}${prefixString}`
}
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export const once = <T extends (...args: any[]) => any>(fn: T): T => {
+ let hasBeenCalled = false
+ let result: ReturnType<T>
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ return function (this: any, ...args: Parameters<T>): ReturnType<T> {
+ if (!hasBeenCalled) {
+ hasBeenCalled = true
+ result = fn.apply(this, args) as ReturnType<T>
+ }
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+ return result
+ } as T
+}
+
+export const has = (property: PropertyKey, object: null | object | undefined): boolean => {
+ if (object == null) {
+ return false
+ }
+ return Object.hasOwn(object, property)
+}
+
+const type = (value: unknown): string => {
+ if (value === null) return 'Null'
+ if (value === undefined) return 'Undefined'
+ if (Number.isNaN(value)) return 'NaN'
+ if (Array.isArray(value)) return 'Array'
+ return Object.prototype.toString.call(value).slice(8, -1)
+}
+
+export const isEmpty = (value: unknown): boolean => {
+ const valueType = type(value)
+ if (['NaN', 'Null', 'Number', 'Undefined'].includes(valueType)) {
+ return false
+ }
+ if (!value) return true
+
+ if (valueType === 'Object') {
+ return Object.keys(value as Record<string, unknown>).length === 0
+ }
+
+ if (valueType === 'Array') {
+ return (value as unknown[]).length === 0
+ }
+
+ if (valueType === 'Map') {
+ return (value as Map<unknown, unknown>).size === 0
+ }
+
+ if (valueType === 'Set') {
+ return (value as Set<unknown>).size === 0
+ }
+
+ return false
+}
+
+const isObject = (value: unknown): value is object => {
+ return type(value) === 'Object'
+}
+
+export const mergeDeepRight = <T extends Record<string, unknown>>(
+ target: T,
+ source: Partial<T>
+): T => {
+ const output = { ...target }
+
+ if (isObject(target) && isObject(source)) {
+ Object.keys(source).forEach(key => {
+ if (isObject(source[key])) {
+ if (!(key in target)) {
+ Object.assign(output, { [key]: source[key] })
+ } else {
+ output[key] = mergeDeepRight(target[key], source[key])
+ }
+ } else {
+ Object.assign(output, { [key]: source[key] })
+ }
+ })
+ }
+
+ return output
+}
+
export const generateUUID = (): `${string}-${string}-${string}-${string}-${string}` => {
return randomUUID()
}
days,
hours,
minutes,
- seconds
+ seconds,
})
}
// More efficient time validation function than the one provided by date-fns
export const isValidDate = (date: Date | number | undefined): date is Date | number => {
if (typeof date === 'number') {
- return !isNaN(date)
+ return !Number.isNaN(date)
} else if (isDate(date)) {
- return !isNaN(date.getTime())
+ return !Number.isNaN(date.getTime())
}
return false
}
export const convertToDate = (
- value: Date | string | number | undefined | null
+ value: Date | null | number | string | undefined
): Date | undefined => {
if (value == null) {
return undefined
}
if (typeof value === 'string' || typeof value === 'number') {
const valueToDate = new Date(value)
- if (isNaN(valueToDate.getTime())) {
- throw new Error(`Cannot convert to date: '${value}'`)
+ if (Number.isNaN(valueToDate.getTime())) {
+ throw new Error(`Cannot convert to date: '${value.toString()}'`)
}
return valueToDate
}
}
let changedValue: number = value as number
if (typeof value === 'string') {
- changedValue = parseInt(value)
+ changedValue = Number.parseInt(value)
}
- if (isNaN(changedValue)) {
- throw new Error(`Cannot convert to integer: '${String(value)}'`)
+ if (Number.isNaN(changedValue)) {
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
+ throw new Error(`Cannot convert to integer: '${value.toString()}'`)
}
return changedValue
}
}
let changedValue: number = value as number
if (typeof value === 'string') {
- changedValue = parseFloat(value)
+ changedValue = Number.parseFloat(value)
}
- if (isNaN(changedValue)) {
- throw new Error(`Cannot convert to float: '${String(value)}'`)
+ if (Number.isNaN(changedValue)) {
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
+ throw new Error(`Cannot convert to float: '${value.toString()}'`)
}
return changedValue
}
/**
* Rounds the given number to the given scale.
* The rounding is done using the "round half away from zero" method.
- *
* @param numberValue - The number to round.
* @param scale - The scale to round to.
* @returns The rounded number.
*/
export const roundTo = (numberValue: number, scale: number): number => {
- const roundPower = Math.pow(10, scale)
+ const roundPower = 10 ** scale
return Math.round(numberValue * roundPower * (1 + Number.EPSILON)) / roundPower
}
): number => {
if (fluctuationPercent < 0 || fluctuationPercent > 100) {
throw new RangeError(
- `Fluctuation percent must be between 0 and 100. Actual value: ${fluctuationPercent}`
+ `Fluctuation percent must be between 0 and 100. Actual value: ${fluctuationPercent.toString()}`
)
}
if (fluctuationPercent === 0) {
return structuredClone<T>(object)
}
+type AsyncFunctionType<A extends unknown[], R> = (...args: A) => PromiseLike<R>
+
/**
* Detects whether the given value is an asynchronous function or not.
- *
* @param fn - Unknown value.
* @returns `true` if `fn` was an asynchronous function, otherwise `false`.
* @internal
*/
-export const isAsyncFunction = (fn: unknown): fn is (...args: unknown[]) => Promise<unknown> => {
- return is(Function, fn) && fn.constructor.name === 'AsyncFunction'
-}
-
-export const isObject = (value: unknown): value is object => {
- return value != null && !Array.isArray(value) && is(Object, value)
-}
-
-export const hasOwnProp = (value: unknown, property: PropertyKey): boolean => {
- return isObject(value) && Object.hasOwn(value, property)
+export const isAsyncFunction = (fn: unknown): fn is AsyncFunctionType<unknown[], unknown> => {
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
+ return fn?.constructor === (async () => {}).constructor
}
export const isCFEnvironment = (): boolean => {
return env.VCAP_APPLICATION != null
}
-export const isNotEmptyString = (value: unknown): value is string => {
+declare const nonEmptyString: unique symbol
+type NonEmptyString = string & { [nonEmptyString]: true }
+export const isNotEmptyString = (value: unknown): value is NonEmptyString => {
return typeof value === 'string' && value.trim().length > 0
}
-export const isNotEmptyArray = (value: unknown): value is unknown[] => {
+export const isNotEmptyArray = <T>(
+ value: unknown
+): value is NonEmptyArray<T> | ReadonlyNonEmptyArray<T> => {
return Array.isArray(value) && value.length > 0
}
/**
* Computes the retry delay in milliseconds using an exponential backoff algorithm.
- *
* @param retryNumber - the number of retries that have already been attempted
* @param delayFactor - the base delay factor in milliseconds
* @returns delay in milliseconds
*/
export const exponentialDelay = (retryNumber = 0, delayFactor = 100): number => {
- const delay = Math.pow(2, retryNumber) * delayFactor
+ const delay = 2 ** retryNumber * delayFactor
const randomSum = delay * 0.2 * secureRandom() // 0-20% of the delay
return delay + randomSum
}
/**
* Generates a cryptographically secure random number in the [0,1[ range
- *
* @returns A number in the [0,1[ range
*/
export const secureRandom = (): number => {
}
export const JSONStringify = <
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
T extends
- | JsonType
- | Array<Record<string, unknown>>
- | Set<Record<string, unknown>>
- | Map<string, Record<string, unknown>>
+ | JsonType
+ | Map<string, Record<string, unknown>>
+ | Record<string, unknown>[]
+ | Set<Record<string, unknown>>
>(
object: T,
- space?: string | number,
+ space?: number | string,
mapFormat?: MapStringifyFormat
): string => {
return JSON.stringify(
object,
(_, value: Record<string, unknown>) => {
- if (is(Map, value)) {
+ if (value instanceof Map) {
switch (mapFormat) {
case MapStringifyFormat.object:
- return { ...Object.fromEntries<Map<string, Record<string, unknown>>>(value.entries()) }
+ return {
+ ...Object.fromEntries<Map<string, Record<string, unknown>>>(value.entries()),
+ }
case MapStringifyFormat.array:
default:
return [...value]
}
- } else if (is(Set, value)) {
- return [...value] as JsonType[]
+ } else if (value instanceof Set) {
+ return [...value] as Record<string, unknown>[]
}
return value
},
/**
* Converts websocket error code to human readable string message
- *
* @param code - websocket error code
* @returns human readable string message
*/
}
export const isArraySorted = <T>(array: T[], compareFn: (a: T, b: T) => number): boolean => {
+ if (array.length <= 1) {
+ return true
+ }
for (let index = 0; index < array.length - 1; ++index) {
if (compareFn(array[index], array[index + 1]) > 0) {
return false
return true
}
-export const throwErrorInNextTick = (error: Error): void => {
- nextTick(() => {
+export const queueMicrotaskErrorThrowing = (error: Error): void => {
+ queueMicrotask(() => {
throw error
})
}
buildChargingStationAutomaticTransactionGeneratorConfiguration,
buildConnectorsStatus,
buildEvsesStatus,
- OutputFormat
+ OutputFormat,
} from './ChargingStationConfigurationUtils.js'
export { Configuration } from './Configuration.js'
export { Constants } from './Constants.js'
export { ACElectricUtils, DCElectricUtils } from './ElectricUtils.js'
export {
handleFileException,
+ handleIncomingRequestError,
handleSendMessageError,
handleUncaughtException,
handleUnhandledRejection,
- setDefaultErrorParams
} from './ErrorUtils.js'
export { watchJsonFile } from './FileUtils.js'
export { logger } from './Logger.js'
buildPerformanceStatisticsMessage,
buildStartedMessage,
buildStoppedMessage,
- buildUpdatedMessage
+ buildUpdatedMessage,
} from './MessageChannelUtils.js'
-export { max, min, nthPercentile, stdDeviation } from './StatisticUtils.js'
+export { average, max, median, min, percentile, std } from './StatisticUtils.js'
export {
clone,
convertToBoolean,
getRandomFloatFluctuatedRounded,
getRandomFloatRounded,
getWebSocketCloseEventStatusString,
+ has,
isArraySorted,
isAsyncFunction,
+ isEmpty,
isNotEmptyArray,
isNotEmptyString,
isValidDate,
JSONStringify,
logPrefix,
+ mergeDeepRight,
+ once,
roundTo,
secureRandom,
sleep,
- validateUUID
+ validateUUID,
} from './Utils.js'
import type { EventEmitterAsyncResource } from 'node:events'
-import { existsSync } from 'node:fs'
-
import type { PoolInfo } from 'poolifier'
+import { existsSync } from 'node:fs'
+
import type { SetInfo, WorkerData, WorkerOptions } from './WorkerTypes.js'
export abstract class WorkerAbstract<D extends WorkerData, R extends WorkerData> {
- protected readonly workerScript: string
- protected readonly workerOptions: WorkerOptions
+ public abstract readonly emitter: EventEmitterAsyncResource | undefined
public abstract readonly info: PoolInfo | SetInfo
- public abstract readonly size: number
public abstract readonly maxElementsPerWorker: number | undefined
- public abstract readonly emitter: EventEmitterAsyncResource | undefined
+ public abstract readonly size: number
+
+ protected readonly workerOptions: WorkerOptions
+ protected readonly workerScript: string
/**
* `WorkerAbstract` constructor.
- *
* @param workerScript -
* @param workerOptions -
*/
this.workerOptions = workerOptions
}
+ /**
+ * Adds a task element to the worker pool/set.
+ * @param elementData -
+ */
+ public abstract addElement (elementData: D): Promise<R>
/**
* Starts the worker pool/set.
*/
- public abstract start (): void | Promise<void>
+ public abstract start (): Promise<void> | void
/**
* Stops the worker pool/set.
*/
public abstract stop (): Promise<void>
- /**
- * Adds a task element to the worker pool/set.
- *
- * @param elementData -
- */
- public abstract addElement (elementData: D): Promise<R>
}
import { availableParallelism } from 'poolifier'
import type { WorkerOptions } from './WorkerTypes.js'
+
import { defaultErrorHandler, defaultExitHandler } from './WorkerUtils.js'
export const EMPTY_FUNCTION = Object.freeze(() => {
export const DEFAULT_POOL_MAX_SIZE = Math.round(availableParallelism() * 1.5)
export const DEFAULT_ELEMENTS_PER_WORKER = 1
-export const DEFAULT_WORKER_OPTIONS: WorkerOptions = Object.freeze({
- workerStartDelay: DEFAULT_WORKER_START_DELAY,
+export const DEFAULT_WORKER_OPTIONS: Readonly<WorkerOptions> = Object.freeze({
elementAddDelay: DEFAULT_ELEMENT_ADD_DELAY,
- poolMinSize: DEFAULT_POOL_MIN_SIZE,
- poolMaxSize: DEFAULT_POOL_MAX_SIZE,
elementsPerWorker: DEFAULT_ELEMENTS_PER_WORKER,
+ poolMaxSize: DEFAULT_POOL_MAX_SIZE,
+ poolMinSize: DEFAULT_POOL_MIN_SIZE,
poolOptions: {
- startWorkers: false,
enableEvents: true,
- restartWorkerOnError: true,
errorHandler: defaultErrorHandler,
- exitHandler: defaultExitHandler
- }
+ exitHandler: defaultExitHandler,
+ restartWorkerOnError: true,
+ startWorkers: false,
+ },
+ workerStartDelay: DEFAULT_WORKER_START_DELAY,
})
import { DynamicThreadPool, type PoolInfo } from 'poolifier'
-import { WorkerAbstract } from './WorkerAbstract.js'
import type { WorkerData, WorkerOptions } from './WorkerTypes.js'
+
+import { WorkerAbstract } from './WorkerAbstract.js'
import { randomizeDelay, sleep } from './WorkerUtils.js'
export class WorkerDynamicPool<D extends WorkerData, R extends WorkerData> extends WorkerAbstract<
-D,
-R
+ D,
+ R
> {
+ get emitter (): EventEmitterAsyncResource | undefined {
+ return this.pool.emitter
+ }
+
+ get info (): PoolInfo {
+ return this.pool.info
+ }
+
+ get maxElementsPerWorker (): number | undefined {
+ return undefined
+ }
+
+ get size (): number {
+ return this.pool.info.workerNodes
+ }
+
private readonly pool: DynamicThreadPool<D, R>
/**
* Creates a new `WorkerDynamicPool`.
- *
* @param workerScript -
* @param workerOptions -
*/
)
}
- get info (): PoolInfo {
- return this.pool.info
- }
-
- get size (): number {
- return this.pool.info.workerNodes
- }
-
- get maxElementsPerWorker (): number | undefined {
- return undefined
- }
-
- get emitter (): EventEmitterAsyncResource | undefined {
- return this.pool.emitter
+ /** @inheritDoc */
+ public async addElement (elementData: D): Promise<R> {
+ const response = await this.pool.execute(elementData)
+ // Start element sequentially to optimize memory at startup
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.workerOptions.elementAddDelay! > 0 &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ (await sleep(randomizeDelay(this.workerOptions.elementAddDelay!)))
+ return response
}
/** @inheritDoc */
public async stop (): Promise<void> {
await this.pool.destroy()
}
-
- /** @inheritDoc */
- public async addElement (elementData: D): Promise<R> {
- const response = await this.pool.execute(elementData)
- // Start element sequentially to optimize memory at startup
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.workerOptions.elementAddDelay! > 0 &&
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- (await sleep(randomizeDelay(this.workerOptions.elementAddDelay!)))
- return response
- }
}
import { isMainThread } from 'node:worker_threads'
-import { mergeDeepRight } from 'rambda'
-
import type { WorkerAbstract } from './WorkerAbstract.js'
+
+import { mergeDeepRight } from '../utils/index.js'
import { DEFAULT_WORKER_OPTIONS } from './WorkerConstants.js'
import { WorkerDynamicPool } from './WorkerDynamicPool.js'
import { WorkerFixedPool } from './WorkerFixedPool.js'
}
workerOptions = mergeDeepRight<WorkerOptions>(DEFAULT_WORKER_OPTIONS, workerOptions ?? {})
switch (workerProcessType) {
- case WorkerProcessType.workerSet:
- return new WorkerSet<D, R>(workerScript, workerOptions)
- case WorkerProcessType.fixedPool:
- return new WorkerFixedPool<D, R>(workerScript, workerOptions)
case WorkerProcessType.dynamicPool:
return new WorkerDynamicPool<D, R>(workerScript, workerOptions)
+ case WorkerProcessType.fixedPool:
+ return new WorkerFixedPool<D, R>(workerScript, workerOptions)
+ case WorkerProcessType.workerSet:
+ return new WorkerSet<D, R>(workerScript, workerOptions)
default:
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
throw new Error(`Worker implementation type '${workerProcessType}' not found`)
import { FixedThreadPool, type PoolInfo } from 'poolifier'
-import { WorkerAbstract } from './WorkerAbstract.js'
import type { WorkerData, WorkerOptions } from './WorkerTypes.js'
+
+import { WorkerAbstract } from './WorkerAbstract.js'
import { randomizeDelay, sleep } from './WorkerUtils.js'
export class WorkerFixedPool<D extends WorkerData, R extends WorkerData> extends WorkerAbstract<
-D,
-R
+ D,
+ R
> {
+ get emitter (): EventEmitterAsyncResource | undefined {
+ return this.pool.emitter
+ }
+
+ get info (): PoolInfo {
+ return this.pool.info
+ }
+
+ get maxElementsPerWorker (): number | undefined {
+ return undefined
+ }
+
+ get size (): number {
+ return this.pool.info.workerNodes
+ }
+
private readonly pool: FixedThreadPool<D, R>
/**
* Creates a new `WorkerFixedPool`.
- *
* @param workerScript -
* @param workerOptions -
*/
)
}
- get info (): PoolInfo {
- return this.pool.info
- }
-
- get size (): number {
- return this.pool.info.workerNodes
- }
-
- get maxElementsPerWorker (): number | undefined {
- return undefined
- }
-
- get emitter (): EventEmitterAsyncResource | undefined {
- return this.pool.emitter
+ /** @inheritDoc */
+ public async addElement (elementData: D): Promise<R> {
+ const response = await this.pool.execute(elementData)
+ // Start element sequentially to optimize memory at startup
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ this.workerOptions.elementAddDelay! > 0 &&
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ (await sleep(randomizeDelay(this.workerOptions.elementAddDelay!)))
+ return response
}
/** @inheritDoc */
public async stop (): Promise<void> {
await this.pool.destroy()
}
-
- /** @inheritDoc */
- public async addElement (elementData: D): Promise<R> {
- const response = await this.pool.execute(elementData)
- // Start element sequentially to optimize memory at startup
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- this.workerOptions.elementAddDelay! > 0 &&
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- (await sleep(randomizeDelay(this.workerOptions.elementAddDelay!)))
- return response
- }
}
WorkerMessageEvents,
type WorkerOptions,
type WorkerSetElement,
- WorkerSetEvents
+ WorkerSetEvents,
} from './WorkerTypes.js'
import { randomizeDelay, sleep } from './WorkerUtils.js'
interface ResponseWrapper<R extends WorkerData> {
- resolve: (value: R | PromiseLike<R>) => void
reject: (reason?: unknown) => void
+ resolve: (value: PromiseLike<R> | R) => void
workerSetElement: WorkerSetElement
}
export class WorkerSet<D extends WorkerData, R extends WorkerData> extends WorkerAbstract<D, R> {
public readonly emitter: EventEmitterAsyncResource | undefined
- private readonly workerSet: Set<WorkerSetElement>
+
+ get info (): SetInfo {
+ return {
+ elementsExecuting: [...this.workerSet].reduce(
+ (accumulator, workerSetElement) => accumulator + workerSetElement.numberOfWorkerElements,
+ 0
+ ),
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ elementsPerWorker: this.maxElementsPerWorker!,
+ size: this.size,
+ started: this.started,
+ type: 'set',
+ version: workerSetVersion,
+ worker: 'thread',
+ }
+ }
+
+ get maxElementsPerWorker (): number | undefined {
+ return this.workerOptions.elementsPerWorker
+ }
+
+ get size (): number {
+ return this.workerSet.size
+ }
+
private readonly promiseResponseMap: Map<
`${string}-${string}-${string}-${string}`,
- ResponseWrapper<R>
+ ResponseWrapper<R>
>
private started: boolean
+ private readonly workerSet: Set<WorkerSetElement>
private workerStartup: boolean
/**
* Creates a new `WorkerSet`.
- *
* @param workerScript -
* @param workerOptions -
*/
this.workerSet = new Set<WorkerSetElement>()
this.promiseResponseMap = new Map<
`${string}-${string}-${string}-${string}`,
- ResponseWrapper<R>
+ ResponseWrapper<R>
>()
if (this.workerOptions.poolOptions?.enableEvents === true) {
this.emitter = new EventEmitterAsyncResource({ name: 'workerset' })
this.workerStartup = false
}
- get info (): SetInfo {
- return {
- version: workerSetVersion,
- type: 'set',
- worker: 'thread',
- started: this.started,
- size: this.size,
- elementsExecuting: [...this.workerSet].reduce(
- (accumulator, workerSetElement) => accumulator + workerSetElement.numberOfWorkerElements,
- 0
- ),
+ /** @inheritDoc */
+ public async addElement (elementData: D): Promise<R> {
+ if (!this.started) {
+ throw new Error('Cannot add a WorkerSet element: not started')
+ }
+ const workerSetElement = await this.getWorkerSetElement()
+ const sendMessageToWorker = new Promise<R>((resolve, reject) => {
+ const message = {
+ data: elementData,
+ event: WorkerMessageEvents.addWorkerElement,
+ uuid: randomUUID(),
+ } satisfies WorkerMessage<D>
+ workerSetElement.worker.postMessage(message)
+ this.promiseResponseMap.set(message.uuid, {
+ reject,
+ resolve,
+ workerSetElement,
+ })
+ })
+ const response = await sendMessageToWorker
+ // Add element sequentially to optimize memory at startup
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ if (this.workerOptions.elementAddDelay! > 0) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- elementsPerWorker: this.maxElementsPerWorker!
+ await sleep(randomizeDelay(this.workerOptions.elementAddDelay!))
}
- }
-
- get size (): number {
- return this.workerSet.size
- }
-
- get maxElementsPerWorker (): number | undefined {
- return this.workerOptions.elementsPerWorker
+ return response
}
/** @inheritDoc */
this.emitter?.emitDestroy()
}
- /** @inheritDoc */
- public async addElement (elementData: D): Promise<R> {
- if (!this.started) {
- throw new Error('Cannot add a WorkerSet element: not started')
- }
- const workerSetElement = await this.getWorkerSetElement()
- const sendMessageToWorker = new Promise<R>((resolve, reject) => {
- const message = {
- uuid: randomUUID(),
- event: WorkerMessageEvents.addWorkerElement,
- data: elementData
- } satisfies WorkerMessage<D>
- workerSetElement.worker.postMessage(message)
- this.promiseResponseMap.set(message.uuid, { resolve, reject, workerSetElement })
- })
- const response = await sendMessageToWorker
- // Add element sequentially to optimize memory at startup
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- if (this.workerOptions.elementAddDelay! > 0) {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- await sleep(randomizeDelay(this.workerOptions.elementAddDelay!))
- }
- return response
- }
-
/**
* Adds a new `WorkerSetElement`.
+ * @returns The new `WorkerSetElement`.
*/
private addWorkerSetElement (): WorkerSetElement {
this.workerStartup = true
const worker = new Worker(this.workerScript, {
env: SHARE_ENV,
- ...this.workerOptions.poolOptions?.workerOptions
+ ...this.workerOptions.poolOptions?.workerOptions,
})
worker.on('message', this.workerOptions.poolOptions?.messageHandler ?? EMPTY_FUNCTION)
worker.on('message', (message: WorkerMessage<R>) => {
- const { uuid, event, data } = message
+ const { data, event, uuid } = message
if (this.promiseResponseMap.has(uuid)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const { resolve, reject, workerSetElement } = this.promiseResponseMap.get(uuid)!
+ const { reject, resolve, workerSetElement } = this.promiseResponseMap.get(uuid)!
switch (event) {
case WorkerMessageEvents.addedWorkerElement:
this.emitter?.emit(WorkerSetEvents.elementAdded, this.info)
this.addWorkerSetElement()
}
worker.unref()
+ // eslint-disable-next-line promise/no-promise-in-callback
worker.terminate().catch((error: unknown) => this.emitter?.emit(WorkerSetEvents.error, error))
})
worker.on('online', this.workerOptions.poolOptions?.onlineHandler ?? EMPTY_FUNCTION)
worker.once('exit', () => {
this.removeWorkerSetElement(this.getWorkerSetElementByWorker(worker))
})
- const workerSetElement: WorkerSetElement = { worker, numberOfWorkerElements: 0 }
+ const workerSetElement: WorkerSetElement = {
+ numberOfWorkerElements: 0,
+ worker,
+ }
this.workerSet.add(workerSetElement)
this.workerStartup = false
return workerSetElement
}
- private removeWorkerSetElement (workerSetElement: WorkerSetElement | undefined): void {
- if (workerSetElement == null) {
- return
- }
- this.workerSet.delete(workerSetElement)
- }
-
private async getWorkerSetElement (): Promise<WorkerSetElement> {
- let chosenWorkerSetElement: WorkerSetElement | undefined
+ let chosenWorkerSetElement: undefined | WorkerSetElement
for (const workerSetElement of this.workerSet) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (workerSetElement.numberOfWorkerElements < this.workerOptions.elementsPerWorker!) {
return chosenWorkerSetElement
}
- private getWorkerSetElementByWorker (worker: Worker): WorkerSetElement | undefined {
- let workerSetElt: WorkerSetElement | undefined
+ private getWorkerSetElementByWorker (worker: Worker): undefined | WorkerSetElement {
+ let workerSetElt: undefined | WorkerSetElement
for (const workerSetElement of this.workerSet) {
if (workerSetElement.worker.threadId === worker.threadId) {
workerSetElt = workerSetElement
}
return workerSetElt
}
+
+ private removeWorkerSetElement (workerSetElement: undefined | WorkerSetElement): void {
+ if (workerSetElement == null) {
+ return
+ }
+ this.workerSet.delete(workerSetElement)
+ }
}
import { type PoolEvent, PoolEvents, type ThreadPoolOptions } from 'poolifier'
+export enum WorkerMessageEvents {
+ addedWorkerElement = 'addedWorkerElement',
+ addWorkerElement = 'addWorkerElement',
+ workerElementError = 'workerElementError',
+}
+
export enum WorkerProcessType {
- workerSet = 'workerSet',
- fixedPool = 'fixedPool',
/** @experimental */
- dynamicPool = 'dynamicPool'
+ dynamicPool = 'dynamicPool',
+ fixedPool = 'fixedPool',
+ workerSet = 'workerSet',
+}
+
+export enum WorkerSetEvents {
+ elementAdded = 'elementAdded',
+ elementError = 'elementError',
+ error = 'error',
+ started = 'started',
+ stopped = 'stopped',
}
export interface SetInfo {
- version: string
- type: string
- worker: string
- started: boolean
- size: number
elementsExecuting: number
elementsPerWorker: number
+ size: number
+ started: boolean
+ type: string
+ version: string
+ worker: string
}
-export enum WorkerSetEvents {
- started = 'started',
- stopped = 'stopped',
- error = 'error',
- elementAdded = 'elementAdded',
- elementError = 'elementError'
+export type WorkerData = Record<string, unknown>
+
+export interface WorkerDataError extends WorkerData {
+ event: WorkerMessageEvents
+ message: string
+ name: string
+ stack?: string
}
export const WorkerEvents = {
...PoolEvents,
- ...WorkerSetEvents
+ ...WorkerSetEvents,
} as const
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type WorkerEvents = PoolEvent | WorkerSetEvents
-export interface WorkerOptions {
- workerStartDelay?: number
+export interface WorkerMessage<T extends WorkerData> {
+ data: T
+ event: WorkerMessageEvents
+ uuid: `${string}-${string}-${string}-${string}`
+}
+
+export interface WorkerOptions extends Record<string, unknown> {
elementAddDelay?: number
+ elementsPerWorker?: number
poolMaxSize: number
poolMinSize: number
- elementsPerWorker?: number
poolOptions?: ThreadPoolOptions
-}
-
-export type WorkerData = Record<string, unknown>
-
-export interface WorkerDataError extends WorkerData {
- event: WorkerMessageEvents
- name: string
- message: string
- stack?: string
+ workerStartDelay?: number
}
export interface WorkerSetElement {
- worker: Worker
numberOfWorkerElements: number
-}
-
-export interface WorkerMessage<T extends WorkerData> {
- uuid: `${string}-${string}-${string}-${string}`
- event: WorkerMessageEvents
- data: T
-}
-
-export enum WorkerMessageEvents {
- addWorkerElement = 'addWorkerElement',
- addedWorkerElement = 'addedWorkerElement',
- workerElementError = 'workerElementError'
+ worker: Worker
}
-import { getRandomValues } from 'node:crypto'
-
import chalk from 'chalk'
+import { getRandomValues } from 'node:crypto'
export const sleep = async (milliSeconds: number): Promise<NodeJS.Timeout> => {
return await new Promise<NodeJS.Timeout>(resolve =>
/**
* Generates a cryptographically secure random number in the [0,1[ range
- *
* @returns A number in the [0,1[ range
* @internal
*/
DEFAULT_ELEMENTS_PER_WORKER,
DEFAULT_POOL_MAX_SIZE,
DEFAULT_POOL_MIN_SIZE,
- DEFAULT_WORKER_START_DELAY
+ DEFAULT_WORKER_START_DELAY,
} from './WorkerConstants.js'
export { WorkerFactory } from './WorkerFactory.js'
export {
WorkerEvents,
type WorkerMessage,
WorkerMessageEvents,
- WorkerProcessType
+ WorkerProcessType,
} from './WorkerTypes.js'
--- /dev/null
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+
+import { expect } from '@std/expect'
+import { describe, it } from 'node:test'
+
+import type { ChargingStation } from '../../src/charging-station/index.js'
+
+import {
+ checkChargingStationState,
+ checkConfiguration,
+ checkStationInfoConnectorStatus,
+ checkTemplate,
+ getChargingStationId,
+ getHashId,
+ getMaxNumberOfEvses,
+ getPhaseRotationValue,
+ validateStationInfo,
+} from '../../src/charging-station/Helpers.js'
+import { BaseError } from '../../src/exception/index.js'
+import {
+ type ChargingStationConfiguration,
+ type ChargingStationInfo,
+ type ChargingStationTemplate,
+ type ConnectorStatus,
+ ConnectorStatusEnum,
+ type EvseStatus,
+ OCPPVersion,
+} from '../../src/types/index.js'
+import { logger } from '../../src/utils/Logger.js'
+
+await describe('Helpers test suite', async () => {
+ const baseName = 'CS-TEST'
+ const chargingStationTemplate = {
+ baseName,
+ } as ChargingStationTemplate
+ const chargingStation = {
+ connectors: new Map<number, ConnectorStatus>(),
+ evses: new Map<number, EvseStatus>(),
+ logPrefix: () => `${baseName} |`,
+ started: false,
+ } as ChargingStation
+
+ await it('Verify getChargingStationId()', () => {
+ expect(getChargingStationId(1, chargingStationTemplate)).toBe(`${baseName}-00001`)
+ })
+
+ await it('Verify getHashId()', () => {
+ expect(getHashId(1, chargingStationTemplate)).toBe(
+ 'b4b1e8ec4fca79091d99ea9a7ea5901548010e6c0e98be9296f604b9d68734444dfdae73d7d406b6124b42815214d088'
+ )
+ })
+
+ await it('Verify validateStationInfo()', () => {
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).toThrow(new BaseError('Missing charging station information'))
+ chargingStation.stationInfo = {} as ChargingStationInfo
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).toThrow(new BaseError('Missing charging station information'))
+ chargingStation.stationInfo.baseName = baseName
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).toThrow(new BaseError('Missing chargingStationId in stationInfo properties'))
+ chargingStation.stationInfo.chargingStationId = ''
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).toThrow(new BaseError('Missing chargingStationId in stationInfo properties'))
+ chargingStation.stationInfo.chargingStationId = getChargingStationId(1, chargingStationTemplate)
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).toThrow(new BaseError(`${baseName}-00001: Missing hashId in stationInfo properties`))
+ chargingStation.stationInfo.hashId = ''
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).toThrow(new BaseError(`${baseName}-00001: Missing hashId in stationInfo properties`))
+ chargingStation.stationInfo.hashId = getHashId(1, chargingStationTemplate)
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).toThrow(new BaseError(`${baseName}-00001: Missing templateIndex in stationInfo properties`))
+ chargingStation.stationInfo.templateIndex = 0
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).toThrow(
+ new BaseError(`${baseName}-00001: Invalid templateIndex value in stationInfo properties`)
+ )
+ chargingStation.stationInfo.templateIndex = 1
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).toThrow(new BaseError(`${baseName}-00001: Missing templateName in stationInfo properties`))
+ chargingStation.stationInfo.templateName = ''
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).toThrow(new BaseError(`${baseName}-00001: Missing templateName in stationInfo properties`))
+ chargingStation.stationInfo.templateName = 'test-template.json'
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).toThrow(new BaseError(`${baseName}-00001: Missing maximumPower in stationInfo properties`))
+ chargingStation.stationInfo.maximumPower = 0
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).toThrow(
+ new RangeError(`${baseName}-00001: Invalid maximumPower value in stationInfo properties`)
+ )
+ chargingStation.stationInfo.maximumPower = 12000
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).toThrow(
+ new BaseError(`${baseName}-00001: Missing maximumAmperage in stationInfo properties`)
+ )
+ chargingStation.stationInfo.maximumAmperage = 0
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).toThrow(
+ new RangeError(`${baseName}-00001: Invalid maximumAmperage value in stationInfo properties`)
+ )
+ chargingStation.stationInfo.maximumAmperage = 16
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).not.toThrow()
+ chargingStation.stationInfo.ocppVersion = OCPPVersion.VERSION_20
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).toThrow(
+ new BaseError(
+ `${baseName}-00001: OCPP 2.0 or superior requires at least one EVSE defined in the charging station template/configuration`
+ )
+ )
+ chargingStation.stationInfo.ocppVersion = OCPPVersion.VERSION_201
+ expect(() => {
+ validateStationInfo(chargingStation)
+ }).toThrow(
+ new BaseError(
+ `${baseName}-00001: OCPP 2.0 or superior requires at least one EVSE defined in the charging station template/configuration`
+ )
+ )
+ })
+
+ await it('Verify checkChargingStationState()', t => {
+ t.mock.method(logger, 'warn')
+ expect(checkChargingStationState(chargingStation, 'log prefix |')).toBe(false)
+ expect(logger.warn.mock.calls.length).toBe(1)
+ chargingStation.starting = true
+ expect(checkChargingStationState(chargingStation, 'log prefix |')).toBe(true)
+ expect(logger.warn.mock.calls.length).toBe(1)
+ chargingStation.started = true
+ expect(checkChargingStationState(chargingStation, 'log prefix |')).toBe(true)
+ expect(logger.warn.mock.calls.length).toBe(1)
+ })
+
+ await it('Verify getPhaseRotationValue()', () => {
+ expect(getPhaseRotationValue(0, 0)).toBe('0.RST')
+ expect(getPhaseRotationValue(1, 0)).toBe('1.NotApplicable')
+ expect(getPhaseRotationValue(2, 0)).toBe('2.NotApplicable')
+ expect(getPhaseRotationValue(0, 1)).toBe('0.NotApplicable')
+ expect(getPhaseRotationValue(1, 1)).toBe('1.NotApplicable')
+ expect(getPhaseRotationValue(2, 1)).toBe('2.NotApplicable')
+ expect(getPhaseRotationValue(0, 2)).toBeUndefined()
+ expect(getPhaseRotationValue(1, 2)).toBeUndefined()
+ expect(getPhaseRotationValue(2, 2)).toBeUndefined()
+ expect(getPhaseRotationValue(0, 3)).toBe('0.RST')
+ expect(getPhaseRotationValue(1, 3)).toBe('1.RST')
+ expect(getPhaseRotationValue(2, 3)).toBe('2.RST')
+ })
+
+ await it('Verify getMaxNumberOfEvses()', () => {
+ expect(getMaxNumberOfEvses(undefined)).toBe(-1)
+ expect(getMaxNumberOfEvses({})).toBe(0)
+ })
+
+ await it('Verify checkTemplate()', t => {
+ t.mock.method(logger, 'warn')
+ t.mock.method(logger, 'error')
+ expect(() => {
+ checkTemplate(undefined, 'log prefix |', 'test-template.json')
+ }).toThrow(new BaseError('Failed to read charging station template file test-template.json'))
+ expect(logger.error.mock.calls.length).toBe(1)
+ expect(() => {
+ checkTemplate({} as ChargingStationTemplate, 'log prefix |', 'test-template.json')
+ }).toThrow(
+ new BaseError('Empty charging station information from template file test-template.json')
+ )
+ expect(logger.error.mock.calls.length).toBe(2)
+ checkTemplate(chargingStationTemplate, 'log prefix |', 'test-template.json')
+ expect(logger.warn.mock.calls.length).toBe(1)
+ })
+
+ await it('Verify checkConfiguration()', t => {
+ t.mock.method(logger, 'error')
+ expect(() => {
+ checkConfiguration(undefined, 'log prefix |', 'configuration.json')
+ }).toThrow(
+ new BaseError('Failed to read charging station configuration file configuration.json')
+ )
+ expect(logger.error.mock.calls.length).toBe(1)
+ expect(() => {
+ checkConfiguration({} as ChargingStationConfiguration, 'log prefix |', 'configuration.json')
+ }).toThrow(new BaseError('Empty charging station configuration from file configuration.json'))
+ expect(logger.error.mock.calls.length).toBe(2)
+ })
+
+ await it('Verify checkStationInfoConnectorStatus()', t => {
+ t.mock.method(logger, 'warn')
+ checkStationInfoConnectorStatus(1, {} as ConnectorStatus, 'log prefix |', 'test-template.json')
+ expect(logger.warn.mock.calls.length).toBe(0)
+ const connectorStatus = {
+ status: ConnectorStatusEnum.Available,
+ } as ConnectorStatus
+ checkStationInfoConnectorStatus(1, connectorStatus, 'log prefix |', 'test-template.json')
+ expect(logger.warn.mock.calls.length).toBe(1)
+ expect(connectorStatus.status).toBeUndefined()
+ })
+})
+import { expect } from '@std/expect'
import { describe, it } from 'node:test'
-import { expect } from 'expect'
-
import { BaseError } from '../../src/exception/BaseError.js'
await describe('BaseError test suite', async () => {
--- /dev/null
+import { expect } from '@std/expect'
+import { describe, it } from 'node:test'
+
+import { OCPPError } from '../../src/exception/OCPPError.js'
+import { ErrorType } from '../../src/types/index.js'
+import { Constants } from '../../src/utils/Constants.js'
+
+await describe('OCPPError test suite', async () => {
+ await it('Verify that OCPPError can be instantiated', () => {
+ const ocppError = new OCPPError(ErrorType.GENERIC_ERROR, '')
+ expect(ocppError).toBeInstanceOf(OCPPError)
+ expect(ocppError.name).toBe('OCPPError')
+ expect(ocppError.message).toBe('')
+ expect(ocppError.code).toBe(ErrorType.GENERIC_ERROR)
+ expect(ocppError.command).toBe(Constants.UNKNOWN_OCPP_COMMAND)
+ expect(ocppError.details).toBeUndefined()
+ expect(typeof ocppError.stack === 'string').toBe(true)
+ expect(ocppError.stack).not.toBe('')
+ expect(ocppError.cause).toBeUndefined()
+ expect(ocppError.date).toBeInstanceOf(Date)
+ })
+})
--- /dev/null
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+end_of_line = lf
+max_line_length = 100
+
+[*.py]
+indent_size = 4
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
+
+[{Makefile,**.mk}]
+# Use tabs for indentation (Makefiles require tabs)
+indent_style = tab
--- /dev/null
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
+poetry.toml
+
+.ruff_cache/
--- /dev/null
+export default {
+ '**/*.{json,md}': ['prettier --cache --write'],
+ '**/*.{py,pyi}': ['ruff check --fix', 'ruff format'],
+}
--- /dev/null
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=827846
+ // for the documentation about the extensions.json format
+ "recommendations": [
+ "EditorConfig.EditorConfig",
+ "streetsidesoftware.code-spell-checker",
+ "ms-python.python",
+ "charliermarsh.ruff"
+ ]
+}
--- /dev/null
+{
+ "editor.codeActionsOnSave": {
+ "source.fixAll": "explicit"
+ },
+ "cSpell.words": ["evse", "ocpp", "websockets"]
+}
--- /dev/null
+# Changelog
+
+## [2.0.10](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server@v2.0.9...ocpp-server@v2.0.10) (2025-07-03)
+
+### 🧹 Chores
+
+- **ocpp-server:** Synchronize simulator-ui-ocpp-server versions
+
+## [2.0.9](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server@v2.0.8...ocpp-server@v2.0.9) (2025-06-27)
+
+### 🤖 Automation
+
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1442](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1442)) ([9dc2344](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/9dc23444c551a9ea448544061efdc6febdca8ad9))
+
+## [2.0.8](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server@v2.0.7...ocpp-server@v2.0.8) (2025-05-27)
+
+### 🤖 Automation
+
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1412](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1412)) ([74d8348](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/74d8348d64f562a1c4cd74bea36955d83638949c))
+
+## [2.0.7](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server@v2.0.6...ocpp-server@v2.0.7) (2025-04-30)
+
+### 🤖 Automation
+
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1383](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1383)) ([4acd8d4](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/4acd8d4bf78b7a685421e1d8c1bf71fbd65c32ef))
+
+## [2.0.6](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server@v2.0.5...ocpp-server@v2.0.6) (2025-04-08)
+
+### 🧹 Chores
+
+- **ocpp-server:** Synchronize simulator-ui-ocpp-server versions
+
+## [2.0.5](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server@v2.0.4...ocpp-server@v2.0.5) (2025-04-08)
+
+### 🤖 Automation
+
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([3bae471](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/3bae4711f84a10a63f196be92081d2644124dce0))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([3327a60](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/3327a6085b4540edead4e9b90bb173e346604016))
+
+## [2.0.4](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server@v2.0.3...ocpp-server@v2.0.4) (2025-04-01)
+
+### 🤖 Automation
+
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([0346f5a](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/0346f5aeb832aca457ef033f58fcfd166e91ae28))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1356](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1356)) ([16323a6](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/16323a6c2d07a70195fe4ee921fc3315b0b68d16))
+
+## [2.0.3](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server@v2.0.2...ocpp-server@v2.0.3) (2025-03-17)
+
+### 🐞 Bug Fixes
+
+- port OCPP 2 server code to ocpp version 2 library ([5dd0043](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/5dd0043f62de284dfdfcd055d891240a696851a3))
+
+### 🤖 Automation
+
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([1240d3f](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1240d3f44065f961c318a66cd212a43774d2f3c6))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([69ef17b](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/69ef17ba78fa0e4587d9a8f4ccb8e0aabd4a788b))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([b07fdee](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b07fdeec628dbee2767118c53f2f39cc718391fc))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([8d44b04](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/8d44b04c638837d9661094906ee0fc762aec84e6))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([c45323e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/c45323e528911f5ab21c52245f7471d4ea4d3dad))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([a00d711](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a00d7116df445153f740568d95a808a94150657f))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([70d6e16](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/70d6e160690f0cd24c37adf5fd227c9b96b26e9e))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1265](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1265)) ([c16a083](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/c16a08374580fbe02b9797909b559ad18241c7a1))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1272](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1272)) ([724426b](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/724426b6062a2515eaa4b96747d672cd93f4421f))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1277](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1277)) ([00c442c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/00c442c3e5e5b09307ae59cd82a9ce76483674b3))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1283](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1283)) ([4079d7d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/4079d7d927671d601ebfc1d24cd3ec3010b94606))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1304](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1304)) ([a2975d2](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a2975d23712aa2a609e356087963f901da8b2cc6))
+- **deps:** bump ocpp from 2.0.0rc3 to 2.0.0rc4 in /tests/ocpp-server ([#1266](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1266)) ([ef6b26b](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/ef6b26b096bb3c6faea89a3c62346e510d81861d))
+- **deps:** bump ocpp from 2.0.0rc4 to 2.0.0 in /tests/ocpp-server ([#1268](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1268)) ([6f05e7a](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/6f05e7a9c51a7a271f5a3a6867a823cf53383d5d))
+- **deps:** bump websockets from 14.2 to 15.0 in /tests/ocpp-server ([6ad66a2](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/6ad66a2dd098c3e767a2ff82c363355319af4725))
+- **deps:** bump websockets in /tests/ocpp-server in the regular group ([caf7b3c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/caf7b3c912da328c15e76b063448150f407a5555))
+- **deps:** bump websockets in /tests/ocpp-server in the regular group ([#1289](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1289)) ([30f283d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/30f283dd68a2262d62ad69c380b93af7a05d5672))
+
+## [2.0.2](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server@v2.0.1...ocpp-server@v2.0.2) (2024-12-23)
+
+### 🤖 Automation
+
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1236](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1236)) ([5fa6474](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/5fa6474bb36abdbb4eaff8fce0946b037ae3943d))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1247](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1247)) ([7113dc0](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/7113dc0799591f7bb8707e7130275a01f338d126))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1252](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1252)) ([7832605](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/78326059f0d364515aab8e67297b0af8e6b27e6d))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1257](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1257)) ([8f3ff89](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/8f3ff8960c98a62154a20aa4799cee85fe922817))
+- **deps-dev:** bump taskipy in /tests/ocpp-server in the regular group ([#1229](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1229)) ([957a50e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/957a50ec72f20059c9118c022fc774c6cb83b87b))
+- **deps:** bump ocpp from 2.0.0rc2 to 2.0.0rc3 in /tests/ocpp-server ([#1248](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1248)) ([45c31e7](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/45c31e715047edf8eb5aeb5e0bb098902a252bf4))
+
+## [2.0.1](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server@v2.0.0...ocpp-server@v2.0.1) (2024-11-22)
+
+### 🤖 Automation
+
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([6c99ee6](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/6c99ee6a02a4c98147c2f47b085faef12d850a73))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1201](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1201)) ([8a80af2](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/8a80af287e23d31f24fde579f0db6b68405f3091))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1213](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1213)) ([89e4a23](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/89e4a238ab0be07503d933dcb62ae3688497c123))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1224](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1224)) ([c047fe5](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/c047fe50eca6da3b32136bd4ce8b8a99346bc8db))
+- **deps:** bump websockets from 13.1 to 14.0 in /tests/ocpp-server ([#1214](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1214)) ([cfafab3](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/cfafab382b0379a6f38a215c69908917e31de434))
+- **deps:** bump websockets in /tests/ocpp-server in the regular group ([#1218](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1218)) ([9e1c610](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/9e1c6101dbeaa175122a8810bc3c94521b49da61))
+
+## [2.0.0](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server@v1.5.2...ocpp-server@v2.0.0) (2024-10-23)
+
+### 🤖 Automation
+
+- **deps-dev:** bump taskipy in /tests/ocpp-server in the regular group ([#1199](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1199)) ([cd41213](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/cd41213f50caaf842c4cc078ce5907adba68c05b))
+
+## [1.5.2](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server@v1.5.1...ocpp-server@v1.5.2) (2024-10-21)
+
+### 🐞 Bug Fixes
+
+- fix server task ([63bdd06](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/63bdd06f6a605d56e31dfc2787b259d190dea56c))
+
+### 🤖 Automation
+
+- **deps-dev:** bump ruff from 0.5.5 to 0.5.6 in /tests/ocpp-server ([#1121](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1121)) ([600d4c1](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/600d4c16c67c6c91c97368aa59931faa86ccfc23))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([05d3347](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/05d3347e16f1a64531c1f9a8020f5196634d7062))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([5522407](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/5522407ca7c53f5eb5c92f066bba27502959afc0))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1133](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1133)) ([e5ea15f](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e5ea15fc2a6ca7679c9eefdb5a3f56163341ea07))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1141](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1141)) ([0f729d5](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/0f729d55a33898e17bc7eae9c6789e5460e9ec29))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1142](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1142)) ([815ddf2](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/815ddf2b89991ca7450c5edbb43cd34fd0c5655a))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1149](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1149)) ([e62f5d8](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e62f5d862ff66ba33559c3852d63df159359a0e1))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1169](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1169)) ([a5e2da5](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a5e2da5d5e46970afadc6d4933d997830bbd7b42))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1174](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1174)) ([5e1baef](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/5e1baef5574abfe01f8891acc97ad87c9e98018b))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1186](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1186)) ([2442336](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/2442336b709ce2848b26f7210bb9d22cff12dc39))
+- **deps-dev:** bump ruff in /tests/ocpp-server in the regular group ([#1194](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1194)) ([8641c87](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/8641c876f7bca338bfa81546298917576a7503c2))
+- **deps:** bump the regular group in /tests/ocpp-server with 2 updates ([#1154](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1154)) ([1632cc4](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1632cc430da54a1ca9511f1ebe261ac6a260ac4a))
+- **deps:** bump the regular group in /tests/ocpp-server with 2 updates ([#1175](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1175)) ([455167a](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/455167a9345be3811196083fbb54c3db22be62c7))
+- **deps:** bump websockets in /tests/ocpp-server in the major group ([ebea5db](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/ebea5dbf6b4b042cb481ef7a7d0686c2d56ea1f4))
+
+## [1.5.1](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server@v1.5.0...ocpp-server@v1.5.1) (2024-07-30)
+
+### 🤖 Automation
+
+- **deps-dev:** bump ruff from 0.5.4 to 0.5.5 in /tests/ocpp-server ([#1109](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1109)) ([ed9eed8](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/ed9eed87bba1bee5b0a7cb06d96a5ad40a2278eb))
+
+## [1.5.0](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server@v1.4.2...ocpp-server@v1.5.0) (2024-07-25)
+
+### 🤖 Automation
+
+- **deps-dev:** bump ruff from 0.5.2 to 0.5.3 in /tests/ocpp-server ([#1094](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1094)) ([be27d4e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/be27d4eacbbc58857c7c8a3caac51383f920b2f9))
+
+## [1.4.2](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server@v1.4.1...ocpp-server@v1.4.2) (2024-07-06)
+
+### 🤖 Automation
+
+- **deps-dev:** bump ruff from 0.5.0 to 0.5.1 in /tests/ocpp-server ([b6f8b09](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b6f8b09baf035ba075a837cb9199e821b2deb6fa))
+
+## [1.4.1](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server@v1.4.0...ocpp-server@v1.4.1) (2024-07-05)
+
+### 🧹 Chores
+
+- **ocpp-server:** Synchronize simulator-ui-ocpp-server versions
+
+## [1.4.0](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ocpp-server-v1.3.7...ocpp-server@v1.4.0) (2024-07-04)
+
+### 🐞 Fixes
+
+- **ocpp-server:** randomize GetBaseReport request id ([8fe113d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/8fe113d7ae764df93daaa7a69c6fe810b6703587))
--- /dev/null
+# OCPP2 Mock Server
+
+This project includes an Open Charge Point Protocol (OCPP) version 2.0.1 mock server implemented in Python.
+
+## Prerequisites
+
+This project requires Python 3.7+ and [poetry](https://python-poetry.org/) to install the required packages:
+
+```shell
+poetry install --no-root
+```
+
+## Running the Server
+
+To start the server, run the `server.py` script:
+
+```shell
+poetry run task server
+```
+
+Or
+
+```shell
+poetry run python server.py
+```
+
+The server will start listening for connections on port 9000.
+
+## Running the server with OCPP command sending
+
+You can also specify a command and a period duration with the --command and --period options respectively when running the server. The server will then send your chosen command to the connected client(s) every period seconds.
+
+### GetBaseReport Command
+
+To run the server and send a GetBaseReport command every 5 seconds, use:
+
+```shell
+poetry run task server --command GetBaseReport --period 5
+```
+
+### ClearCache Command
+
+To run the server and send a ClearCache command every 5 seconds, use:
+
+```shell
+poetry run task server --command ClearCache --period 5
+```
+
+Please be mindful that these commands were examples according to the provided scenario, the available commands and their syntax might vary depending on the ocpp version and the implemented functionalities on your client.
+
+## Overview of the Server Scripts
+
+### Server.py
+
+The server script waits for connections from clients. When a client connects, the server creates a new instance of the `ChargePoint` class. This class includes methods for handling various OCPP messages, most of which return a dummy response.
+
+The server script uses the `websockets` and `ocpp` libraries to facilitate the implementation.
+
+## Development
+
+### Code formatting
+
+```shell
+poetry run task format
+```
+
+### Code linting
+
+```shell
+poetry run task lint
+```
+
+## Note
+
+Primarily, this software is intended for testing applications. The server script don't adhere to the full OCPP specifications and it is advised not to use them in a production environment without additional development.
+
+For reference:
+https://github.com/mobilityhouse/ocpp
--- /dev/null
+# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand.
+
+[[package]]
+name = "attrs"
+version = "25.3.0"
+description = "Classes Without Boilerplate"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"},
+ {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"},
+]
+
+[package.extras]
+benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"]
+tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "jsonschema"
+version = "4.24.0"
+description = "An implementation of JSON Schema validation for Python"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "jsonschema-4.24.0-py3-none-any.whl", hash = "sha256:a462455f19f5faf404a7902952b6f0e3ce868f3ee09a359b05eca6673bd8412d"},
+ {file = "jsonschema-4.24.0.tar.gz", hash = "sha256:0b4e8069eb12aedfa881333004bccaec24ecef5a8a6a4b6df142b2cc9599d196"},
+]
+
+[package.dependencies]
+attrs = ">=22.2.0"
+jsonschema-specifications = ">=2023.03.6"
+referencing = ">=0.28.4"
+rpds-py = ">=0.7.1"
+
+[package.extras]
+format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"]
+format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=24.6.0)"]
+
+[[package]]
+name = "jsonschema-specifications"
+version = "2025.4.1"
+description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "jsonschema_specifications-2025.4.1-py3-none-any.whl", hash = "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af"},
+ {file = "jsonschema_specifications-2025.4.1.tar.gz", hash = "sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608"},
+]
+
+[package.dependencies]
+referencing = ">=0.31.0"
+
+[[package]]
+name = "mslex"
+version = "1.3.0"
+description = "shlex for windows"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "mslex-1.3.0-py3-none-any.whl", hash = "sha256:c7074b347201b3466fc077c5692fbce9b5f62a63a51f537a53fbbd02eff2eea4"},
+ {file = "mslex-1.3.0.tar.gz", hash = "sha256:641c887d1d3db610eee2af37a8e5abda3f70b3006cdfd2d0d29dc0d1ae28a85d"},
+]
+
+[[package]]
+name = "ocpp"
+version = "2.0.0"
+description = "Python package implementing the JSON version of the Open Charge Point Protocol (OCPP)."
+optional = false
+python-versions = "<4.0,>=3.8"
+files = [
+ {file = "ocpp-2.0.0-py3-none-any.whl", hash = "sha256:45ea3f35cb0afd7a0acbc1cdf2cfd107caf371c24aca7e7a03491405bf39e626"},
+ {file = "ocpp-2.0.0.tar.gz", hash = "sha256:bbc203ae5edeb7baf43a9a24b73c6a7473179197437fb39c641f0d93afce5dc0"},
+]
+
+[package.dependencies]
+jsonschema = ">=4.4.0,<5.0.0"
+
+[[package]]
+name = "psutil"
+version = "6.1.1"
+description = "Cross-platform lib for process and system monitoring in Python."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
+files = [
+ {file = "psutil-6.1.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:9ccc4316f24409159897799b83004cb1e24f9819b0dcf9c0b68bdcb6cefee6a8"},
+ {file = "psutil-6.1.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ca9609c77ea3b8481ab005da74ed894035936223422dc591d6772b147421f777"},
+ {file = "psutil-6.1.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:8df0178ba8a9e5bc84fed9cfa61d54601b371fbec5c8eebad27575f1e105c0d4"},
+ {file = "psutil-6.1.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:1924e659d6c19c647e763e78670a05dbb7feaf44a0e9c94bf9e14dfc6ba50468"},
+ {file = "psutil-6.1.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:018aeae2af92d943fdf1da6b58665124897cfc94faa2ca92098838f83e1b1bca"},
+ {file = "psutil-6.1.1-cp27-none-win32.whl", hash = "sha256:6d4281f5bbca041e2292be3380ec56a9413b790579b8e593b1784499d0005dac"},
+ {file = "psutil-6.1.1-cp27-none-win_amd64.whl", hash = "sha256:c777eb75bb33c47377c9af68f30e9f11bc78e0f07fbf907be4a5d70b2fe5f030"},
+ {file = "psutil-6.1.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:fc0ed7fe2231a444fc219b9c42d0376e0a9a1a72f16c5cfa0f68d19f1a0663e8"},
+ {file = "psutil-6.1.1-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0bdd4eab935276290ad3cb718e9809412895ca6b5b334f5a9111ee6d9aff9377"},
+ {file = "psutil-6.1.1-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6e06c20c05fe95a3d7302d74e7097756d4ba1247975ad6905441ae1b5b66003"},
+ {file = "psutil-6.1.1-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97f7cb9921fbec4904f522d972f0c0e1f4fabbdd4e0287813b21215074a0f160"},
+ {file = "psutil-6.1.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33431e84fee02bc84ea36d9e2c4a6d395d479c9dd9bba2376c1f6ee8f3a4e0b3"},
+ {file = "psutil-6.1.1-cp36-cp36m-win32.whl", hash = "sha256:384636b1a64b47814437d1173be1427a7c83681b17a450bfc309a1953e329603"},
+ {file = "psutil-6.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:8be07491f6ebe1a693f17d4f11e69d0dc1811fa082736500f649f79df7735303"},
+ {file = "psutil-6.1.1-cp37-abi3-win32.whl", hash = "sha256:eaa912e0b11848c4d9279a93d7e2783df352b082f40111e078388701fd479e53"},
+ {file = "psutil-6.1.1-cp37-abi3-win_amd64.whl", hash = "sha256:f35cfccb065fff93529d2afb4a2e89e363fe63ca1e4a5da22b603a85833c2649"},
+ {file = "psutil-6.1.1.tar.gz", hash = "sha256:cf8496728c18f2d0b45198f06895be52f36611711746b7f30c464b422b50e2f5"},
+]
+
+[package.extras]
+dev = ["abi3audit", "black", "check-manifest", "coverage", "packaging", "pylint", "pyperf", "pypinfo", "pytest-cov", "requests", "rstcheck", "ruff", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "virtualenv", "vulture", "wheel"]
+test = ["pytest", "pytest-xdist", "setuptools"]
+
+[[package]]
+name = "referencing"
+version = "0.36.2"
+description = "JSON Referencing + Python"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0"},
+ {file = "referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa"},
+]
+
+[package.dependencies]
+attrs = ">=22.2.0"
+rpds-py = ">=0.7.0"
+typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""}
+
+[[package]]
+name = "rpds-py"
+version = "0.26.0"
+description = "Python bindings to Rust's persistent data structures (rpds)"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "rpds_py-0.26.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:4c70c70f9169692b36307a95f3d8c0a9fcd79f7b4a383aad5eaa0e9718b79b37"},
+ {file = "rpds_py-0.26.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:777c62479d12395bfb932944e61e915741e364c843afc3196b694db3d669fcd0"},
+ {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec671691e72dff75817386aa02d81e708b5a7ec0dec6669ec05213ff6b77e1bd"},
+ {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a1cb5d6ce81379401bbb7f6dbe3d56de537fb8235979843f0d53bc2e9815a79"},
+ {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f789e32fa1fb6a7bf890e0124e7b42d1e60d28ebff57fe806719abb75f0e9a3"},
+ {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c55b0a669976cf258afd718de3d9ad1b7d1fe0a91cd1ab36f38b03d4d4aeaaf"},
+ {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c70d9ec912802ecfd6cd390dadb34a9578b04f9bcb8e863d0a7598ba5e9e7ccc"},
+ {file = "rpds_py-0.26.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3021933c2cb7def39d927b9862292e0f4c75a13d7de70eb0ab06efed4c508c19"},
+ {file = "rpds_py-0.26.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8a7898b6ca3b7d6659e55cdac825a2e58c638cbf335cde41f4619e290dd0ad11"},
+ {file = "rpds_py-0.26.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:12bff2ad9447188377f1b2794772f91fe68bb4bbfa5a39d7941fbebdbf8c500f"},
+ {file = "rpds_py-0.26.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:191aa858f7d4902e975d4cf2f2d9243816c91e9605070aeb09c0a800d187e323"},
+ {file = "rpds_py-0.26.0-cp310-cp310-win32.whl", hash = "sha256:b37a04d9f52cb76b6b78f35109b513f6519efb481d8ca4c321f6a3b9580b3f45"},
+ {file = "rpds_py-0.26.0-cp310-cp310-win_amd64.whl", hash = "sha256:38721d4c9edd3eb6670437d8d5e2070063f305bfa2d5aa4278c51cedcd508a84"},
+ {file = "rpds_py-0.26.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:9e8cb77286025bdb21be2941d64ac6ca016130bfdcd228739e8ab137eb4406ed"},
+ {file = "rpds_py-0.26.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5e09330b21d98adc8ccb2dbb9fc6cb434e8908d4c119aeaa772cb1caab5440a0"},
+ {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c9c1b92b774b2e68d11193dc39620d62fd8ab33f0a3c77ecdabe19c179cdbc1"},
+ {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:824e6d3503ab990d7090768e4dfd9e840837bae057f212ff9f4f05ec6d1975e7"},
+ {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ad7fd2258228bf288f2331f0a6148ad0186b2e3643055ed0db30990e59817a6"},
+ {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0dc23bbb3e06ec1ea72d515fb572c1fea59695aefbffb106501138762e1e915e"},
+ {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d80bf832ac7b1920ee29a426cdca335f96a2b5caa839811803e999b41ba9030d"},
+ {file = "rpds_py-0.26.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0919f38f5542c0a87e7b4afcafab6fd2c15386632d249e9a087498571250abe3"},
+ {file = "rpds_py-0.26.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d422b945683e409000c888e384546dbab9009bb92f7c0b456e217988cf316107"},
+ {file = "rpds_py-0.26.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:77a7711fa562ba2da1aa757e11024ad6d93bad6ad7ede5afb9af144623e5f76a"},
+ {file = "rpds_py-0.26.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:238e8c8610cb7c29460e37184f6799547f7e09e6a9bdbdab4e8edb90986a2318"},
+ {file = "rpds_py-0.26.0-cp311-cp311-win32.whl", hash = "sha256:893b022bfbdf26d7bedb083efeea624e8550ca6eb98bf7fea30211ce95b9201a"},
+ {file = "rpds_py-0.26.0-cp311-cp311-win_amd64.whl", hash = "sha256:87a5531de9f71aceb8af041d72fc4cab4943648d91875ed56d2e629bef6d4c03"},
+ {file = "rpds_py-0.26.0-cp311-cp311-win_arm64.whl", hash = "sha256:de2713f48c1ad57f89ac25b3cb7daed2156d8e822cf0eca9b96a6f990718cc41"},
+ {file = "rpds_py-0.26.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:894514d47e012e794f1350f076c427d2347ebf82f9b958d554d12819849a369d"},
+ {file = "rpds_py-0.26.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc921b96fa95a097add244da36a1d9e4f3039160d1d30f1b35837bf108c21136"},
+ {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e1157659470aa42a75448b6e943c895be8c70531c43cb78b9ba990778955582"},
+ {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:521ccf56f45bb3a791182dc6b88ae5f8fa079dd705ee42138c76deb1238e554e"},
+ {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9def736773fd56b305c0eef698be5192c77bfa30d55a0e5885f80126c4831a15"},
+ {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdad4ea3b4513b475e027be79e5a0ceac8ee1c113a1a11e5edc3c30c29f964d8"},
+ {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82b165b07f416bdccf5c84546a484cc8f15137ca38325403864bfdf2b5b72f6a"},
+ {file = "rpds_py-0.26.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d04cab0a54b9dba4d278fe955a1390da3cf71f57feb78ddc7cb67cbe0bd30323"},
+ {file = "rpds_py-0.26.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:79061ba1a11b6a12743a2b0f72a46aa2758613d454aa6ba4f5a265cc48850158"},
+ {file = "rpds_py-0.26.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f405c93675d8d4c5ac87364bb38d06c988e11028a64b52a47158a355079661f3"},
+ {file = "rpds_py-0.26.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dafd4c44b74aa4bed4b250f1aed165b8ef5de743bcca3b88fc9619b6087093d2"},
+ {file = "rpds_py-0.26.0-cp312-cp312-win32.whl", hash = "sha256:3da5852aad63fa0c6f836f3359647870e21ea96cf433eb393ffa45263a170d44"},
+ {file = "rpds_py-0.26.0-cp312-cp312-win_amd64.whl", hash = "sha256:cf47cfdabc2194a669dcf7a8dbba62e37a04c5041d2125fae0233b720da6f05c"},
+ {file = "rpds_py-0.26.0-cp312-cp312-win_arm64.whl", hash = "sha256:20ab1ae4fa534f73647aad289003f1104092890849e0266271351922ed5574f8"},
+ {file = "rpds_py-0.26.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:696764a5be111b036256c0b18cd29783fab22154690fc698062fc1b0084b511d"},
+ {file = "rpds_py-0.26.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1e6c15d2080a63aaed876e228efe4f814bc7889c63b1e112ad46fdc8b368b9e1"},
+ {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:390e3170babf42462739a93321e657444f0862c6d722a291accc46f9d21ed04e"},
+ {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7da84c2c74c0f5bc97d853d9e17bb83e2dcafcff0dc48286916001cc114379a1"},
+ {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c5fe114a6dd480a510b6d3661d09d67d1622c4bf20660a474507aaee7eeeee9"},
+ {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3100b3090269f3a7ea727b06a6080d4eb7439dca4c0e91a07c5d133bb1727ea7"},
+ {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c03c9b0c64afd0320ae57de4c982801271c0c211aa2d37f3003ff5feb75bb04"},
+ {file = "rpds_py-0.26.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5963b72ccd199ade6ee493723d18a3f21ba7d5b957017607f815788cef50eaf1"},
+ {file = "rpds_py-0.26.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9da4e873860ad5bab3291438525cae80169daecbfafe5657f7f5fb4d6b3f96b9"},
+ {file = "rpds_py-0.26.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5afaddaa8e8c7f1f7b4c5c725c0070b6eed0228f705b90a1732a48e84350f4e9"},
+ {file = "rpds_py-0.26.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4916dc96489616a6f9667e7526af8fa693c0fdb4f3acb0e5d9f4400eb06a47ba"},
+ {file = "rpds_py-0.26.0-cp313-cp313-win32.whl", hash = "sha256:2a343f91b17097c546b93f7999976fd6c9d5900617aa848c81d794e062ab302b"},
+ {file = "rpds_py-0.26.0-cp313-cp313-win_amd64.whl", hash = "sha256:0a0b60701f2300c81b2ac88a5fb893ccfa408e1c4a555a77f908a2596eb875a5"},
+ {file = "rpds_py-0.26.0-cp313-cp313-win_arm64.whl", hash = "sha256:257d011919f133a4746958257f2c75238e3ff54255acd5e3e11f3ff41fd14256"},
+ {file = "rpds_py-0.26.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:529c8156d7506fba5740e05da8795688f87119cce330c244519cf706a4a3d618"},
+ {file = "rpds_py-0.26.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f53ec51f9d24e9638a40cabb95078ade8c99251945dad8d57bf4aabe86ecee35"},
+ {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab504c4d654e4a29558eaa5bb8cea5fdc1703ea60a8099ffd9c758472cf913f"},
+ {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fd0641abca296bc1a00183fe44f7fced8807ed49d501f188faa642d0e4975b83"},
+ {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69b312fecc1d017b5327afa81d4da1480f51c68810963a7336d92203dbb3d4f1"},
+ {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c741107203954f6fc34d3066d213d0a0c40f7bb5aafd698fb39888af277c70d8"},
+ {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc3e55a7db08dc9a6ed5fb7103019d2c1a38a349ac41901f9f66d7f95750942f"},
+ {file = "rpds_py-0.26.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e851920caab2dbcae311fd28f4313c6953993893eb5c1bb367ec69d9a39e7ed"},
+ {file = "rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:dfbf280da5f876d0b00c81f26bedce274e72a678c28845453885a9b3c22ae632"},
+ {file = "rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1cc81d14ddfa53d7f3906694d35d54d9d3f850ef8e4e99ee68bc0d1e5fed9a9c"},
+ {file = "rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dca83c498b4650a91efcf7b88d669b170256bf8017a5db6f3e06c2bf031f57e0"},
+ {file = "rpds_py-0.26.0-cp313-cp313t-win32.whl", hash = "sha256:4d11382bcaf12f80b51d790dee295c56a159633a8e81e6323b16e55d81ae37e9"},
+ {file = "rpds_py-0.26.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff110acded3c22c033e637dd8896e411c7d3a11289b2edf041f86663dbc791e9"},
+ {file = "rpds_py-0.26.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:da619979df60a940cd434084355c514c25cf8eb4cf9a508510682f6c851a4f7a"},
+ {file = "rpds_py-0.26.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ea89a2458a1a75f87caabefe789c87539ea4e43b40f18cff526052e35bbb4fdf"},
+ {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feac1045b3327a45944e7dcbeb57530339f6b17baff154df51ef8b0da34c8c12"},
+ {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b818a592bd69bfe437ee8368603d4a2d928c34cffcdf77c2e761a759ffd17d20"},
+ {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a8b0dd8648709b62d9372fc00a57466f5fdeefed666afe3fea5a6c9539a0331"},
+ {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6d3498ad0df07d81112aa6ec6c95a7e7b1ae00929fb73e7ebee0f3faaeabad2f"},
+ {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24a4146ccb15be237fdef10f331c568e1b0e505f8c8c9ed5d67759dac58ac246"},
+ {file = "rpds_py-0.26.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a9a63785467b2d73635957d32a4f6e73d5e4df497a16a6392fa066b753e87387"},
+ {file = "rpds_py-0.26.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:de4ed93a8c91debfd5a047be327b7cc8b0cc6afe32a716bbbc4aedca9e2a83af"},
+ {file = "rpds_py-0.26.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:caf51943715b12af827696ec395bfa68f090a4c1a1d2509eb4e2cb69abbbdb33"},
+ {file = "rpds_py-0.26.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4a59e5bc386de021f56337f757301b337d7ab58baa40174fb150accd480bc953"},
+ {file = "rpds_py-0.26.0-cp314-cp314-win32.whl", hash = "sha256:92c8db839367ef16a662478f0a2fe13e15f2227da3c1430a782ad0f6ee009ec9"},
+ {file = "rpds_py-0.26.0-cp314-cp314-win_amd64.whl", hash = "sha256:b0afb8cdd034150d4d9f53926226ed27ad15b7f465e93d7468caaf5eafae0d37"},
+ {file = "rpds_py-0.26.0-cp314-cp314-win_arm64.whl", hash = "sha256:ca3f059f4ba485d90c8dc75cb5ca897e15325e4e609812ce57f896607c1c0867"},
+ {file = "rpds_py-0.26.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:5afea17ab3a126006dc2f293b14ffc7ef3c85336cf451564a0515ed7648033da"},
+ {file = "rpds_py-0.26.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:69f0c0a3df7fd3a7eec50a00396104bb9a843ea6d45fcc31c2d5243446ffd7a7"},
+ {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:801a71f70f9813e82d2513c9a96532551fce1e278ec0c64610992c49c04c2dad"},
+ {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df52098cde6d5e02fa75c1f6244f07971773adb4a26625edd5c18fee906fa84d"},
+ {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bc596b30f86dc6f0929499c9e574601679d0341a0108c25b9b358a042f51bca"},
+ {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9dfbe56b299cf5875b68eb6f0ebaadc9cac520a1989cac0db0765abfb3709c19"},
+ {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac64f4b2bdb4ea622175c9ab7cf09444e412e22c0e02e906978b3b488af5fde8"},
+ {file = "rpds_py-0.26.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:181ef9b6bbf9845a264f9aa45c31836e9f3c1f13be565d0d010e964c661d1e2b"},
+ {file = "rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:49028aa684c144ea502a8e847d23aed5e4c2ef7cadfa7d5eaafcb40864844b7a"},
+ {file = "rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e5d524d68a474a9688336045bbf76cb0def88549c1b2ad9dbfec1fb7cfbe9170"},
+ {file = "rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c1851f429b822831bd2edcbe0cfd12ee9ea77868f8d3daf267b189371671c80e"},
+ {file = "rpds_py-0.26.0-cp314-cp314t-win32.whl", hash = "sha256:7bdb17009696214c3b66bb3590c6d62e14ac5935e53e929bcdbc5a495987a84f"},
+ {file = "rpds_py-0.26.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f14440b9573a6f76b4ee4770c13f0b5921f71dde3b6fcb8dabbefd13b7fe05d7"},
+ {file = "rpds_py-0.26.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:7a48af25d9b3c15684059d0d1fc0bc30e8eee5ca521030e2bffddcab5be40226"},
+ {file = "rpds_py-0.26.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0c71c2f6bf36e61ee5c47b2b9b5d47e4d1baad6426bfed9eea3e858fc6ee8806"},
+ {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d815d48b1804ed7867b539236b6dd62997850ca1c91cad187f2ddb1b7bbef19"},
+ {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:84cfbd4d4d2cdeb2be61a057a258d26b22877266dd905809e94172dff01a42ae"},
+ {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fbaa70553ca116c77717f513e08815aec458e6b69a028d4028d403b3bc84ff37"},
+ {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39bfea47c375f379d8e87ab4bb9eb2c836e4f2069f0f65731d85e55d74666387"},
+ {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1533b7eb683fb5f38c1d68a3c78f5fdd8f1412fa6b9bf03b40f450785a0ab915"},
+ {file = "rpds_py-0.26.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c5ab0ee51f560d179b057555b4f601b7df909ed31312d301b99f8b9fc6028284"},
+ {file = "rpds_py-0.26.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e5162afc9e0d1f9cae3b577d9c29ddbab3505ab39012cb794d94a005825bde21"},
+ {file = "rpds_py-0.26.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:43f10b007033f359bc3fa9cd5e6c1e76723f056ffa9a6b5c117cc35720a80292"},
+ {file = "rpds_py-0.26.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e3730a48e5622e598293eee0762b09cff34dd3f271530f47b0894891281f051d"},
+ {file = "rpds_py-0.26.0-cp39-cp39-win32.whl", hash = "sha256:4b1f66eb81eab2e0ff5775a3a312e5e2e16bf758f7b06be82fb0d04078c7ac51"},
+ {file = "rpds_py-0.26.0-cp39-cp39-win_amd64.whl", hash = "sha256:519067e29f67b5c90e64fb1a6b6e9d2ec0ba28705c51956637bac23a2f4ddae1"},
+ {file = "rpds_py-0.26.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3c0909c5234543ada2515c05dc08595b08d621ba919629e94427e8e03539c958"},
+ {file = "rpds_py-0.26.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:c1fb0cda2abcc0ac62f64e2ea4b4e64c57dfd6b885e693095460c61bde7bb18e"},
+ {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84d142d2d6cf9b31c12aa4878d82ed3b2324226270b89b676ac62ccd7df52d08"},
+ {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a547e21c5610b7e9093d870be50682a6a6cf180d6da0f42c47c306073bfdbbf6"},
+ {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:35e9a70a0f335371275cdcd08bc5b8051ac494dd58bff3bbfb421038220dc871"},
+ {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0dfa6115c6def37905344d56fb54c03afc49104e2ca473d5dedec0f6606913b4"},
+ {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:313cfcd6af1a55a286a3c9a25f64af6d0e46cf60bc5798f1db152d97a216ff6f"},
+ {file = "rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f7bf2496fa563c046d05e4d232d7b7fd61346e2402052064b773e5c378bf6f73"},
+ {file = "rpds_py-0.26.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:aa81873e2c8c5aa616ab8e017a481a96742fdf9313c40f14338ca7dbf50cb55f"},
+ {file = "rpds_py-0.26.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:68ffcf982715f5b5b7686bdd349ff75d422e8f22551000c24b30eaa1b7f7ae84"},
+ {file = "rpds_py-0.26.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6188de70e190847bb6db3dc3981cbadff87d27d6fe9b4f0e18726d55795cee9b"},
+ {file = "rpds_py-0.26.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1c962145c7473723df9722ba4c058de12eb5ebedcb4e27e7d902920aa3831ee8"},
+ {file = "rpds_py-0.26.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f61a9326f80ca59214d1cceb0a09bb2ece5b2563d4e0cd37bfd5515c28510674"},
+ {file = "rpds_py-0.26.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:183f857a53bcf4b1b42ef0f57ca553ab56bdd170e49d8091e96c51c3d69ca696"},
+ {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:941c1cfdf4799d623cf3aa1d326a6b4fdb7a5799ee2687f3516738216d2262fb"},
+ {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72a8d9564a717ee291f554eeb4bfeafe2309d5ec0aa6c475170bdab0f9ee8e88"},
+ {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:511d15193cbe013619dd05414c35a7dedf2088fcee93c6bbb7c77859765bd4e8"},
+ {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aea1f9741b603a8d8fedb0ed5502c2bc0accbc51f43e2ad1337fe7259c2b77a5"},
+ {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4019a9d473c708cf2f16415688ef0b4639e07abaa569d72f74745bbeffafa2c7"},
+ {file = "rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:093d63b4b0f52d98ebae33b8c50900d3d67e0666094b1be7a12fffd7f65de74b"},
+ {file = "rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2abe21d8ba64cded53a2a677e149ceb76dcf44284202d737178afe7ba540c1eb"},
+ {file = "rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:4feb7511c29f8442cbbc28149a92093d32e815a28aa2c50d333826ad2a20fdf0"},
+ {file = "rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e99685fc95d386da368013e7fb4269dd39c30d99f812a8372d62f244f662709c"},
+ {file = "rpds_py-0.26.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a90a13408a7a856b87be8a9f008fff53c5080eea4e4180f6c2e546e4a972fb5d"},
+ {file = "rpds_py-0.26.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:3ac51b65e8dc76cf4949419c54c5528adb24fc721df722fd452e5fbc236f5c40"},
+ {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59b2093224a18c6508d95cfdeba8db9cbfd6f3494e94793b58972933fcee4c6d"},
+ {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4f01a5d6444a3258b00dc07b6ea4733e26f8072b788bef750baa37b370266137"},
+ {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6e2c12160c72aeda9d1283e612f68804621f448145a210f1bf1d79151c47090"},
+ {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cb28c1f569f8d33b2b5dcd05d0e6ef7005d8639c54c2f0be824f05aedf715255"},
+ {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1766b5724c3f779317d5321664a343c07773c8c5fd1532e4039e6cc7d1a815be"},
+ {file = "rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b6d9e5a2ed9c4988c8f9b28b3bc0e3e5b1aaa10c28d210a594ff3a8c02742daf"},
+ {file = "rpds_py-0.26.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:b5f7a446ddaf6ca0fad9a5535b56fbfc29998bf0e0b450d174bbec0d600e1d72"},
+ {file = "rpds_py-0.26.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:eed5ac260dd545fbc20da5f4f15e7efe36a55e0e7cf706e4ec005b491a9546a0"},
+ {file = "rpds_py-0.26.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:582462833ba7cee52e968b0341b85e392ae53d44c0f9af6a5927c80e539a8b67"},
+ {file = "rpds_py-0.26.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:69a607203441e07e9a8a529cff1d5b73f6a160f22db1097211e6212a68567d11"},
+ {file = "rpds_py-0.26.0.tar.gz", hash = "sha256:20dae58a859b0906f0685642e591056f1e787f3a8b39c8e8749a45dc7d26bdb0"},
+]
+
+[[package]]
+name = "ruff"
+version = "0.12.2"
+description = "An extremely fast Python linter and code formatter, written in Rust."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "ruff-0.12.2-py3-none-linux_armv6l.whl", hash = "sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be"},
+ {file = "ruff-0.12.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e"},
+ {file = "ruff-0.12.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc"},
+ {file = "ruff-0.12.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922"},
+ {file = "ruff-0.12.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b"},
+ {file = "ruff-0.12.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d"},
+ {file = "ruff-0.12.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1"},
+ {file = "ruff-0.12.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4"},
+ {file = "ruff-0.12.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9"},
+ {file = "ruff-0.12.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da"},
+ {file = "ruff-0.12.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce"},
+ {file = "ruff-0.12.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d"},
+ {file = "ruff-0.12.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04"},
+ {file = "ruff-0.12.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342"},
+ {file = "ruff-0.12.2-py3-none-win32.whl", hash = "sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a"},
+ {file = "ruff-0.12.2-py3-none-win_amd64.whl", hash = "sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639"},
+ {file = "ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12"},
+ {file = "ruff-0.12.2.tar.gz", hash = "sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e"},
+]
+
+[[package]]
+name = "taskipy"
+version = "1.14.1"
+description = "tasks runner for python projects"
+optional = false
+python-versions = "<4.0,>=3.6"
+files = [
+ {file = "taskipy-1.14.1-py3-none-any.whl", hash = "sha256:6e361520f29a0fd2159848e953599f9c75b1d0b047461e4965069caeb94908f1"},
+ {file = "taskipy-1.14.1.tar.gz", hash = "sha256:410fbcf89692dfd4b9f39c2b49e1750b0a7b81affd0e2d7ea8c35f9d6a4774ed"},
+]
+
+[package.dependencies]
+colorama = ">=0.4.4,<0.5.0"
+mslex = {version = ">=1.1.0,<2.0.0", markers = "sys_platform == \"win32\""}
+psutil = ">=5.7.2,<7"
+tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version >= \"3.7\" and python_version < \"4.0\""}
+
+[[package]]
+name = "tomli"
+version = "2.2.1"
+description = "A lil' TOML parser"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"},
+ {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"},
+ {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"},
+ {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"},
+ {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"},
+ {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"},
+ {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"},
+ {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"},
+ {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"},
+ {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"},
+ {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"},
+ {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"},
+ {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"},
+ {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"},
+ {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"},
+ {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"},
+ {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"},
+ {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"},
+ {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"},
+ {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"},
+ {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"},
+ {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"},
+ {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"},
+ {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"},
+ {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"},
+ {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"},
+ {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"},
+ {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"},
+ {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"},
+ {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"},
+ {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"},
+ {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"},
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.14.1"
+description = "Backported and Experimental Type Hints for Python 3.9+"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76"},
+ {file = "typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36"},
+]
+
+[[package]]
+name = "websockets"
+version = "15.0.1"
+description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "websockets-15.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d63efaa0cd96cf0c5fe4d581521d9fa87744540d4bc999ae6e08595a1014b45b"},
+ {file = "websockets-15.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac60e3b188ec7574cb761b08d50fcedf9d77f1530352db4eef1707fe9dee7205"},
+ {file = "websockets-15.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5756779642579d902eed757b21b0164cd6fe338506a8083eb58af5c372e39d9a"},
+ {file = "websockets-15.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fdfe3e2a29e4db3659dbd5bbf04560cea53dd9610273917799f1cde46aa725e"},
+ {file = "websockets-15.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c2529b320eb9e35af0fa3016c187dffb84a3ecc572bcee7c3ce302bfeba52bf"},
+ {file = "websockets-15.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac1e5c9054fe23226fb11e05a6e630837f074174c4c2f0fe442996112a6de4fb"},
+ {file = "websockets-15.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5df592cd503496351d6dc14f7cdad49f268d8e618f80dce0cd5a36b93c3fc08d"},
+ {file = "websockets-15.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0a34631031a8f05657e8e90903e656959234f3a04552259458aac0b0f9ae6fd9"},
+ {file = "websockets-15.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d00075aa65772e7ce9e990cab3ff1de702aa09be3940d1dc88d5abf1ab8a09c"},
+ {file = "websockets-15.0.1-cp310-cp310-win32.whl", hash = "sha256:1234d4ef35db82f5446dca8e35a7da7964d02c127b095e172e54397fb6a6c256"},
+ {file = "websockets-15.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:39c1fec2c11dc8d89bba6b2bf1556af381611a173ac2b511cf7231622058af41"},
+ {file = "websockets-15.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431"},
+ {file = "websockets-15.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57"},
+ {file = "websockets-15.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905"},
+ {file = "websockets-15.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562"},
+ {file = "websockets-15.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792"},
+ {file = "websockets-15.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413"},
+ {file = "websockets-15.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8"},
+ {file = "websockets-15.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3"},
+ {file = "websockets-15.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf"},
+ {file = "websockets-15.0.1-cp311-cp311-win32.whl", hash = "sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85"},
+ {file = "websockets-15.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065"},
+ {file = "websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3"},
+ {file = "websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665"},
+ {file = "websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2"},
+ {file = "websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215"},
+ {file = "websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5"},
+ {file = "websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65"},
+ {file = "websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe"},
+ {file = "websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4"},
+ {file = "websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597"},
+ {file = "websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9"},
+ {file = "websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7"},
+ {file = "websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931"},
+ {file = "websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675"},
+ {file = "websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151"},
+ {file = "websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22"},
+ {file = "websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f"},
+ {file = "websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8"},
+ {file = "websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375"},
+ {file = "websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d"},
+ {file = "websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4"},
+ {file = "websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa"},
+ {file = "websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561"},
+ {file = "websockets-15.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f4c04ead5aed67c8a1a20491d54cdfba5884507a48dd798ecaf13c74c4489f5"},
+ {file = "websockets-15.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abdc0c6c8c648b4805c5eacd131910d2a7f6455dfd3becab248ef108e89ab16a"},
+ {file = "websockets-15.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a625e06551975f4b7ea7102bc43895b90742746797e2e14b70ed61c43a90f09b"},
+ {file = "websockets-15.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d591f8de75824cbb7acad4e05d2d710484f15f29d4a915092675ad3456f11770"},
+ {file = "websockets-15.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47819cea040f31d670cc8d324bb6435c6f133b8c7a19ec3d61634e62f8d8f9eb"},
+ {file = "websockets-15.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac017dd64572e5c3bd01939121e4d16cf30e5d7e110a119399cf3133b63ad054"},
+ {file = "websockets-15.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4a9fac8e469d04ce6c25bb2610dc535235bd4aa14996b4e6dbebf5e007eba5ee"},
+ {file = "websockets-15.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363c6f671b761efcb30608d24925a382497c12c506b51661883c3e22337265ed"},
+ {file = "websockets-15.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2034693ad3097d5355bfdacfffcbd3ef5694f9718ab7f29c29689a9eae841880"},
+ {file = "websockets-15.0.1-cp39-cp39-win32.whl", hash = "sha256:3b1ac0d3e594bf121308112697cf4b32be538fb1444468fb0a6ae4feebc83411"},
+ {file = "websockets-15.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7643a03db5c95c799b89b31c036d5f27eeb4d259c798e878d6937d71832b1e4"},
+ {file = "websockets-15.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0c9e74d766f2818bb95f84c25be4dea09841ac0f734d1966f415e4edfc4ef1c3"},
+ {file = "websockets-15.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1009ee0c7739c08a0cd59de430d6de452a55e42d6b522de7aa15e6f67db0b8e1"},
+ {file = "websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d1f20b1c7a2fa82367e04982e708723ba0e7b8d43aa643d3dcd404d74f1475"},
+ {file = "websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f29d80eb9a9263b8d109135351caf568cc3f80b9928bccde535c235de55c22d9"},
+ {file = "websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b359ed09954d7c18bbc1680f380c7301f92c60bf924171629c5db97febb12f04"},
+ {file = "websockets-15.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cad21560da69f4ce7658ca2cb83138fb4cf695a2ba3e475e0559e05991aa8122"},
+ {file = "websockets-15.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7f493881579c90fc262d9cdbaa05a6b54b3811c2f300766748db79f098db9940"},
+ {file = "websockets-15.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:47b099e1f4fbc95b701b6e85768e1fcdaf1630f3cbe4765fa216596f12310e2e"},
+ {file = "websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67f2b6de947f8c757db2db9c71527933ad0019737ec374a8a6be9a956786aaf9"},
+ {file = "websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d08eb4c2b7d6c41da6ca0600c077e93f5adcfd979cd777d747e9ee624556da4b"},
+ {file = "websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b826973a4a2ae47ba357e4e82fa44a463b8f168e1ca775ac64521442b19e87f"},
+ {file = "websockets-15.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:21c1fa28a6a7e3cbdc171c694398b6df4744613ce9b36b1a498e816787e28123"},
+ {file = "websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f"},
+ {file = "websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee"},
+]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.12"
+content-hash = "62614fb148de5562276e0d38d01a7ff23c60391b80b5092ef93846cb2478e4cb"
--- /dev/null
+[tool.poetry]
+name = "ocpp-server"
+version = "2.0.10"
+description = "OCPP2 mock server"
+authors = ["Jérôme Benoit <jerome.benoit@sap.com>"]
+readme = "README.md"
+
+[tool.poetry.dependencies]
+python = "^3.12"
+websockets = "^15.0"
+ocpp = "^2.0.0"
+
+[tool.poetry.group.dev.dependencies]
+taskipy = "^1"
+ruff = "^0.12"
+
+[tool.taskipy.tasks]
+server = "poetry run python server.py"
+format = "ruff check --fix . && ruff format ."
+lint = "ruff check --diff . && ruff format --check --diff ."
+
+[tool.ruff.lint]
+select = ["E", "W", "F", "ASYNC", "S", "B", "A", "Q", "RUF", "I"]
+
+
+[build-system]
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
--- /dev/null
+import argparse
+import asyncio
+import logging
+from datetime import datetime, timezone
+from functools import partial
+from random import randint
+from typing import Optional
+
+import ocpp.v201
+import websockets
+from ocpp.routing import on
+from ocpp.v201.enums import (
+ Action,
+ AuthorizationStatusEnumType,
+ ClearCacheStatusEnumType,
+ GenericDeviceModelStatusEnumType,
+ RegistrationStatusEnumType,
+ ReportBaseEnumType,
+ TransactionEventEnumType,
+)
+from websockets import ConnectionClosed
+
+from timer import Timer
+
+# Setting up the logging configuration to display debug level messages.
+logging.basicConfig(level=logging.DEBUG)
+
+ChargePoints = set()
+
+
+class ChargePoint(ocpp.v201.ChargePoint):
+ _command_timer: Optional[Timer]
+
+ def __init__(self, connection):
+ super().__init__(connection.path.strip("/"), connection)
+ self._command_timer = None
+
+ # Message handlers to receive OCPP messages.
+ @on(Action.boot_notification)
+ async def on_boot_notification(self, charging_station, reason, **kwargs):
+ logging.info("Received %s", Action.boot_notification)
+ # Create and return a BootNotification response with the current time,
+ # an interval of 60 seconds, and an accepted status.
+ return ocpp.v201.call_result.BootNotification(
+ current_time=datetime.now(timezone.utc).isoformat(),
+ interval=60,
+ status=RegistrationStatusEnumType.accepted,
+ )
+
+ @on(Action.heartbeat)
+ async def on_heartbeat(self, **kwargs):
+ logging.info("Received %s", Action.heartbeat)
+ return ocpp.v201.call_result.Heartbeat(
+ current_time=datetime.now(timezone.utc).isoformat()
+ )
+
+ @on(Action.status_notification)
+ async def on_status_notification(
+ self, timestamp, evse_id: int, connector_id: int, connector_status, **kwargs
+ ):
+ logging.info("Received %s", Action.status_notification)
+ return ocpp.v201.call_result.StatusNotification()
+
+ @on(Action.authorize)
+ async def on_authorize(self, id_token, **kwargs):
+ logging.info("Received %s", Action.authorize)
+ return ocpp.v201.call_result.Authorize(
+ id_token_info={"status": AuthorizationStatusEnumType.accepted}
+ )
+
+ @on(Action.transaction_event)
+ async def on_transaction_event(
+ self,
+ event_type: TransactionEventEnumType,
+ timestamp,
+ trigger_reason,
+ seq_no: int,
+ transaction_info,
+ **kwargs,
+ ):
+ match event_type:
+ case TransactionEventEnumType.started:
+ logging.info("Received %s Started", Action.transaction_event)
+ return ocpp.v201.call_result.TransactionEvent(
+ id_token_info={"status": AuthorizationStatusEnumType.accepted}
+ )
+ case TransactionEventEnumType.updated:
+ logging.info("Received %s Updated", Action.transaction_event)
+ return ocpp.v201.call_result.TransactionEvent(total_cost=10)
+ case TransactionEventEnumType.ended:
+ logging.info("Received %s Ended", Action.transaction_event)
+ return ocpp.v201.call_result.TransactionEvent()
+
+ @on(Action.meter_values)
+ async def on_meter_values(self, evse_id: int, meter_value, **kwargs):
+ logging.info("Received %s", Action.meter_values)
+ return ocpp.v201.call_result.MeterValues()
+
+ # Request handlers to emit OCPP messages.
+ async def _send_clear_cache(self):
+ request = ocpp.v201.call.ClearCache()
+ response = await self.call(request)
+
+ if response.status == ClearCacheStatusEnumType.accepted:
+ logging.info("%s successful", Action.clear_cache)
+ else:
+ logging.info("%s failed", Action.clear_cache)
+
+ async def _send_get_base_report(self):
+ request = ocpp.v201.call.GetBaseReport(
+ request_id=randint(1, 100), # noqa: S311
+ report_base=ReportBaseEnumType.full_inventory,
+ )
+ response = await self.call(request)
+
+ if response.status == GenericDeviceModelStatusEnumType.accepted:
+ logging.info("%s successful", Action.get_base_report)
+ else:
+ logging.info("%s failed", Action.get_base_report)
+
+ async def _send_command(self, command_name: Action):
+ logging.debug("Sending OCPP command %s", command_name)
+ match command_name:
+ case Action.clear_cache:
+ await self._send_clear_cache()
+ case Action.get_base_report:
+ await self._send_get_base_report()
+ case _:
+ logging.info(f"Not supported command {command_name}")
+
+ async def send_command(
+ self, command_name: Action, delay: Optional[float], period: Optional[float]
+ ):
+ try:
+ if delay and not self._command_timer:
+ self._command_timer = Timer(
+ delay,
+ False,
+ self._send_command,
+ [command_name],
+ )
+ if period and not self._command_timer:
+ self._command_timer = Timer(
+ period,
+ True,
+ self._send_command,
+ [command_name],
+ )
+ except ConnectionClosed:
+ self.handle_connection_closed()
+
+ def handle_connection_closed(self):
+ logging.info("ChargePoint %s closed connection", self.id)
+ if self._command_timer:
+ self._command_timer.cancel()
+ ChargePoints.remove(self)
+ logging.debug("Connected ChargePoint(s): %d", len(ChargePoints))
+
+
+# Function to handle new WebSocket connections.
+async def on_connect(
+ websocket,
+ command_name: Optional[Action],
+ delay: Optional[float],
+ period: Optional[float],
+):
+ """For every new charge point that connects, create a ChargePoint instance and start
+ listening for messages.
+ """
+ try:
+ requested_protocols = websocket.request_headers["Sec-WebSocket-Protocol"]
+ except KeyError:
+ logging.info("Client hasn't requested any Subprotocol. Closing Connection")
+ return await websocket.close()
+
+ if websocket.subprotocol:
+ logging.info("Protocols Matched: %s", websocket.subprotocol)
+ else:
+ logging.warning(
+ "Protocols Mismatched | Expected Subprotocols: %s,"
+ " but client supports %s | Closing connection",
+ websocket.available_subprotocols,
+ requested_protocols,
+ )
+ return await websocket.close()
+
+ cp = ChargePoint(websocket)
+ if command_name:
+ await cp.send_command(command_name, delay, period)
+
+ ChargePoints.add(cp)
+
+ try:
+ await cp.start()
+ except ConnectionClosed:
+ cp.handle_connection_closed()
+
+
+def check_positive_number(value: Optional[float]):
+ try:
+ value = float(value)
+ except ValueError:
+ raise argparse.ArgumentTypeError("must be a number") from None
+ if value <= 0:
+ raise argparse.ArgumentTypeError("must be a positive number")
+ return value
+
+
+# Main function to start the WebSocket server.
+async def main():
+ parser = argparse.ArgumentParser(description="OCPP2 Server")
+ parser.add_argument("-c", "--command", type=Action, help="command name")
+ group = parser.add_mutually_exclusive_group()
+ group.add_argument(
+ "-d",
+ "--delay",
+ type=check_positive_number,
+ help="delay in seconds",
+ )
+ group.add_argument(
+ "-p",
+ "--period",
+ type=check_positive_number,
+ help="period in seconds",
+ )
+ group.required = parser.parse_known_args()[0].command is not None
+
+ args = parser.parse_args()
+
+ # Create the WebSocket server and specify the handler for new connections.
+ server = await websockets.serve(
+ partial(
+ on_connect, command_name=args.command, delay=args.delay, period=args.period
+ ),
+ "127.0.0.1", # Listen on loopback.
+ 9000, # Port number.
+ subprotocols=["ocpp2.0", "ocpp2.0.1"], # Specify OCPP 2.0.1 subprotocols.
+ )
+ logging.info("WebSocket Server Started")
+
+ # Wait for the server to close (runs indefinitely).
+ await server.wait_closed()
+
+
+# Entry point of the script.
+if __name__ == "__main__":
+ # Run the main function to start the server.
+ asyncio.run(main())
--- /dev/null
+"""Timer for asyncio."""
+
+import asyncio
+
+
+class Timer:
+ def __init__(
+ self,
+ timeout: float,
+ repeat: bool,
+ callback,
+ callback_args=(),
+ callback_kwargs=None,
+ ):
+ """
+ An asynchronous Timer object.
+
+ Parameters
+ ----------
+ timeout: :class:`float`:
+ The duration for which the timer should last.
+
+ repeat: :class:`bool`:
+ Whether the timer should repeat.
+
+ callback: :class:`Coroutine` or `Method` or `Function`:
+ An `asyncio` coroutine or a regular method that will be called as soon as
+ the timer ends.
+
+ callback_args: Optional[:class:`tuple`]:
+ The args to be passed to the callback.
+
+ callback_kwargs: Optional[:class:`dict`]:
+ The kwargs to be passed to the callback.
+ """
+ self._timeout = timeout
+ self._repeat = repeat
+ self._callback = callback
+ self._task = asyncio.create_task(self._job())
+ self._callback_args = callback_args
+ if callback_kwargs is None:
+ callback_kwargs = {}
+ self._callback_kwargs = callback_kwargs
+
+ async def _job(self):
+ if self._repeat:
+ while self._task.cancelled() is False:
+ await asyncio.sleep(self._timeout)
+ await self._call_callback()
+ else:
+ await asyncio.sleep(self._timeout)
+ await self._call_callback()
+
+ async def _call_callback(self):
+ if asyncio.iscoroutine(self._callback) or asyncio.iscoroutinefunction(
+ self._callback
+ ):
+ await self._callback(*self._callback_args, **self._callback_kwargs)
+ else:
+ self._callback(*self._callback_args, **self._callback_kwargs)
+
+ def cancel(self):
+ """Cancels the timer. The callback will not be called."""
+ self._task.cancel()
--- /dev/null
+import { expect } from '@std/expect'
+import { describe, it } from 'node:test'
+
+import {
+ ApplicationProtocolVersion,
+ ConfigurationSection,
+ SupervisionUrlDistribution,
+} from '../../src/types/ConfigurationData.js'
+
+await describe('ConfigurationData test suite', async () => {
+ await it('Verify ConfigurationSection enumeration', () => {
+ expect(ConfigurationSection.log).toBe('log')
+ expect(ConfigurationSection.performanceStorage).toBe('performanceStorage')
+ expect(ConfigurationSection.uiServer).toBe('uiServer')
+ expect(ConfigurationSection.worker).toBe('worker')
+ })
+
+ await it('Verify SupervisionUrlDistribution enumeration', () => {
+ expect(SupervisionUrlDistribution.CHARGING_STATION_AFFINITY).toBe('charging-station-affinity')
+ expect(SupervisionUrlDistribution.RANDOM).toBe('random')
+ expect(SupervisionUrlDistribution.ROUND_ROBIN).toBe('round-robin')
+ })
+
+ await it('Verify ApplicationProtocolVersion enumeration', () => {
+ expect(ApplicationProtocolVersion.VERSION_11).toBe('1.1')
+ expect(ApplicationProtocolVersion.VERSION_20).toBe('2.0')
+ })
+})
--- /dev/null
+import { expect } from '@std/expect'
+import { randomInt } from 'node:crypto'
+import { describe, it } from 'node:test'
+
+import { AsyncLock, AsyncLockType } from '../../src/utils/AsyncLock.js'
+
+await describe('AsyncLock test suite', async () => {
+ await it('Verify runExclusive() on sync fn', () => {
+ const runs = 10
+ const executed: number[] = []
+ let count = 0
+ const fn = () => {
+ executed.push(++count)
+ }
+ for (let i = 0; i < runs; i++) {
+ AsyncLock.runExclusive(AsyncLockType.configuration, fn)
+ .then(() => {
+ expect(executed).toStrictEqual(new Array(count).fill(0).map((_, i) => ++i))
+ return undefined
+ })
+ .catch(console.error)
+ }
+ })
+
+ await it('Verify runExclusive() on async fn', () => {
+ const runs = 10
+ const executed: number[] = []
+ let count = 0
+ const asyncFn = async () => {
+ await new Promise(resolve => {
+ setTimeout(resolve, randomInt(1, 100))
+ })
+ executed.push(++count)
+ }
+ for (let i = 0; i < runs; i++) {
+ AsyncLock.runExclusive(AsyncLockType.configuration, asyncFn)
+ .then(() => {
+ expect(executed).toStrictEqual(new Array(count).fill(0).map((_, i) => ++i))
+ return undefined
+ })
+ .catch(console.error)
+ }
+ })
+})
--- /dev/null
+// /* eslint-disable @typescript-eslint/no-unsafe-member-access */
+// import { expect } from '@std/expect'
+// import { describe, it } from 'node:test'
+
+// import { FileType } from '../../src/types/index.js'
+// import { handleFileException, logPrefix } from '../../src/utils/ConfigurationUtils.js'
+
+// await describe('ConfigurationUtils test suite', async () => {
+// await it('Verify logPrefix()', () => {
+// expect(logPrefix()).toContain(' Simulator configuration |')
+// })
+
+// await it('Verify handleFileException()', t => {
+// t.mock.method(console, 'error')
+// const error = new Error()
+// error.code = 'ENOENT'
+// expect(() => {
+// handleFileException('path/to/module.js', FileType.Authorization, error, 'log prefix |')
+// }).toThrow(error)
+// expect(console.error.mock.calls.length).toBe(1)
+// })
+// })
+import { expect } from '@std/expect'
import { describe, it } from 'node:test'
-import { expect } from 'expect'
-
import { ACElectricUtils, DCElectricUtils } from '../../src/utils/ElectricUtils.js'
await describe('ElectricUtils test suite', async () => {
--- /dev/null
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+
+import { expect } from '@std/expect'
+import { describe, it } from 'node:test'
+
+import type { ChargingStation } from '../../src/charging-station/index.js'
+
+import {
+ FileType,
+ GenericStatus,
+ IncomingRequestCommand,
+ MessageType,
+ RequestCommand,
+} from '../../src/types/index.js'
+import {
+ handleFileException,
+ handleIncomingRequestError,
+ handleSendMessageError,
+} from '../../src/utils/ErrorUtils.js'
+import { logger } from '../../src/utils/Logger.js'
+
+await describe('ErrorUtils test suite', async () => {
+ const chargingStation = {
+ logPrefix: () => 'CS-TEST |',
+ } as ChargingStation
+
+ await it('Verify handleFileException()', t => {
+ t.mock.method(console, 'warn')
+ t.mock.method(console, 'error')
+ t.mock.method(logger, 'warn')
+ t.mock.method(logger, 'error')
+ const error = new Error()
+ error.code = 'ENOENT'
+ expect(() => {
+ handleFileException('path/to/module.js', FileType.Authorization, error, 'log prefix |', {})
+ }).toThrow(error)
+ expect(() => {
+ handleFileException('path/to/module.js', FileType.Authorization, error, 'log prefix |', {
+ throwError: false,
+ })
+ }).not.toThrow()
+ expect(logger.warn.mock.calls.length).toBe(1)
+ expect(logger.error.mock.calls.length).toBe(1)
+ expect(() => {
+ handleFileException('path/to/module.js', FileType.Authorization, error, 'log prefix |', {
+ consoleOut: true,
+ })
+ }).toThrow(error)
+ expect(() => {
+ handleFileException('path/to/module.js', FileType.Authorization, error, 'log prefix |', {
+ consoleOut: true,
+ throwError: false,
+ })
+ }).not.toThrow()
+ expect(console.warn.mock.calls.length).toBe(1)
+ expect(console.error.mock.calls.length).toBe(1)
+ })
+
+ await it('Verify handleSendMessageError()', t => {
+ t.mock.method(logger, 'error')
+ t.mock.method(chargingStation, 'logPrefix')
+ const error = new Error()
+ expect(() => {
+ handleSendMessageError(
+ chargingStation,
+ RequestCommand.BOOT_NOTIFICATION,
+ MessageType.CALL_MESSAGE,
+ error
+ )
+ }).not.toThrow()
+ expect(() => {
+ handleSendMessageError(
+ chargingStation,
+ RequestCommand.BOOT_NOTIFICATION,
+ MessageType.CALL_MESSAGE,
+ error,
+ { throwError: true }
+ )
+ }).toThrow(error)
+ expect(chargingStation.logPrefix.mock.calls.length).toBe(2)
+ expect(logger.error.mock.calls.length).toBe(2)
+ })
+
+ await it('Verify handleIncomingRequestError()', t => {
+ t.mock.method(logger, 'error')
+ t.mock.method(chargingStation, 'logPrefix')
+ const error = new Error()
+ expect(() => {
+ handleIncomingRequestError(chargingStation, IncomingRequestCommand.CLEAR_CACHE, error)
+ }).toThrow(error)
+ expect(() => {
+ handleIncomingRequestError(chargingStation, IncomingRequestCommand.CLEAR_CACHE, error, {
+ throwError: false,
+ })
+ }).not.toThrow()
+ const errorResponse = {
+ status: GenericStatus.Rejected,
+ }
+ expect(
+ handleIncomingRequestError(chargingStation, IncomingRequestCommand.CLEAR_CACHE, error, {
+ errorResponse,
+ throwError: false,
+ })
+ ).toStrictEqual(errorResponse)
+ expect(chargingStation.logPrefix.mock.calls.length).toBe(3)
+ expect(logger.error.mock.calls.length).toBe(3)
+ })
+})
+import { expect } from '@std/expect'
import { describe, it } from 'node:test'
-import { expect } from 'expect'
-
-import { max, min, nthPercentile, stdDeviation } from '../../src/utils/StatisticUtils.js'
+import { average, max, median, min, percentile, std } from '../../src/utils/StatisticUtils.js'
await describe('StatisticUtils test suite', async () => {
+ await it('Verify average()', () => {
+ expect(average([])).toBe(0)
+ expect(average([0.08])).toBe(0.08)
+ expect(average([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(3.1642857142857146)
+ expect(average([0.25, 4.75, 3.05, 6.04, 1.01, 2.02])).toBe(2.8533333333333335)
+ })
+
+ await it('Verify median()', () => {
+ expect(median([])).toBe(0)
+ expect(median([0.08])).toBe(0.08)
+ expect(median([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(3.05)
+ expect(median([0.25, 4.75, 3.05, 6.04, 1.01, 2.02])).toBe(2.535)
+ })
+
await it('Verify min()', () => {
expect(min()).toBe(Number.POSITIVE_INFINITY)
expect(min(0, 1)).toBe(0)
expect(max(-1, 0)).toBe(0)
})
- await it('Verify nthPercentile()', () => {
- expect(nthPercentile([], 25)).toBe(0)
- expect(nthPercentile([0.08], 50)).toBe(0.08)
+ await it('Verify percentile()', () => {
+ expect(percentile([], 25)).toBe(0)
+ expect(percentile([0.08], 50)).toBe(0.08)
const array0 = [0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03]
- expect(nthPercentile(array0, 0)).toBe(0.25)
- expect(nthPercentile(array0, 50)).toBe(3.05)
- expect(nthPercentile(array0, 80)).toBe(4.974)
- expect(nthPercentile(array0, 85)).toBe(5.131)
- expect(nthPercentile(array0, 90)).toBe(5.434)
- expect(nthPercentile(array0, 95)).toBe(5.736999999999999)
- expect(nthPercentile(array0, 100)).toBe(6.04)
+ expect(percentile(array0, 0)).toBe(0.25)
+ expect(percentile(array0, 50)).toBe(3.05)
+ expect(percentile(array0, 80)).toBe(4.974)
+ expect(percentile(array0, 85)).toBe(5.131)
+ expect(percentile(array0, 90)).toBe(5.434)
+ expect(percentile(array0, 95)).toBe(5.736999999999999)
+ expect(percentile(array0, 100)).toBe(6.04)
})
- await it('Verify stdDeviation()', () => {
- expect(stdDeviation([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(2.1879050645374383)
+ await it('Verify std()', () => {
+ expect(std([0.25, 4.75, 3.05, 6.04, 1.01, 2.02, 5.03])).toBe(2.1879050645374383)
})
})
+import { expect } from '@std/expect'
+import { hoursToMilliseconds, hoursToSeconds } from 'date-fns'
+import { CircularBuffer } from 'mnemonist'
import { randomInt } from 'node:crypto'
import { version } from 'node:process'
import { describe, it } from 'node:test'
-
-import { hoursToMilliseconds, hoursToSeconds } from 'date-fns'
-import { expect } from 'expect'
-import { CircularBuffer } from 'mnemonist'
import { satisfies } from 'semver'
import type { TimestampedData } from '../../src/types/index.js'
+
+import { JSRuntime, runtime } from '../../scripts/runtime.js'
import { Constants } from '../../src/utils/Constants.js'
import {
clone,
formatDurationSeconds,
generateUUID,
getRandomFloat,
- hasOwnProp,
+ has,
+ insertAt,
isArraySorted,
isAsyncFunction,
+ isEmpty,
isNotEmptyArray,
isNotEmptyString,
- isObject,
isValidDate,
+ once,
roundTo,
secureRandom,
sleep,
- validateUUID
+ validateUUID,
} from '../../src/utils/Utils.js'
await describe('Utils test suite', async () => {
expect(extractTimeSeriesValues(circularBuffer)).toEqual([1.1, 2.2, 3.3])
})
- await it('Verify isObject()', () => {
- expect(isObject('test')).toBe(false)
- expect(isObject(undefined)).toBe(false)
- expect(isObject(null)).toBe(false)
- expect(isObject(0)).toBe(false)
- expect(isObject([])).toBe(false)
- expect(isObject([0, 1])).toBe(false)
- expect(isObject(['0', '1'])).toBe(false)
- expect(isObject({})).toBe(true)
- expect(isObject({ 1: 1 })).toBe(true)
- expect(isObject({ 1: '1' })).toBe(true)
- expect(isObject(new Map())).toBe(true)
- expect(isObject(new Set())).toBe(true)
- expect(isObject(new WeakMap())).toBe(true)
- expect(isObject(new WeakSet())).toBe(true)
- })
-
await it('Verify isAsyncFunction()', () => {
expect(isAsyncFunction(null)).toBe(false)
expect(isAsyncFunction(undefined)).toBe(false)
expect(isAsyncFunction('')).toBe(false)
expect(isAsyncFunction([])).toBe(false)
expect(isAsyncFunction(new Date())).toBe(false)
- // eslint-disable-next-line prefer-regex-literals
- expect(isAsyncFunction(new RegExp('[a-z]', 'i'))).toBe(false)
+ expect(isAsyncFunction(/[a-z]/i)).toBe(false)
expect(isAsyncFunction(new Error())).toBe(false)
expect(isAsyncFunction(new Map())).toBe(false)
expect(isAsyncFunction(new Set())).toBe(false)
expect(isAsyncFunction(async function named () {})).toBe(true)
class TestClass {
// eslint-disable-next-line @typescript-eslint/no-empty-function
- public testSync (): void {}
- // eslint-disable-next-line @typescript-eslint/no-empty-function
- public async testAsync (): Promise<void> {}
+ public static async testStaticAsync (): Promise<void> {}
// eslint-disable-next-line @typescript-eslint/no-empty-function
- public testArrowSync = (): void => {}
+ public static testStaticSync (): void {}
// eslint-disable-next-line @typescript-eslint/no-empty-function
public testArrowAsync = async (): Promise<void> => {}
// eslint-disable-next-line @typescript-eslint/no-empty-function
- public static testStaticSync (): void {}
+ public testArrowSync = (): void => {}
// eslint-disable-next-line @typescript-eslint/no-empty-function
- public static async testStaticAsync (): Promise<void> {}
+ public async testAsync (): Promise<void> {}
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
+ public testSync (): void {}
}
const testClass = new TestClass()
// eslint-disable-next-line @typescript-eslint/unbound-method
const date = new Date()
expect(clone(date)).toStrictEqual(date)
expect(clone(date) === date).toBe(false)
- if (satisfies(version, '>=21.0.0')) {
+ if (runtime === JSRuntime.node && satisfies(version, '>=22.0.0')) {
const url = new URL('https://domain.tld')
- expect(() => clone(url)).toThrowError(new Error('Cannot clone object of unsupported type.'))
+ expect(() => clone(url)).toThrow(new Error('Cannot clone object of unsupported type.'))
}
const map = new Map([['1', '2']])
expect(clone(map)).toStrictEqual(map)
expect(clone(set)).toStrictEqual(set)
expect(clone(set) === set).toBe(false)
const weakMap = new WeakMap([[{ 1: 1 }, { 2: 2 }]])
- expect(() => clone(weakMap)).toThrowError(new Error('#<WeakMap> could not be cloned.'))
+ expect(() => clone(weakMap)).toThrow(new Error('#<WeakMap> could not be cloned.'))
const weakSet = new WeakSet([{ 1: 1 }, { 2: 2 }])
- expect(() => clone(weakSet)).toThrowError(new Error('#<WeakSet> could not be cloned.'))
+ expect(() => clone(weakSet)).toThrow(new Error('#<WeakSet> could not be cloned.'))
+ })
+
+ await it('Verify once()', () => {
+ let called = 0
+ const fn = (): number => ++called
+ const onceFn = once(fn)
+ const result1 = onceFn()
+ expect(called).toBe(1)
+ expect(result1).toBe(1)
+ const result2 = onceFn()
+ expect(called).toBe(1)
+ expect(result2).toBe(1)
+ const result3 = onceFn()
+ expect(called).toBe(1)
+ expect(result3).toBe(1)
+ })
+
+ await it('Verify has()', () => {
+ expect(has('', 'test')).toBe(false)
+ expect(has('test', '')).toBe(false)
+ expect(has('test', 'test')).toBe(false)
+ expect(has('', undefined)).toBe(false)
+ expect(has('', null)).toBe(false)
+ expect(has('', [])).toBe(false)
+ expect(has('', {})).toBe(false)
+ expect(has(1, { 1: 1 })).toBe(true)
+ expect(has('1', { 1: 1 })).toBe(true)
+ expect(has(2, { 1: 1 })).toBe(false)
+ expect(has('2', { 1: 1 })).toBe(false)
+ expect(has('1', { 1: '1' })).toBe(true)
+ expect(has(1, { 1: '1' })).toBe(true)
+ expect(has('2', { 1: '1' })).toBe(false)
+ expect(has(2, { 1: '1' })).toBe(false)
})
- await it('Verify hasOwnProp()', () => {
- expect(hasOwnProp('test', '')).toBe(false)
- expect(hasOwnProp(undefined, '')).toBe(false)
- expect(hasOwnProp(null, '')).toBe(false)
- expect(hasOwnProp([], '')).toBe(false)
- expect(hasOwnProp({}, '')).toBe(false)
- expect(hasOwnProp({ 1: 1 }, 1)).toBe(true)
- expect(hasOwnProp({ 1: 1 }, '1')).toBe(true)
- expect(hasOwnProp({ 1: 1 }, 2)).toBe(false)
- expect(hasOwnProp({ 1: 1 }, '2')).toBe(false)
- expect(hasOwnProp({ 1: '1' }, '1')).toBe(true)
- expect(hasOwnProp({ 1: '1' }, 1)).toBe(true)
- expect(hasOwnProp({ 1: '1' }, '2')).toBe(false)
- expect(hasOwnProp({ 1: '1' }, 2)).toBe(false)
+ await it('Verify isEmpty()', () => {
+ expect(isEmpty('')).toBe(true)
+ expect(isEmpty(' ')).toBe(false)
+ expect(isEmpty(' ')).toBe(false)
+ expect(isEmpty('test')).toBe(false)
+ expect(isEmpty(' test')).toBe(false)
+ expect(isEmpty('test ')).toBe(false)
+ expect(isEmpty(undefined)).toBe(false)
+ expect(isEmpty(null)).toBe(false)
+ expect(isEmpty(0)).toBe(false)
+ expect(isEmpty({})).toBe(true)
+ expect(isEmpty([])).toBe(true)
+ expect(isEmpty(new Map())).toBe(true)
+ expect(isEmpty(new Set())).toBe(true)
+ expect(isEmpty(new WeakMap())).toBe(false)
+ expect(isEmpty(new WeakSet())).toBe(false)
})
await it('Verify isNotEmptyString()', () => {
expect(isNotEmptyArray(new WeakSet())).toBe(false)
})
+ await it('Verify insertAt()', () => {
+ expect(insertAt('test', 'ing', 'test'.length)).toBe('testing')
+ // eslint-disable-next-line @cspell/spellchecker
+ expect(insertAt('test', 'ing', 2)).toBe('teingst')
+ })
+
await it('Verify isArraySorted()', () => {
- expect(
- isArraySorted([], (a, b) => {
- return a - b
- })
- ).toBe(true)
- expect(
- isArraySorted([1], (a, b) => {
- return a - b
- })
- ).toBe(true)
+ expect(isArraySorted<number>([], (a, b) => a - b)).toBe(true)
+ expect(isArraySorted<number>([1], (a, b) => a - b)).toBe(true)
expect(isArraySorted<number>([1, 2, 3, 4, 5], (a, b) => a - b)).toBe(true)
expect(isArraySorted<number>([1, 2, 3, 5, 4], (a, b) => a - b)).toBe(false)
expect(isArraySorted<number>([2, 1, 3, 4, 5], (a, b) => a - b)).toBe(false)
"verbatimModuleSyntax": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
- "forceConsistentCasingInFileNames": true
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitOverride": true
},
- "exclude": ["ui/web/**/*.ts"]
+ "include": ["*.ts", "src/**/*.ts", "tests/**/*.ts"]
}
+++ /dev/null
-require('@rushstack/eslint-patch/modern-module-resolution')
-const { env } = require('node:process')
-const { defineConfig } = require('eslint-define-config')
-
-module.exports = defineConfig({
- root: true,
-
- env: {
- node: true
- },
-
- plugins: ['simple-import-sort'],
-
- extends: [
- 'eslint:recommended',
- 'plugin:import/recommended',
- 'plugin:import/typescript',
- 'plugin:vue/vue3-recommended',
- '@vue/eslint-config-typescript/recommended',
- '@vue/eslint-config-prettier'
- ],
-
- settings: {
- 'import/resolver': {
- typescript: {
- project: './tsconfig.json'
- }
- }
- },
-
- parserOptions: {
- sourceType: 'module',
- ecmaVersion: 'latest'
- },
-
- rules: {
- 'no-console': env.NODE_ENV === 'production' ? 'warn' : 'off',
- 'no-debugger': env.NODE_ENV === 'production' ? 'warn' : 'off',
- 'simple-import-sort/imports': 'error',
- 'simple-import-sort/exports': 'error',
- 'vue/multi-word-component-names': 'off'
- }
-})
export default {
- '*.{.css,json,md,yml,yaml,html,js,jsx,cjs,mjs,ts,tsx,cts,mts}': 'prettier --cache --write',
- '*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}':
- 'eslint . --cache --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore'
+ '*.{css,json,md,yml,yaml,html,js,jsx,cjs,mjs,ts,tsx,cts,mts}': 'prettier --cache --write',
+ '*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}': 'eslint --cache --fix',
}
"arrowParens": "avoid",
"singleQuote": true,
"semi": false,
- "trailingComma": "none"
+ "trailingComma": "es5"
}
--- /dev/null
+# Changelog
+
+## [2.0.10](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/webui@v2.0.9...webui@v2.0.10) (2025-07-03)
+
+### 🤖 Automation
+
+- **deps:** bump the regular group across 1 directory with 6 updates ([#1452](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1452)) ([b039a4f](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b039a4fc9382aec82b63e48b126a47cb615f7dd4))
+
+## [2.0.9](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/webui@v2.0.8...webui@v2.0.9) (2025-06-27)
+
+### 🤖 Automation
+
+- **deps-dev:** bump @types/node from 22.15.31 to 24.0.0 ([#1437](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1437)) ([b871758](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b871758ddaa7e28b479d45bf7585f172b4db36c4))
+- **deps-dev:** bump the regular group with 2 updates ([#1444](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1444)) ([dcd454c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/dcd454c166a2afcc25f992d3cb7c0fb6f7a07284))
+- **deps-dev:** bump the vite group with 3 updates ([1cd81ff](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1cd81ff001b7505ddbdd9260bc5485367ac8973a))
+
+## [2.0.8](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/webui@v2.0.7...webui@v2.0.8) (2025-05-27)
+
+### 🐞 Bug Fixes
+
+- **docker:** dependencies installation with latest pnpm ([b1dab0c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b1dab0ce2c231c96a3ba1aecb559054879745170))
+
+## [2.0.7](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/webui@v2.0.6...webui@v2.0.7) (2025-04-30)
+
+### 🤖 Automation
+
+- **deps-dev:** bump the regular group across 1 directory with 5 updates ([#1396](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1396)) ([637b90c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/637b90ccf2a4c187e5681ab37d394e4cf57dd5bf))
+- **deps-dev:** bump vite from 6.2.5 to 6.2.6 in the regular group ([#1382](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1382)) ([c369454](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/c369454c86a86543f38ce9549d16ac57a7b4e360))
+- **deps-dev:** bump vite from 6.3.3 to 6.3.4 in the regular group ([#1400](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1400)) ([3ea8331](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/3ea83318991587b84a8d7df00655f437ef170752))
+- **deps:** bump the regular group across 1 directory with 7 updates ([#1393](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1393)) ([e55d6c4](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e55d6c40ca642e2dfb9f764a2b824a4eaba38494))
+
+## [2.0.6](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/webui@v2.0.5...webui@v2.0.6) (2025-04-08)
+
+### 🧹 Chores
+
+- **webui:** Synchronize simulator-ui-ocpp-server versions
+
+## [2.0.5](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/webui@v2.0.4...webui@v2.0.5) (2025-04-08)
+
+### 🤖 Automation
+
+- **deps-dev:** bump the regular group with 2 updates ([1b0518d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1b0518d781c3c2f5fb08243c5e8b39cbe8da871e))
+- **deps-dev:** bump the regular group with 2 updates ([a86ad89](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a86ad89b37158d888826946197e82e28afa51606))
+
+## [2.0.4](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/webui@v2.0.3...webui@v2.0.4) (2025-04-01)
+
+### 🤖 Automation
+
+- **deps-dev:** bump the regular group with 6 updates ([da28b39](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/da28b394d059de0fd2cfa28bafe037e382411f7e))
+- **deps:** bump the regular group with 6 updates ([#1357](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1357)) ([93c3165](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/93c3165637b688b851ac9de682e9fcc8cc4a6d00))
+
+## [2.0.3](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/webui@v2.0.2...webui@v2.0.3) (2025-03-17)
+
+### 🐞 Bug Fixes
+
+- **docker:** workaround corepack bug ([88a04b7](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/88a04b71ccf51cf4f94a279c95e072f0306d902b))
+
+### 🤖 Automation
+
+- **deps-dev:** bump @types/node in the regular group ([#1264](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1264)) ([7d3076d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/7d3076df490d0c4fe2f19bba39066384bf2a6060))
+- **deps-dev:** bump @types/node in the regular group ([#1269](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1269)) ([f76119c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f76119cefac3d3ef7f8186e5e37e92c11f58be5f))
+- **deps-dev:** bump @types/node in the regular group ([#1317](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1317)) ([cb49916](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/cb49916d261d2785d0fe96cdaf674e3fc6a29469))
+- **deps-dev:** bump jsdom from 25.0.1 to 26.0.0 ([#1276](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1276)) ([a082525](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a082525de20451c572433ac5cb9b4b6c0a908b1d))
+- **deps-dev:** bump the regular group across 1 directory with 6 updates ([#1300](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1300)) ([4ec2ae9](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/4ec2ae9d1a25c3e7605fa329a59a55b9b30708ca))
+- **deps-dev:** bump the regular group with 2 updates ([#1279](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1279)) ([84f9a57](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/84f9a5783bc76c46acf6a31c29f16f698096f318))
+- **deps-dev:** bump the regular group with 2 updates ([#1288](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1288)) ([1598cd2](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1598cd2b66f5ee794b3de24c3cddb7df27e058f9))
+- **deps-dev:** bump the regular group with 3 updates ([#1292](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1292)) ([460b4f7](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/460b4f787eaa9d6ec9ff928b5e674679ac069982))
+- **deps-dev:** bump the regular group with 3 updates ([#1316](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1316)) ([33f023c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/33f023c84ef127cd19d1034b0ca27dc54d18c30b))
+- **deps-dev:** bump the regular group with 5 updates ([#1347](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1347)) ([7de098e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/7de098e773583a32d92bd41babf6fb7590f637ee))
+- **deps-dev:** bump typescript in the typescript group ([db6e518](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/db6e518be63b8eba2510937c9291ac34acbd9563))
+- **deps-dev:** bump typescript in the typescript group ([#1275](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1275)) ([8a16c2c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/8a16c2cd8dea56de21d7a4bfabc2178b4091f6d8))
+- **deps-dev:** bump typescript in the typescript group ([#1336](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1336)) ([f59c2bc](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f59c2bc913c580258e8e574c6faa41cfbd0e2041))
+- **deps-dev:** bump vite from 5.4.11 to 5.4.12 ([#1293](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1293)) ([3935e7d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/3935e7dcb8b4d46c43f3b73db8cbd4cab0b6aa00))
+- **deps-dev:** bump vite from 5.4.14 to 6.2.0 in the vite group ([03487e6](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/03487e6ed10b9dccf45836dfc6f14e8e1ad53244))
+- **deps-dev:** bump vite from 6.2.1 to 6.2.2 in the regular group ([e406114](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e406114618fc4b9055eab801a4cca08b032683d7))
+- **deps:** bump finalhandler from 1.3.1 to 2.1.0 ([4c20ab7](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/4c20ab72a54def59e360353ebd2d82e8c4243129))
+- **deps:** bump the regular group across 1 directory with 3 updates ([3c61d82](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/3c61d827b67cda74fa4f0ff76d169a238f0ccf06))
+- **deps:** bump the regular group across 1 directory with 3 updates ([#1285](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1285)) ([1831ac9](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1831ac9e3426d88f58523de957428a121fd423b8))
+- **deps:** bump the regular group across 1 directory with 3 updates ([#1337](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1337)) ([efb264d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/efb264d54f0e3d3d0c6a024215915e95779127f8))
+- **deps:** bump the regular group across 1 directory with 5 updates ([074d58e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/074d58e7718045e8cbd1535c19f435ec27ef9d51))
+- **deps:** bump the regular group across 1 directory with 6 updates ([#1305](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1305)) ([fea949e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fea949ef7ab1ad7d8b30e34470f62703a711c067))
+- **deps:** bump the regular group across 1 directory with 9 updates ([5dd44c7](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/5dd44c73f3c8a77069d71631fa93e2d7ff9cbe6e))
+- **deps:** bump the regular group with 10 updates ([#1353](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1353)) ([0a7a66b](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/0a7a66bc2a448d881f63c361a39e193b13a8c2a3))
+- **deps:** bump the regular group with 14 updates ([97693a9](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/97693a9d2f0689847de045d4828cf3c6e1189d2e))
+- **deps:** bump the regular group with 5 updates ([dfca506](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/dfca506c9ff6d5908eeb6a8941967137e3bb4574))
+- **deps:** bump the regular group with 8 updates ([fd124fb](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fd124fbe6004358e03569ae44027bb9886063d9c))
+
+## [2.0.2](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/webui@v2.0.1...webui@v2.0.2) (2024-12-23)
+
+### ✨ Polish
+
+- cleanup event handling callbacks ([eeb27da](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/eeb27da6a0a27a68a6d5af86c288e2bf94b81dca))
+
+### 🤖 Automation
+
+- **deps-dev:** bump prettier from 3.4.1 to 3.4.2 in the regular group ([#1243](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1243)) ([a1bbf37](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a1bbf3717246b87c33e935cdb28179eb78eae109))
+- **deps-dev:** bump the regular group with 2 updates ([#1235](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1235)) ([0414e23](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/0414e23c28c3a44aea711d596516a21070a3b867))
+- **deps-dev:** bump the regular group with 5 updates ([#1239](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1239)) ([5b34f7a](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/5b34f7ae2193fedb89219b108bbcc696303bd910))
+- **deps-dev:** bump the regular group with 6 updates ([#1230](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1230)) ([6ffb90e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/6ffb90e3d27c1935dc65cf9517ecfec0bfe31053))
+- **deps:** bump the regular group with 2 updates ([#1228](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1228)) ([01ae0b2](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/01ae0b21e24f7490f67c7f51434c03854123be58))
+- **deps:** bump the regular group with 4 updates ([#1251](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1251)) ([2cfd250](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/2cfd2508ff99ea6600088b503e592ca0ef9a114c))
+
+## [2.0.1](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/webui@v2.0.0...webui@v2.0.1) (2024-11-22)
+
+### 🐞 Bug Fixes
+
+- ensure local storage is cleaned at CS deletion ([122e014](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/122e014f0d4d9b9a81b6113de3d280745747670d))
+- ensure undefined is handled at computing power limitation ([55a17ee](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/55a17ee03b588b4cd5b14276b1f103bcdd3ec0a4)), closes [#1223](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1223)
+
+### 🤖 Automation
+
+- **deps-dev:** bump @types/node in the regular group ([05eeba4](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/05eeba4c543c89a098f89d2859922ecca92d81d3))
+- **deps-dev:** bump @types/node in the regular group ([#1206](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1206)) ([009b39e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/009b39e67fc3ed602b676daa8d7984fee62a45dc))
+- **deps-dev:** bump @types/node in the regular group ([#1207](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1207)) ([a8ecc38](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a8ecc3853c85790d59a67befa2d31e588624d29d))
+- **deps-dev:** bump the regular group with 4 updates ([#1217](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1217)) ([639c849](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/639c849b2cf9fbc586f7b101896f7ed0cf61066e))
+- **deps:** bump the regular group across 1 directory with 2 updates ([#1203](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1203)) ([90eb3b3](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/90eb3b34a3679829df20d3b008115d23444d1c1e))
+- **deps:** bump the regular group with 11 updates ([#1215](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1215)) ([1c3e200](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1c3e200fa957bae57aa33da1117828abd6d7b61e))
+- **deps:** bump the regular group with 2 updates ([#1212](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1212)) ([7c4f2ba](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/7c4f2baeb2988e79e98a77a969f800c267c1fb44))
+- **deps:** bump the regular group with 2 updates ([#1219](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1219)) ([9b823a0](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/9b823a0faa557dadeb5ea951e76fb40ce875b553))
+- **deps:** bump the regular group with 5 updates ([#1205](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1205)) ([6e0ee99](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/6e0ee990fee626e27d99103aad81ccbc9658fd63))
+- **deps:** bump the regular group with 6 updates ([#1211](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1211)) ([636421d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/636421d3912f65978bc31ab486d4d9f0f6e3cc3d))
+- fix linter errors ([408b4e6](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/408b4e6d9b9a617ef4a1fc465e407e4711886b24))
+
+## [2.0.0](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/webui@v1.5.2...webui@v2.0.0) (2024-10-23)
+
+### 🤖 Automation
+
+- **deps:** bump the regular group with 2 updates ([#1197](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1197)) ([6f31a7a](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/6f31a7a48fbe760691ebc36695ca8ab07b538f8b))
+
+## [1.5.2](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/webui@v1.5.1...webui@v1.5.2) (2024-10-21)
+
+### 🐞 Bug Fixes
+
+- silence TS strict null check errors ([df60841](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/df60841b5f33a375830f6c8865bedaa9a54da65e))
+
+### ✨ Polish
+
+- cleanup blank lines ([b1421bc](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b1421bc351387bb5efd738f0be8cfd5ab94a4426))
+- **deps-dev:** remove unused deps ([fd855c1](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fd855c1b97eb0eb50caba0f766c94b2cea4ff5e0))
+- display transaction id in UI ([99fb669](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/99fb669336a4182fa6932a1e1b1c0eb2fad834aa))
+- **docker:** rename start.sh to run.sh ([baf8b16](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/baf8b16408ca3209ec4b9b8b07e1a9b026761444))
+- separate out dashboard docker image ([20fb109](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/20fb10949dc2553d7695be1aab02bf84a8ddab98)), closes [#1040](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1040)
+- switch to eslint-plugin-perfectionist ([0749233](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/0749233f25516e4c73ee8dbcea8c4ad6b8a506bb))
+- turn on `noImplicitOverride` in TS configuration ([6375d3c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/6375d3cdd7f42a6e125976df194f4fe689d24113))
+- use ENTRYPOINT syntax in docker files ([989108f](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/989108f63bd531f04b28e65c8b499c9dbf5bbed0))
+
+### 🧪 Tests
+
+- add checkStationInfoConnectorStatus() test ([dd81d27](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/dd81d27d043073971f29ec761261489f16c66541))
+
+### 🤖 Automation
+
+- **deps-dev:** bump @types/node from 22.0.3 to 22.1.0 ([#1120](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1120)) ([c11dc2a](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/c11dc2a0aca044ee03dc565dfaff7342b4ce039a))
+- **deps-dev:** bump @vitest/coverage-v8 from 2.0.4 to 2.0.5 ([#1117](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1117)) ([4ee8259](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/4ee82592a066961b6877858ed29a825bfd480acf))
+- **deps-dev:** bump jsdom from 24.1.1 to 25.0.0 in the major group ([#1152](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1152)) ([bb7aeb1](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/bb7aeb1e64f53b1b3af1b1b33c405bb13310578c))
+- **deps-dev:** bump the regular group with 2 updates ([cc3e26b](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/cc3e26b41348dffd62937a9b44e4b22d963beebc))
+- **deps-dev:** bump the regular group with 2 updates ([#1156](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1156)) ([d366869](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/d36686932f284482ecfd095387a717b92ce64b5a))
+- **deps-dev:** bump the regular group with 2 updates ([#1183](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1183)) ([9de6af7](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/9de6af7490dc616d685c474b0d54c19c53fb15cd))
+- **deps-dev:** bump the regular group with 3 updates ([#1167](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1167)) ([fcca987](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fcca98745121549db537d9ce588e38900c8f0e0d))
+- **deps-dev:** bump vitest from 2.0.4 to 2.0.5 ([#1116](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1116)) ([e454b55](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e454b5538856316f8492463262186a24e02e2925))
+- **deps:** bump the regular group across 1 directory with 12 updates ([#1140](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1140)) ([89e8682](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/89e8682d8e1b3936bd17af7eca0142f9ad695b7f))
+- **deps:** bump the regular group across 1 directory with 4 updates ([58e990c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/58e990c7169a44eaa5ee14029119713ce92f5033))
+- **deps:** bump the regular group with 10 updates ([#1153](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1153)) ([48bd33f](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/48bd33f9432231b9551d65ceb5cd14b937e5cff1))
+- **deps:** bump the regular group with 2 updates ([#1129](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1129)) ([d9f951c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/d9f951c258d12765106548688672b8413716fb16))
+- **deps:** bump the regular group with 2 updates ([#1143](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1143)) ([f883a83](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f883a83f647b54a7b625e19972e94224f768c50b))
+- **deps:** bump the regular group with 2 updates ([#1155](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1155)) ([c02ea07](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/c02ea0790b61c5b29c353ff1297fa5e3fe5538da))
+- **deps:** bump the regular group with 2 updates ([#1165](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1165)) ([e1fb067](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e1fb067c6a2d00106c5bf7ec0707d5374fdca464))
+- **deps:** bump the regular group with 2 updates ([#1189](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1189)) ([d626254](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/d626254db881732a6478258428fd37da26c4cabb))
+- **deps:** bump the regular group with 3 updates ([#1151](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1151)) ([271426f](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/271426fb72220de7969c8200067f51793a5502a7))
+- **deps:** bump the regular group with 3 updates ([#1170](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1170)) ([fb89e15](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fb89e155dbfd8be508fa42a08fc44dad925bd7ad))
+- **deps:** bump the regular group with 4 updates ([#1157](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1157)) ([35fbcd3](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/35fbcd383c244ae746b45c031abac4b6cbadf001))
+- **deps:** bump the regular group with 4 updates ([#1166](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1166)) ([2f2d625](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/2f2d625b102d7211e5311c8367690bd03ce8087a))
+- **deps:** bump the regular group with 4 updates ([#1173](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1173)) ([b07a57e](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b07a57e8de27faf8008b26e94f78978cc1b58ff4))
+- **deps:** bump the regular group with 5 updates ([#1191](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1191)) ([c9a4d44](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/c9a4d44f8a45e92a7b5dd755c0b811c85f5c2f6e))
+- **deps:** bump the regular group with 6 updates ([#1163](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1163)) ([e6ea62c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e6ea62c8b4c1ba8c99c8502a9df24709f46e19cf))
+- **deps:** bump the regular group with 7 updates ([f5d5fe0](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f5d5fe0e8449c8c1ecd560cdaea66757d4cb6168))
+- **deps:** bump the regular group with 7 updates ([#1130](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1130)) ([4f1d887](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/4f1d8877c57dd59ec6b862c5caee613532e0873a))
+- **deps:** bump the regular group with 7 updates ([#1158](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1158)) ([4809da4](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/4809da42ba62306e05652e685aba604bc66ec179))
+- **deps:** bump the regular group with 7 updates ([#1168](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1168)) ([2336b18](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/2336b18a25e03b086d23fd7c99753ac9201eee6e))
+- **deps:** bump the regular group with 9 updates ([#1137](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1137)) ([eede99d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/eede99da5f4df39204a48daf6caf8463c1048be6))
+- **deps:** bump vue from 3.4.36 to 3.4.37 in the regular group ([#1132](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1132)) ([1e755e0](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/1e755e07ca8925d906b4b83a9a430d4d4dc4b31d))
+- **deps:** bump vue from 3.5.1 to 3.5.2 in the regular group ([54e7c79](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/54e7c7947381865de499ddff816d007399942040))
+- **deps:** bump vue from 3.5.10 to 3.5.11 in the regular group ([#1184](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1184)) ([b216885](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/b216885bc638297def6a91f530813a4ab078dc5c))
+- **docker:** fix dashboard auto config paths ([abba1ad](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/abba1ad8aec06b4c1783adc6893c09ce108f08a3))
+- **sonar:** refine sonar-project.properties files ([216a56a](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/216a56a2a3c4548eb9fdb3a67793e653b4f8bbf3))
+
+## [1.5.1](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/webui@v1.5.0...webui@v1.5.1) (2024-07-30)
+
+### 🧹 Chores
+
+- **webui:** Synchronize simulator-ui-ocpp-server versions
+
+## [1.5.0](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/webui@v1.4.2...webui@v1.5.0) (2024-07-25)
+
+### 🤖 Automation
+
+- **deps-dev:** bump @types/node from 20.14.11 to 20.14.12 ([#1106](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1106)) ([fb46a87](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/fb46a877f5c2b880759b9e70a08092510a7cb473))
+- **deps-dev:** bump @vitejs/plugin-vue from 5.0.5 to 5.1.0 ([#1105](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1105)) ([d36c4c8](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/d36c4c840ab5ac7a9c7fe6abbd2ae01844cb981e))
+- **deps-dev:** bump @vitest/coverage-v8 from 2.0.1 to 2.0.2 ([bbdb386](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/bbdb3861ed14ea52669231e5d372add76c50d65e))
+- **deps-dev:** bump rimraf from 5.0.8 to 6.0.0 ([207408c](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/207408cf661a7b8a1d35f8a9aa5ff02104fcd8ba))
+- **deps-dev:** bump typescript-eslint from 7.16.0 to 7.16.1 ([a60a99d](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a60a99dce05328466e9a631ba83a9d527f3b4548))
+- **deps-dev:** bump vitest from 2.0.1 to 2.0.2 ([#1082](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1082)) ([f3d0d30](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f3d0d30346974ec0e979d53d8a761ce254ba8bb0))
+- **deps:** bump vue from 3.4.33 to 3.4.34 ([#1107](https://github.com/SAP/e-mobility-charging-stations-simulator/issues/1107)) ([0bfef14](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/0bfef1423a926bd6054a25934957148d1d2fb4b0))
+
+## [1.4.2](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/webui-v1.4.1...webui@v1.4.2) (2024-07-06)
+
+### 🧹 Chores
+
+- **webui:** Synchronize simulator-ui-ocpp-server versions
+
+## [1.4.1](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ui@v1.4.0...ui@v1.4.1) (2024-07-05)
+
+### 🐞 Fixes
+
+- **ci:** fix release branches creation ([f727f02](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/f727f029cb974cffb38a2c569173730b6b808e3f))
+
+## [1.4.0](https://github.com/SAP/e-mobility-charging-stations-simulator/compare/ui-v1.3.7...ui@v1.4.0) (2024-07-04)
+
+### 🤖 Automation
+
+- bump volta node version ([abc5de8](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/abc5de857ea9e4a27f83d1c2fe60b4618775a540))
+- **deps-dev:** apply updates ([e92bd99](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/e92bd991d1f0c43442dd20d7b5e34fd30f9bb136))
+- **deps-dev:** apply updates ([a33e3b4](https://github.com/SAP/e-mobility-charging-stations-simulator/commit/a33e3b4129757990b84af075cf9b678506937afb))
- [Run](#run)
- [Compiles and run for production](#compiles-and-run-for-production)
- [Preview locally](#preview-locally)
+ - [Docker](#docker)
- [Development](#development)
- [Compiles and run for development](#compiles-and-run-for-development)
- [Formats files](#formats-files)
1. With the buttons on the top you can change UI server, start/stop the simulator, add new charging stations and refresh the content.
2. Each charging station is a row in the table with specific 'Actions' to execute on. Try 'Stop Charging Station' and refresh with the large blue button and see the status 'Started' turns from 'Yes' into 'No'.
+#### Docker
+
+In the [docker](./docker) folder:
+
+```shell
+make
+```
+
### Development
#### Compiles and run for development
--- /dev/null
+FROM node:lts-alpine AS builder
+
+# Build dashboard
+WORKDIR /usr/builder
+COPY . ./
+RUN set -ex \
+ && npm install -g --ignore-scripts corepack \
+ && corepack enable \
+ && corepack prepare pnpm@latest --activate \
+ && pnpm set progress=false \
+ && pnpm config set depth 0 \
+ && pnpm install --ignore-scripts \
+ && cp docker/config.json public/config.json \
+ && pnpm build
+
+FROM node:lts-alpine
+
+WORKDIR /usr/app
+COPY --from=builder /usr/builder ./
+COPY docker/run.sh /run.sh
+COPY docker/autoconfig.sh /autoconfig.sh
+RUN set -ex \
+ && chmod +x /run.sh \
+ && chmod +x /autoconfig.sh
+
+ENTRYPOINT ["/bin/sh", "-c", "/autoconfig.sh && /run.sh"]
--- /dev/null
+PROJECT_NAME?=evse
+NAME:=e-mobility-charging-stations-dashboard
+SUBMODULES_INIT?=false
+DOCKER_ECR_ACCOUNT_ID?=166296450311
+DOCKER_ECR_REGION?=eu-west-3
+DOCKER_ECR_REGISTRY_NAME?=e-mobility-charging-stations-dashboard
+DOCKER_ECR_TAG?=latest
+
+.PHONY: all
+
+default: all
+
+submodule-update:
+ git submodule update --init --recursive
+
+submodules-init=
+ifeq '$(SUBMODULES_INIT)' 'true'
+ submodules-init += submodule-update
+endif
+
+$(NAME): $(submodules-init)
+ docker compose -p $(PROJECT_NAME) up -d
+
+$(NAME)-force: $(submodules-init)
+ docker compose -p $(PROJECT_NAME) up -d --build --force-recreate
+
+all: $(NAME)
+
+clean-images:
+ -docker rmi $(PROJECT_NAME)-$(NAME)
+
+clean-containers:
+ -docker compose -p $(PROJECT_NAME) down
+
+clean: clean-containers clean-images
+
+docker-tag-ecr:
+ docker tag $(PROJECT_NAME)-$(NAME) $(DOCKER_ECR_ACCOUNT_ID).dkr.ecr.$(DOCKER_ECR_REGION).amazonaws.com/$(DOCKER_ECR_REGISTRY_NAME):$(DOCKER_ECR_TAG)
+
+docker-push-ecr: $(NAME)-force docker-tag-ecr
+ aws ecr get-login-password --region $(DOCKER_ECR_REGION) | docker login --username AWS --password-stdin $(DOCKER_ECR_ACCOUNT_ID).dkr.ecr.$(DOCKER_ECR_REGION).amazonaws.com/$(DOCKER_ECR_REGISTRY_NAME)
+ docker push $(DOCKER_ECR_ACCOUNT_ID).dkr.ecr.$(DOCKER_ECR_REGION).amazonaws.com/$(DOCKER_ECR_REGISTRY_NAME):$(DOCKER_ECR_TAG)
+
+dist-clean-images:
+ docker image prune -a -f
+
+dist-clean-volumes:
+ docker volume prune -f
+
+dist-clean: clean-containers dist-clean-volumes dist-clean-images
--- /dev/null
+#!/usr/bin/env sh
+
+if ! [ -z $emobility_server_type ] && ! [ -z $emobility_service_type ]
+then
+ [ -z $emobility_install_dir ] && { echo "emobility installation directory env variable not found, exiting"; exit 1; }
+ [ -z $emobility_landscape ] && { echo "emobility landscape env variable not found, exiting"; exit 1; }
+ [ -z $emobility_server_type ] && { echo "emobility env server type variable not found, exiting"; exit 1; }
+ [ -z $emobility_service_type ] && { echo "emobility env service type variable not found, exiting"; exit 1; }
+
+ cp $emobility_install_dir/src/assets/configs-docker/$emobility_server_type-$emobility_service_type-$emobility_landscape.json $emobility_install_dir/dist/config.json
+else
+ echo "no emobility env defined, start with default configuration"
+fi
--- /dev/null
+{
+ "uiServer": {
+ "host": "localhost",
+ "port": 8080,
+ "protocol": "ui",
+ "version": "0.0.1",
+ "authentication": {
+ "enabled": true,
+ "type": "protocol-basic-auth",
+ "username": "admin",
+ "password": "admin"
+ }
+ }
+}
--- /dev/null
+networks:
+ ev_network:
+ driver: bridge
+services:
+ e-mobility-charging-stations-dashboard:
+ build:
+ context: ..
+ dockerfile: docker/Dockerfile
+ networks:
+ - ev_network
+ ports:
+ - 3030:3030
--- /dev/null
+#!/usr/bin/env sh
+
+node start.js
{
"$schema": "https://json.schemastore.org/package",
"name": "webui",
- "version": "0.3.0",
+ "version": "2.0.10",
"readme": "README.md",
"engines": {
- "node": ">=18.0.0",
+ "node": ">=20.0.0",
"pnpm": ">=9.0.0"
},
"volta": {
- "node": "22.2.0",
- "pnpm": "9.1.2"
+ "node": "22.17.0",
+ "pnpm": "10.12.4"
},
- "packageManager": "pnpm@9.1.2",
+ "packageManager": "pnpm@10.12.4",
"type": "module",
"scripts": {
"build": "vite build",
"dev": "vite",
"clean:dist": "pnpm exec rimraf dist",
"clean:node_modules": "pnpm exec rimraf node_modules",
- "lint": "cross-env TIMING=1 eslint . --cache --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --ignore-path .gitignore",
- "lint:fix": "cross-env TIMING=1 eslint . --cache --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
+ "lint": "cross-env TIMING=1 eslint --cache .",
+ "lint:fix": "cross-env TIMING=1 eslint --cache --fix .",
"format": "prettier --cache --write .",
"test": "vitest",
"coverage": "vitest run --coverage"
},
"dependencies": {
- "finalhandler": "^1.2.0",
- "serve-static": "^1.15.0",
- "vue": "^3.4.27",
- "vue-router": "^4.3.2",
- "vue-toast-notification": "^3.1.2"
+ "finalhandler": "^2.1.0",
+ "serve-static": "^2.2.0",
+ "vue": "^3.5.17",
+ "vue-router": "^4.5.1",
+ "vue-toast-notification": "^3.1.3"
},
"devDependencies": {
- "@rushstack/eslint-patch": "^1.10.3",
- "@tsconfig/node20": "^20.1.4",
- "@types/jsdom": "^21.1.6",
- "@types/node": "^20.12.12",
- "@typescript-eslint/eslint-plugin": "^7.10.0",
- "@typescript-eslint/parser": "^7.10.0",
- "@vitejs/plugin-vue": "^5.0.4",
- "@vitejs/plugin-vue-jsx": "^3.1.0",
- "@vitest/coverage-v8": "^1.6.0",
- "@vue/eslint-config-prettier": "^9.0.0",
- "@vue/eslint-config-typescript": "^13.0.0",
+ "@tsconfig/node22": "^22.0.2",
+ "@types/jsdom": "^21.1.7",
+ "@types/node": "^24.0.10",
+ "@vitejs/plugin-vue": "^6.0.0",
+ "@vitejs/plugin-vue-jsx": "^5.0.1",
+ "@vitest/coverage-v8": "^3.2.4",
"@vue/test-utils": "^2.4.6",
- "@vue/tsconfig": "^0.5.1",
+ "@vue/tsconfig": "^0.7.0",
"cross-env": "^7.0.3",
- "eslint": "^8.57.0",
- "eslint-define-config": "^2.1.0",
- "eslint-import-resolver-typescript": "^3.6.1",
- "eslint-plugin-import": "^2.29.1",
- "eslint-plugin-simple-import-sort": "^12.1.0",
- "eslint-plugin-vue": "^9.26.0",
- "jsdom": "^24.0.0",
- "prettier": "^3.2.5",
- "rimraf": "^5.0.7",
- "typescript": "~5.4.5",
- "vite": "^5.2.11",
- "vitest": "^1.6.0"
- },
- "_id": "webui@0.3.0"
+ "jsdom": "^26.1.0",
+ "prettier": "^3.6.2",
+ "rimraf": "^6.0.1",
+ "typescript": "~5.8.3",
+ "vite": "^7.0.2",
+ "vitest": "^3.2.4"
+ }
}
# This is the name and version displayed in the SonarCloud UI.
sonar.projectName=e-mobility-charging-stations-simulator-webui
-sonar.projectVersion=0.3.0
+# x-release-please-start-version
+sonar.projectVersion=2.0.10
+# x-release-please-end
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
sonar.sources=src
sonar.tests=tests
-sonar.javascript.lcov.reportPaths=coverage/lcov.info
+sonar.typescript.lcov.reportPaths=coverage/lcov.info
# Encoding of the source code. Default is default system encoding
#sonar.sourceEncoding=UTF-8
<template>
<div class="container">
- <slot></slot>
+ <slot />
</div>
</template>
<template>
- <h1 id="action">Add Charging Stations</h1>
+ <h1 id="action">
+ Add Charging Stations
+ </h1>
<p>Template:</p>
- <select :key="state.renderTemplates" v-model="state.template">
- <option disabled value="">Please select a template</option>
+ <select
+ :key="state.renderTemplates"
+ v-model="state.template"
+ >
+ <option
+ disabled
+ value=""
+ >
+ Please select a template
+ </option>
<option
- v-for="template in $templates.value"
- v-show="Array.isArray($templates.value) && $templates.value.length > 0"
+ v-for="template in $templates!.value"
+ v-show="Array.isArray($templates?.value) && $templates.value.length > 0"
:key="template"
>
{{ template }}
<input
id="number-of-stations"
v-model="state.numberOfStations"
- type="number"
min="1"
name="number-of-stations"
placeholder="number of stations"
- />
+ type="number"
+ >
<p>Template options overrides:</p>
<ul id="template-options">
<li>
<input
id="supervision-url"
v-model.trim="state.supervisionUrl"
- type="url"
name="supervision-url"
placeholder="wss://"
- />
+ type="url"
+ >
</li>
<li>
Auto start:
- <input v-model="state.autoStart" type="checkbox" true-value="true" false-value="false" />
+ <input
+ v-model="state.autoStart"
+ false-value="false"
+ true-value="true"
+ type="checkbox"
+ >
</li>
<li>
Persistent configuration:
<input
v-model="state.persistentConfiguration"
- type="checkbox"
- true-value="true"
false-value="false"
- />
+ true-value="true"
+ type="checkbox"
+ >
</li>
<li>
OCPP strict compliance:
<input
v-model="state.ocppStrictCompliance"
- type="checkbox"
- true-value="true"
false-value="false"
- />
+ true-value="true"
+ type="checkbox"
+ >
</li>
<li>
Performance statistics:
<input
v-model="state.enableStatistics"
- type="checkbox"
- true-value="true"
false-value="false"
- />
+ true-value="true"
+ type="checkbox"
+ >
</li>
</ul>
- <br />
+ <br>
<Button
id="action-button"
@click="
() => {
$uiClient
- .addChargingStations(state.template, state.numberOfStations, {
+ ?.addChargingStations(state.template, state.numberOfStations, {
supervisionUrls: state.supervisionUrl.length > 0 ? state.supervisionUrl : undefined,
autoStart: convertToBoolean(state.autoStart),
persistentConfiguration: convertToBoolean(state.persistentConfiguration),
ocppStrictCompliance: convertToBoolean(state.ocppStrictCompliance),
- enableStatistics: convertToBoolean(state.enableStatistics)
+ enableStatistics: convertToBoolean(state.enableStatistics),
})
.then(() => {
$toast.success('Charging stations successfully added')
import { convertToBoolean, randomUUID } from '@/composables'
const state = ref<{
- renderTemplates: `${string}-${string}-${string}-${string}-${string}`
- template: string
- numberOfStations: number
- supervisionUrl: string
autoStart: boolean
- persistentConfiguration: boolean
- ocppStrictCompliance: boolean
enableStatistics: boolean
+ numberOfStations: number
+ ocppStrictCompliance: boolean
+ persistentConfiguration: boolean
+ renderTemplates: `${string}-${string}-${string}-${string}-${string}`
+ supervisionUrl: string
+ template: string
}>({
- renderTemplates: randomUUID(),
- template: '',
- numberOfStations: 1,
- supervisionUrl: '',
autoStart: false,
- persistentConfiguration: true,
+ enableStatistics: false,
+ numberOfStations: 1,
ocppStrictCompliance: true,
- enableStatistics: false
+ persistentConfiguration: true,
+ renderTemplates: randomUUID(),
+ supervisionUrl: '',
+ template: '',
})
-watch(getCurrentInstance()!.appContext.config.globalProperties.$templates, () => {
+watch(getCurrentInstance()!.appContext.config.globalProperties!.$templates, () => {
state.value.renderTemplates = randomUUID()
})
</script>
<template>
- <h1 id="action">Set Supervision Url</h1>
+ <h1 id="action">
+ Set Supervision Url
+ </h1>
<h2>{{ chargingStationId }}</h2>
<p>Supervision Url:</p>
<input
id="supervision-url"
v-model.trim="state.supervisionUrl"
- type="url"
name="supervision-url"
placeholder="wss://"
- />
- <br />
+ type="url"
+ >
+ <br>
<Button
id="action-button"
@click="
() => {
$uiClient
- .setSupervisionUrl(hashId, state.supervisionUrl)
+ ?.setSupervisionUrl(hashId, state.supervisionUrl)
.then(() => {
$toast.success('Supervision url successfully set')
})
import Button from '@/components/buttons/Button.vue'
defineProps<{
- hashId: string
chargingStationId: string
+ hashId: string
}>()
const state = ref<{ supervisionUrl: string }>({
- supervisionUrl: ''
+ supervisionUrl: '',
})
</script>
<template>
- <h1 id="action">Start Transaction</h1>
+ <h1 id="action">
+ Start Transaction
+ </h1>
<h2>{{ chargingStationId }}</h2>
<h3>Connector {{ connectorId }}</h3>
<p>Scan RFID tag:</p>
- <input id="idtag" v-model.trim="state.idTag" type="text" name="idtag" placeholder="RFID tag" />
- <br />
+ <input
+ id="idtag"
+ v-model.trim="state.idTag"
+ name="idtag"
+ placeholder="RFID tag"
+ type="text"
+ >
+ <br>
<Button
id="action-button"
@click="
() => {
$uiClient
- .startTransaction(hashId, convertToInt(connectorId), state.idTag)
+ ?.startTransaction(hashId, convertToInt(connectorId), state.idTag)
.then(() => {
$toast.success('Transaction successfully started')
})
import { convertToInt } from '@/composables'
defineProps<{
- hashId: string
chargingStationId: string
connectorId: string
+ hashId: string
}>()
const state = ref<{ idTag: string }>({
- idTag: ''
+ idTag: '',
})
</script>
<template>
- <button type="button" class="button">
- <slot></slot>
+ <button
+ class="button"
+ type="button"
+ >
+ <slot />
</button>
</template>
<template>
- <Button :class="{ on: state.status }" @click="click()">
- <slot></slot>
+ <Button
+ :class="{ on: state.status }"
+ @click="click()"
+ >
+ <slot />
</Button>
</template>
const props = defineProps<{
id: string
- status?: boolean
- shared?: boolean
- on?: () => void
off?: () => void
+ on?: () => void
+ shared?: boolean
+ status?: boolean
}>()
const $emit = defineEmits(['clicked'])
const id = props.shared === true ? `shared-toggle-button-${props.id}` : `toggle-button-${props.id}`
const state = ref<{ status: boolean }>({
- status: getFromLocalStorage<boolean>(id, props.status ?? false)
+ status: getFromLocalStorage<boolean>(id, props.status ?? false),
})
const click = (): void => {
<template>
<tr class="connectors-table__row">
- <td class="connectors-table__column">{{ connectorId }}</td>
- <td class="connectors-table__column">{{ connector.status ?? 'Ø' }}</td>
<td class="connectors-table__column">
- {{ connector.transactionStarted === true ? 'Yes' : 'No' }}
+ {{ connectorId }}
+ </td>
+ <td class="connectors-table__column">
+ {{ connector.status ?? 'Ø' }}
+ </td>
+ <td class="connectors-table__column">
+ {{ connector.transactionStarted === true ? `Yes (${connector.transactionId})` : 'No' }}
</td>
<td class="connectors-table__column">
{{ atgStatus?.start === true ? 'Yes' : 'No' }}
<td class="connectors-table__column">
<ToggleButton
:id="`${hashId}-${connectorId}-start-transaction`"
- :shared="true"
- :on="
- () => {
- $router.push({
- name: 'start-transaction',
- params: { hashId, chargingStationId, connectorId }
- })
- }
- "
:off="
() => {
$router.push({ name: 'charging-stations' })
}
"
- @clicked="
+ :on="
() => {
- $emit('need-refresh')
+ $router.push({
+ name: 'start-transaction',
+ params: { hashId, chargingStationId, connectorId },
+ })
}
"
+ :shared="true"
+ @clicked="$emit('need-refresh')"
>
Start Transaction
</ToggleButton>
- <Button @click="stopTransaction()">Stop Transaction</Button>
- <Button @click="startAutomaticTransactionGenerator()">Start ATG</Button>
- <Button @click="stopAutomaticTransactionGenerator()">Stop ATG</Button>
+ <Button @click="stopTransaction()">
+ Stop Transaction
+ </Button>
+ <Button @click="startAutomaticTransactionGenerator()">
+ Start ATG
+ </Button>
+ <Button @click="stopAutomaticTransactionGenerator()">
+ Stop ATG
+ </Button>
</td>
</tr>
</template>
<script setup lang="ts">
import { useToast } from 'vue-toast-notification'
+import type { ConnectorStatus, Status } from '@/types'
+
import Button from '@/components/buttons/Button.vue'
import ToggleButton from '@/components/buttons/ToggleButton.vue'
import { useUIClient } from '@/composables'
-import type { ConnectorStatus, Status } from '@/types'
const props = defineProps<{
- hashId: string
+ atgStatus?: Status
chargingStationId: string
- connectorId: number
connector: ConnectorStatus
- atgStatus?: Status
+ connectorId: number
+ hashId: string
}>()
const $emit = defineEmits(['need-refresh'])
uiClient
.stopTransaction(props.hashId, props.connector.transactionId)
.then(() => {
- $toast.success('Transaction successfully stopped')
+ return $toast.success('Transaction successfully stopped')
})
.catch((error: Error) => {
$toast.error('Error at stopping transaction')
uiClient
.startAutomaticTransactionGenerator(props.hashId, props.connectorId)
.then(() => {
- $toast.success('Automatic transaction generator successfully started')
+ return $toast.success('Automatic transaction generator successfully started')
})
.catch((error: Error) => {
$toast.error('Error at starting automatic transaction generator')
uiClient
.stopAutomaticTransactionGenerator(props.hashId, props.connectorId)
.then(() => {
- $toast.success('Automatic transaction generator successfully stopped')
+ return $toast.success('Automatic transaction generator successfully stopped')
})
.catch((error: Error) => {
$toast.error('Error at stopping automatic transaction generator')
<td class="cs-table__column">
{{ chargingStation.stationInfo.chargingStationId }}
</td>
- <td class="cs-table__column">{{ chargingStation.started === true ? 'Yes' : 'No' }}</td>
+ <td class="cs-table__column">
+ {{ chargingStation.started === true ? 'Yes' : 'No' }}
+ </td>
<td class="cs-table__column">
{{ getSupervisionUrl() }}
</td>
- <td class="cs-table__column">{{ getWSState() }}</td>
+ <td class="cs-table__column">
+ {{ getWSState() }}
+ </td>
<td class="cs-table__column">
{{ chargingStation.bootNotificationResponse?.status ?? 'Ø' }}
</td>
<td class="cs-table__column">
{{ chargingStation.stationInfo.templateName }}
</td>
- <td class="cs-table__column">{{ chargingStation.stationInfo.chargePointVendor }}</td>
- <td class="cs-table__column">{{ chargingStation.stationInfo.chargePointModel }}</td>
+ <td class="cs-table__column">
+ {{ chargingStation.stationInfo.chargePointVendor }}
+ </td>
+ <td class="cs-table__column">
+ {{ chargingStation.stationInfo.chargePointModel }}
+ </td>
<td class="cs-table__column">
{{ chargingStation.stationInfo.firmwareVersion ?? 'Ø' }}
</td>
<td class="cs-table__column">
- <Button @click="startChargingStation()">Start Charging Station</Button>
- <Button @click="stopChargingStation()">Stop Charging Station</Button>
+ <Button @click="startChargingStation()">
+ Start Charging Station
+ </Button>
+ <Button @click="stopChargingStation()">
+ Stop Charging Station
+ </Button>
<ToggleButton
:id="`${chargingStation.stationInfo.hashId}-set-supervision-url`"
- :shared="true"
+ :off="
+ () => {
+ $router.push({ name: 'charging-stations' })
+ }
+ "
:on="
() => {
$router.push({
name: 'set-supervision-url',
params: {
hashId: chargingStation.stationInfo.hashId,
- chargingStationId: chargingStation.stationInfo.chargingStationId
- }
+ chargingStationId: chargingStation.stationInfo.chargingStationId,
+ },
})
}
"
- :off="
- () => {
- $router.push({ name: 'charging-stations' })
- }
- "
- @clicked="
- () => {
- $emit('need-refresh')
- }
- "
+ :shared="true"
+ @clicked="$emit('need-refresh')"
>
Set Supervision Url
</ToggleButton>
- <Button @click="openConnection()">Open Connection</Button>
- <Button @click="closeConnection()">Close Connection</Button>
- <Button @click="deleteChargingStation()">Delete Charging Station</Button>
+ <Button @click="openConnection()">
+ Open Connection
+ </Button>
+ <Button @click="closeConnection()">
+ Close Connection
+ </Button>
+ <Button @click="deleteChargingStation()">
+ Delete Charging Station
+ </Button>
</td>
<td class="cs-table__connectors-column">
<table id="connectors-table">
- <caption></caption>
+ <caption />
<thead id="connectors-table__head">
<tr class="connectors-table__row">
- <th scope="col" class="connectors-table__column">Identifier</th>
- <th scope="col" class="connectors-table__column">Status</th>
- <th scope="col" class="connectors-table__column">Transaction</th>
- <th scope="col" class="connectors-table__column">ATG Started</th>
- <th scope="col" class="connectors-table__column">Actions</th>
+ <th
+ class="connectors-table__column"
+ scope="col"
+ >
+ Identifier
+ </th>
+ <th
+ class="connectors-table__column"
+ scope="col"
+ >
+ Status
+ </th>
+ <th
+ class="connectors-table__column"
+ scope="col"
+ >
+ Transaction
+ </th>
+ <th
+ class="connectors-table__column"
+ scope="col"
+ >
+ ATG Started
+ </th>
+ <th
+ class="connectors-table__column"
+ scope="col"
+ >
+ Actions
+ </th>
</tr>
</thead>
<tbody id="connectors-table__body">
<CSConnector
v-for="(connector, index) in getConnectorStatuses()"
:key="index + 1"
- :hash-id="chargingStation.stationInfo.hashId"
+ :atg-status="getATGStatus(index + 1)"
:charging-station-id="chargingStation.stationInfo.chargingStationId"
- :connector-id="index + 1"
:connector="connector"
- :atg-status="getATGStatus(index + 1)"
+ :connector-id="index + 1"
+ :hash-id="chargingStation.stationInfo.hashId"
@need-refresh="$emit('need-refresh')"
/>
</tbody>
<script setup lang="ts">
import { useToast } from 'vue-toast-notification'
+import type { ChargingStationData, ConnectorStatus, Status } from '@/types'
+
import Button from '@/components/buttons/Button.vue'
import ToggleButton from '@/components/buttons/ToggleButton.vue'
import CSConnector from '@/components/charging-stations/CSConnector.vue'
-import { useUIClient } from '@/composables'
-import type { ChargingStationData, ConnectorStatus, Status } from '@/types'
+import { deleteFromLocalStorage, getLocalStorage, useUIClient } from '@/composables'
const props = defineProps<{
chargingStation: ChargingStationData
}
const getWSState = (): string => {
switch (props.chargingStation?.wsState) {
+ case WebSocket.CLOSED:
+ return 'Closed'
+ case WebSocket.CLOSING:
+ return 'Closing'
case WebSocket.CONNECTING:
return 'Connecting'
case WebSocket.OPEN:
return 'Open'
- case WebSocket.CLOSING:
- return 'Closing'
- case WebSocket.CLOSED:
- return 'Closed'
default:
return 'Ø'
}
uiClient
.startChargingStation(props.chargingStation.stationInfo.hashId)
.then(() => {
- $toast.success('Charging station successfully started')
+ return $toast.success('Charging station successfully started')
})
.catch((error: Error) => {
$toast.error('Error at starting charging station')
uiClient
.stopChargingStation(props.chargingStation.stationInfo.hashId)
.then(() => {
- $toast.success('Charging station successfully stopped')
+ return $toast.success('Charging station successfully stopped')
})
.catch((error: Error) => {
$toast.error('Error at stopping charging station')
uiClient
.openConnection(props.chargingStation.stationInfo.hashId)
.then(() => {
- $toast.success('Connection successfully opened')
+ return $toast.success('Connection successfully opened')
})
.catch((error: Error) => {
$toast.error('Error at opening connection')
uiClient
.closeConnection(props.chargingStation.stationInfo.hashId)
.then(() => {
- $toast.success('Connection successfully closed')
+ return $toast.success('Connection successfully closed')
})
.catch((error: Error) => {
$toast.error('Error at closing connection')
uiClient
.deleteChargingStation(props.chargingStation.stationInfo.hashId)
.then(() => {
- $toast.success('Charging station successfully deleted')
+ for (const key in getLocalStorage()) {
+ if (key.includes(props.chargingStation.stationInfo.hashId)) {
+ deleteFromLocalStorage(key)
+ }
+ }
+ return $toast.success('Charging station successfully deleted')
})
.catch((error: Error) => {
$toast.error('Error at deleting charging station')
</caption>
<thead id="cs-table__head">
<tr class="cs-table__row">
- <th scope="col" class="cs-table__column">Name</th>
- <th scope="col" class="cs-table__column">Started</th>
- <th scope="col" class="cs-table__column">Supervision Url</th>
- <th scope="col" class="cs-table__column">WebSocket State</th>
- <th scope="col" class="cs-table__column">Registration Status</th>
- <th scope="col" class="cs-table__column">Template</th>
- <th scope="col" class="cs-table__column">Vendor</th>
- <th scope="col" class="cs-table__column">Model</th>
- <th scope="col" class="cs-table__column">Firmware</th>
- <th scope="col" class="cs-table__column">Actions</th>
- <th scope="col" class="cs-table__connectors-column">Connector(s)</th>
+ <th
+ class="cs-table__column"
+ scope="col"
+ >
+ Name
+ </th>
+ <th
+ class="cs-table__column"
+ scope="col"
+ >
+ Started
+ </th>
+ <th
+ class="cs-table__column"
+ scope="col"
+ >
+ Supervision Url
+ </th>
+ <th
+ class="cs-table__column"
+ scope="col"
+ >
+ WebSocket State
+ </th>
+ <th
+ class="cs-table__column"
+ scope="col"
+ >
+ Registration Status
+ </th>
+ <th
+ class="cs-table__column"
+ scope="col"
+ >
+ Template
+ </th>
+ <th
+ class="cs-table__column"
+ scope="col"
+ >
+ Vendor
+ </th>
+ <th
+ class="cs-table__column"
+ scope="col"
+ >
+ Model
+ </th>
+ <th
+ class="cs-table__column"
+ scope="col"
+ >
+ Firmware
+ </th>
+ <th
+ class="cs-table__column"
+ scope="col"
+ >
+ Actions
+ </th>
+ <th
+ class="cs-table__connectors-column"
+ scope="col"
+ >
+ Connector(s)
+ </th>
</tr>
</thead>
<tbody id="cs-table__body">
</template>
<script setup lang="ts">
-import CSData from '@/components/charging-stations/CSData.vue'
import type { ChargingStationData } from '@/types'
+import CSData from '@/components/charging-stations/CSData.vue'
+
defineProps<{
chargingStations: ChargingStationData[]
}>()
type RequestPayload,
type ResponsePayload,
ResponseStatus,
- type UIServerConfigurationSection
+ type UIServerConfigurationSection,
} from '@/types'
import { randomUUID, validateUUID } from './Utils'
-type ResponseHandler = {
+interface ResponseHandler {
procedureName: ProcedureName
- resolve: (value: ResponsePayload | PromiseLike<ResponsePayload>) => void
reject: (reason?: unknown) => void
+ resolve: (value: PromiseLike<ResponsePayload> | ResponsePayload) => void
}
export class UIClient {
- private static instance: UIClient | null = null
-
- private ws?: WebSocket
+ private static instance: null | UIClient = null
private responseHandlers: Map<
`${string}-${string}-${string}-${string}-${string}`,
ResponseHandler
>
- private constructor(private uiServerConfiguration: UIServerConfigurationSection) {
+ private ws?: WebSocket
+
+ private constructor (private uiServerConfiguration: UIServerConfigurationSection) {
this.openWS()
this.responseHandlers = new Map<
`${string}-${string}-${string}-${string}-${string}`,
>()
}
- public static getInstance(uiServerConfiguration?: UIServerConfigurationSection): UIClient {
+ public static getInstance (uiServerConfiguration?: UIServerConfigurationSection): UIClient {
if (UIClient.instance === null) {
if (uiServerConfiguration == null) {
throw new Error('Cannot initialize UIClient if no configuration is provided')
return UIClient.instance
}
- public setConfiguration(uiServerConfiguration: UIServerConfigurationSection): void {
- if (this.ws?.readyState === WebSocket.OPEN) {
- this.ws.close()
- delete this.ws
- }
- this.uiServerConfiguration = uiServerConfiguration
- this.openWS()
- }
-
- public registerWSEventListener<K extends keyof WebSocketEventMap>(
- event: K,
- listener: (event: WebSocketEventMap[K]) => void,
- options?: boolean | AddEventListenerOptions
- ) {
- this.ws?.addEventListener(event, listener, options)
- }
-
- public unregisterWSEventListener<K extends keyof WebSocketEventMap>(
- event: K,
- listener: (event: WebSocketEventMap[K]) => void,
- options?: boolean | AddEventListenerOptions
- ) {
- this.ws?.removeEventListener(event, listener, options)
+ public async addChargingStations (
+ template: string,
+ numberOfStations: number,
+ options?: ChargingStationOptions
+ ): Promise<ResponsePayload> {
+ return this.sendRequest(ProcedureName.ADD_CHARGING_STATIONS, {
+ numberOfStations,
+ options,
+ template,
+ })
}
- public async simulatorState(): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.SIMULATOR_STATE, {})
+ public async closeConnection (hashId: string): Promise<ResponsePayload> {
+ return this.sendRequest(ProcedureName.CLOSE_CONNECTION, {
+ hashIds: [hashId],
+ })
}
- public async startSimulator(): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.START_SIMULATOR, {})
+ public async deleteChargingStation (hashId: string): Promise<ResponsePayload> {
+ return this.sendRequest(ProcedureName.DELETE_CHARGING_STATIONS, {
+ hashIds: [hashId],
+ })
}
- public async stopSimulator(): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.STOP_SIMULATOR, {})
+ public async listChargingStations (): Promise<ResponsePayload> {
+ return this.sendRequest(ProcedureName.LIST_CHARGING_STATIONS, {})
}
- public async listTemplates(): Promise<ResponsePayload> {
+ public async listTemplates (): Promise<ResponsePayload> {
return this.sendRequest(ProcedureName.LIST_TEMPLATES, {})
}
- public async listChargingStations(): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.LIST_CHARGING_STATIONS, {})
+ public async openConnection (hashId: string): Promise<ResponsePayload> {
+ return this.sendRequest(ProcedureName.OPEN_CONNECTION, {
+ hashIds: [hashId],
+ })
}
- public async addChargingStations(
- template: string,
- numberOfStations: number,
- options?: ChargingStationOptions
- ): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.ADD_CHARGING_STATIONS, {
- template,
- numberOfStations,
- options
- })
+ public registerWSEventListener<K extends keyof WebSocketEventMap>(
+ event: K,
+ listener: (event: WebSocketEventMap[K]) => void,
+ options?: AddEventListenerOptions | boolean
+ ) {
+ this.ws?.addEventListener(event, listener, options)
}
- public async deleteChargingStation(hashId: string): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.DELETE_CHARGING_STATIONS, { hashIds: [hashId] })
+ public setConfiguration (uiServerConfiguration: UIServerConfigurationSection): void {
+ if (this.ws?.readyState === WebSocket.OPEN) {
+ this.ws.close()
+ delete this.ws
+ }
+ this.uiServerConfiguration = uiServerConfiguration
+ this.openWS()
}
- public async setSupervisionUrl(hashId: string, supervisionUrl: string): Promise<ResponsePayload> {
+ public async setSupervisionUrl (hashId: string, supervisionUrl: string): Promise<ResponsePayload> {
return this.sendRequest(ProcedureName.SET_SUPERVISION_URL, {
hashIds: [hashId],
- url: supervisionUrl
+ url: supervisionUrl,
})
}
- public async startChargingStation(hashId: string): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.START_CHARGING_STATION, { hashIds: [hashId] })
+ public async simulatorState (): Promise<ResponsePayload> {
+ return this.sendRequest(ProcedureName.SIMULATOR_STATE, {})
}
- public async stopChargingStation(hashId: string): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.STOP_CHARGING_STATION, { hashIds: [hashId] })
+ public async startAutomaticTransactionGenerator (
+ hashId: string,
+ connectorId: number
+ ): Promise<ResponsePayload> {
+ return this.sendRequest(ProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR, {
+ connectorIds: [connectorId],
+ hashIds: [hashId],
+ })
}
- public async openConnection(hashId: string): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.OPEN_CONNECTION, {
- hashIds: [hashId]
+ public async startChargingStation (hashId: string): Promise<ResponsePayload> {
+ return this.sendRequest(ProcedureName.START_CHARGING_STATION, {
+ hashIds: [hashId],
})
}
- public async closeConnection(hashId: string): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.CLOSE_CONNECTION, {
- hashIds: [hashId]
- })
+ public async startSimulator (): Promise<ResponsePayload> {
+ return this.sendRequest(ProcedureName.START_SIMULATOR, {})
}
- public async startTransaction(
+ public async startTransaction (
hashId: string,
connectorId: number,
idTag: string | undefined
): Promise<ResponsePayload> {
return this.sendRequest(ProcedureName.START_TRANSACTION, {
- hashIds: [hashId],
connectorId,
- idTag
+ hashIds: [hashId],
+ idTag,
})
}
- public async stopTransaction(
+ public async stopAutomaticTransactionGenerator (
hashId: string,
- transactionId: number | undefined
+ connectorId: number
): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.STOP_TRANSACTION, {
+ return this.sendRequest(ProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR, {
+ connectorIds: [connectorId],
hashIds: [hashId],
- transactionId
})
}
- public async startAutomaticTransactionGenerator(
- hashId: string,
- connectorId: number
- ): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR, {
+ public async stopChargingStation (hashId: string): Promise<ResponsePayload> {
+ return this.sendRequest(ProcedureName.STOP_CHARGING_STATION, {
hashIds: [hashId],
- connectorIds: [connectorId]
})
}
- public async stopAutomaticTransactionGenerator(
+ public async stopSimulator (): Promise<ResponsePayload> {
+ return this.sendRequest(ProcedureName.STOP_SIMULATOR, {})
+ }
+
+ public async stopTransaction (
hashId: string,
- connectorId: number
+ transactionId: number | undefined
): Promise<ResponsePayload> {
- return this.sendRequest(ProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR, {
+ return this.sendRequest(ProcedureName.STOP_TRANSACTION, {
hashIds: [hashId],
- connectorIds: [connectorId]
+ transactionId,
})
}
- private openWS(): void {
+ public unregisterWSEventListener<K extends keyof WebSocketEventMap>(
+ event: K,
+ listener: (event: WebSocketEventMap[K]) => void,
+ options?: AddEventListenerOptions | boolean
+ ) {
+ this.ws?.removeEventListener(event, listener, options)
+ }
+
+ private openWS (): void {
const protocols =
this.uiServerConfiguration.authentication?.enabled === true &&
- this.uiServerConfiguration.authentication?.type === AuthenticationType.PROTOCOL_BASIC_AUTH
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ this.uiServerConfiguration.authentication.type === AuthenticationType.PROTOCOL_BASIC_AUTH
? [
`${this.uiServerConfiguration.protocol}${this.uiServerConfiguration.version}`,
- `authorization.basic.${btoa(`${this.uiServerConfiguration.authentication.username}:${this.uiServerConfiguration.authentication.password}`).replace(/={1,2}$/, '')}`
+ `authorization.basic.${btoa(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `${this.uiServerConfiguration.authentication.username}:${this.uiServerConfiguration.authentication.password}`
+ ).replace(/={1,2}$/, '')}`,
]
: `${this.uiServerConfiguration.protocol}${this.uiServerConfiguration.version}`
this.ws = new WebSocket(
- `${this.uiServerConfiguration.secure === true ? ApplicationProtocol.WSS : ApplicationProtocol.WS}://${this.uiServerConfiguration.host}:${this.uiServerConfiguration.port}`,
+ `${
+ this.uiServerConfiguration.secure === true
+ ? ApplicationProtocol.WSS
+ : ApplicationProtocol.WS
+ }://${this.uiServerConfiguration.host}:${this.uiServerConfiguration.port.toString()}`,
protocols
)
this.ws.onopen = () => {
useToast().success(
- `WebSocket to UI server '${this.uiServerConfiguration.host}' successfully opened`
+ `WebSocket to UI server '${this.uiServerConfiguration.host}:${this.uiServerConfiguration.port.toString()}' successfully opened`
)
}
this.ws.onmessage = this.responseHandler.bind(this)
this.ws.onerror = errorEvent => {
- useToast().error(`Error in WebSocket to UI server '${this.uiServerConfiguration.host}'`)
+ useToast().error(
+ `Error in WebSocket to UI server '${this.uiServerConfiguration.host}:${this.uiServerConfiguration.port.toString()}'`
+ )
console.error(
- `Error in WebSocket to UI server '${this.uiServerConfiguration.host}'`,
+ `Error in WebSocket to UI server '${this.uiServerConfiguration.host}:${this.uiServerConfiguration.port.toString()}'`,
errorEvent
)
}
this.ws.onclose = () => {
- useToast().info(`WebSocket to UI server closed`)
+ useToast().info('WebSocket to UI server closed')
}
}
- private async sendRequest(
- procedureName: ProcedureName,
- payload: RequestPayload
- ): Promise<ResponsePayload> {
- return new Promise<ResponsePayload>((resolve, reject) => {
- if (this.ws?.readyState === WebSocket.OPEN) {
- const uuid = randomUUID()
- const msg = JSON.stringify([uuid, procedureName, payload])
- const sendTimeout = setTimeout(() => {
- this.responseHandlers.delete(uuid)
- return reject(new Error(`Send request '${procedureName}' message: connection timeout`))
- }, 60000)
- try {
- this.ws.send(msg)
- this.responseHandlers.set(uuid, { procedureName, resolve, reject })
- } catch (error) {
- this.responseHandlers.delete(uuid)
- reject(error)
- } finally {
- clearTimeout(sendTimeout)
- }
- } else {
- reject(new Error(`Send request '${procedureName}' message: connection closed`))
- }
- })
- }
-
- private responseHandler(messageEvent: MessageEvent<string>): void {
+ private responseHandler (messageEvent: MessageEvent<string>): void {
let response: ProtocolResponse
try {
- response = JSON.parse(messageEvent.data)
+ response = JSON.parse(messageEvent.data) as ProtocolResponse
} catch (error) {
useToast().error('Invalid response JSON format')
console.error('Invalid response JSON format', error)
}
if (this.responseHandlers.has(uuid)) {
- const { procedureName, resolve, reject } = this.responseHandlers.get(uuid)!
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const { procedureName, reject, resolve } = this.responseHandlers.get(uuid)!
switch (responsePayload.status) {
- case ResponseStatus.SUCCESS:
- resolve(responsePayload)
- break
case ResponseStatus.FAILURE:
reject(responsePayload)
break
+ case ResponseStatus.SUCCESS:
+ resolve(responsePayload)
+ break
default:
reject(
new Error(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`Response status for procedure '${procedureName}' not supported: '${responsePayload.status}'`
)
)
throw new Error(`Not a response to a request: ${JSON.stringify(response, undefined, 2)}`)
}
}
+
+ private async sendRequest (
+ procedureName: ProcedureName,
+ payload: RequestPayload
+ ): Promise<ResponsePayload> {
+ return new Promise<ResponsePayload>((resolve, reject) => {
+ if (this.ws?.readyState === WebSocket.OPEN) {
+ const uuid = randomUUID()
+ const msg = JSON.stringify([uuid, procedureName, payload])
+ const sendTimeout = setTimeout(() => {
+ this.responseHandlers.delete(uuid)
+ reject(new Error(`Send request '${procedureName}' message: connection timeout`))
+ }, 60000)
+ try {
+ this.ws.send(msg)
+ this.responseHandlers.set(uuid, { procedureName, reject, resolve })
+ } catch (error) {
+ this.responseHandlers.delete(uuid)
+ reject(
+ new Error(
+ `Send request '${procedureName}' message: error ${(error as Error).toString()}`
+ )
+ )
+ } finally {
+ clearTimeout(sendTimeout)
+ }
+ } else {
+ reject(new Error(`Send request '${procedureName}' message: connection closed`))
+ }
+ })
+ }
}
}
let changedValue: number = value as number
if (typeof value === 'string') {
- changedValue = parseInt(value)
+ changedValue = Number.parseInt(value)
}
- if (isNaN(changedValue)) {
- throw new Error(`Cannot convert to integer: '${String(value)}'`)
+ if (Number.isNaN(changedValue)) {
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
+ throw new Error(`Cannot convert to integer: '${value.toString()}'`)
}
return changedValue
}
return item != null ? (JSON.parse(item) as T) : defaultValue
}
+// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
export const setToLocalStorage = <T>(key: string, value: T): void => {
localStorage.setItem(key, JSON.stringify(value))
}
getLocalStorage,
randomUUID,
setToLocalStorage,
- useUIClient
+ useUIClient,
} from './Utils'
-import 'vue-toast-notification/dist/theme-bootstrap.css'
-
-import { type App as AppType, createApp, ref } from 'vue'
+import { type App as AppType, type Component, createApp, ref } from 'vue'
import ToastPlugin from 'vue-toast-notification'
+import type { ChargingStationData, ConfigurationData, UIServerConfigurationSection } from '@/types'
+
import App from '@/App.vue'
import { getFromLocalStorage, setToLocalStorage, UIClient } from '@/composables'
import { router } from '@/router'
-import type { ChargingStationData, ConfigurationData, UIServerConfigurationSection } from '@/types'
-const app = createApp(App)
+import 'vue-toast-notification/dist/theme-bootstrap.css'
+
+const app = createApp(App as Component)
const initializeApp = (app: AppType, config: ConfigurationData) => {
app.config.errorHandler = (error, instance, info) => {
if (!Array.isArray(config.uiServer)) {
config.uiServer = [config.uiServer]
}
- if (app.config.globalProperties.$configuration == null) {
- app.config.globalProperties.$configuration = ref<ConfigurationData>(config)
- }
+ app.config.globalProperties.$configuration ??= ref<ConfigurationData>(config)
if (!Array.isArray(app.config.globalProperties.$templates?.value)) {
app.config.globalProperties.$templates = ref<string[]>([])
}
) {
setToLocalStorage<number>('uiServerConfigurationIndex', 0)
}
- if (app.config.globalProperties.$uiClient == null) {
- app.config.globalProperties.$uiClient = UIClient.getInstance(
- (app.config.globalProperties.$configuration.value.uiServer as UIServerConfigurationSection[])[
- getFromLocalStorage<number>('uiServerConfigurationIndex', 0)
- ]
- )
- }
+ app.config.globalProperties.$uiClient ??= UIClient.getInstance(
+ (app.config.globalProperties.$configuration.value.uiServer as UIServerConfigurationSection[])[
+ getFromLocalStorage<number>('uiServerConfigurationIndex', 0)
+ ]
+ )
app.use(router).use(ToastPlugin).mount('#app')
}
if (!response.ok) {
// TODO: add code for UI notifications or other error handling logic
console.error('Failed to fetch app configuration')
- return
+ return undefined
}
response
.json()
+ // eslint-disable-next-line promise/no-nesting
.then(config => {
- initializeApp(app, config)
+ initializeApp(app, config as ConfigurationData)
+ return undefined
})
- .catch(error => {
+ // eslint-disable-next-line promise/no-nesting
+ .catch((error: unknown) => {
// TODO: add code for UI notifications or other error handling logic
console.error('Error at deserializing JSON app configuration:', error)
})
+ return undefined
})
- .catch(error => {
+ .catch((error: unknown) => {
// TODO: add code for UI notifications or other error handling logic
console.error('Error at fetching app configuration:', error)
})
+/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { createRouter, createWebHistory } from 'vue-router'
import AddChargingStations from '@/components/actions/AddChargingStations.vue'
history: createWebHistory(),
routes: [
{
- path: '/',
- name: 'charging-stations',
components: {
- default: ChargingStationsView
- }
+ default: ChargingStationsView,
+ },
+ name: 'charging-stations',
+ path: '/',
},
{
- path: '/add-charging-stations',
- name: 'add-charging-stations',
components: {
+ action: AddChargingStations,
default: ChargingStationsView,
- action: AddChargingStations
- }
+ },
+ name: 'add-charging-stations',
+ path: '/add-charging-stations',
},
{
- path: '/set-supervision-url/:hashId/:chargingStationId',
- name: 'set-supervision-url',
components: {
+ action: SetSupervisionUrl,
default: ChargingStationsView,
- action: SetSupervisionUrl
},
- props: { default: false, action: true }
+ name: 'set-supervision-url',
+ path: '/set-supervision-url/:hashId/:chargingStationId',
+ props: { action: true, default: false },
},
{
- path: '/start-transaction/:hashId/:chargingStationId/:connectorId',
- name: 'start-transaction',
components: {
+ action: StartTransaction,
default: ChargingStationsView,
- action: StartTransaction
},
- props: { default: false, action: true }
+ name: 'start-transaction',
+ path: '/start-transaction/:hashId/:chargingStationId/:connectorId',
+ props: { action: true, default: false },
},
{
+ components: {
+ default: NotFoundView,
+ },
name: 'not-found',
path: '/:pathMatch(.*)*',
- components: {
- default: NotFoundView
- }
- }
- ]
+ },
+ ],
})
-export {}
+export type {}
declare module 'vue' {
export interface GlobalComponents {
RouterView: (typeof import('vue-router'))['RouterView']
}
interface ComponentCustomProperties {
- $configuration: import('vue').Ref<import('@/types').ConfigurationData>
- $templates: import('vue').Ref<string[]>
- $chargingStations: import('vue').Ref<import('@/types').ChargingStationData[]>
- $uiClient: import('@/composables').UIClient
+ $chargingStations: import('vue').Ref<import('@/types').ChargingStationData[]> | undefined
+ $configuration: import('vue').Ref<import('@/types').ConfigurationData> | undefined
+ $templates: import('vue').Ref<string[]> | undefined
+ $uiClient: import('@/composables').UIClient | undefined
}
}
import type { JsonObject } from './JsonType'
+export enum AmpereUnits {
+ AMPERE = 'A',
+ CENTI_AMPERE = 'cA',
+ DECI_AMPERE = 'dA',
+ MILLI_AMPERE = 'mA',
+}
+
+export enum CurrentType {
+ AC = 'AC',
+ DC = 'DC',
+}
+
export enum IdTagDistribution {
+ CONNECTOR_AFFINITY = 'connector-affinity',
RANDOM = 'random',
ROUND_ROBIN = 'round-robin',
- CONNECTOR_AFFINITY = 'connector-affinity'
+}
+
+export enum OCPP16AvailabilityType {
+ INOPERATIVE = 'Inoperative',
+ OPERATIVE = 'Operative',
+}
+
+export enum OCPP16ChargePointStatus {
+ AVAILABLE = 'Available',
+ CHARGING = 'Charging',
+ FAULTED = 'Faulted',
+ FINISHING = 'Finishing',
+ OCCUPIED = 'Occupied',
+ PREPARING = 'Preparing',
+ RESERVED = 'Reserved',
+ SUSPENDED_EV = 'SuspendedEV',
+ SUSPENDED_EVSE = 'SuspendedEVSE',
+ UNAVAILABLE = 'Unavailable',
+}
+
+export enum OCPP16FirmwareStatus {
+ Downloaded = 'Downloaded',
+ DownloadFailed = 'DownloadFailed',
+ Downloading = 'Downloading',
+ Idle = 'Idle',
+ InstallationFailed = 'InstallationFailed',
+ Installed = 'Installed',
+ Installing = 'Installing',
+}
+
+export enum OCPP16IncomingRequestCommand {
+ CHANGE_AVAILABILITY = 'ChangeAvailability',
+ CHANGE_CONFIGURATION = 'ChangeConfiguration',
+ CLEAR_CACHE = 'ClearCache',
+ CLEAR_CHARGING_PROFILE = 'ClearChargingProfile',
+ GET_CONFIGURATION = 'GetConfiguration',
+ GET_DIAGNOSTICS = 'GetDiagnostics',
+ REMOTE_START_TRANSACTION = 'RemoteStartTransaction',
+ REMOTE_STOP_TRANSACTION = 'RemoteStopTransaction',
+ RESET = 'Reset',
+ SET_CHARGING_PROFILE = 'SetChargingProfile',
+ TRIGGER_MESSAGE = 'TriggerMessage',
+ UNLOCK_CONNECTOR = 'UnlockConnector',
+}
+
+export enum OCPP16MessageTrigger {
+ BootNotification = 'BootNotification',
+ DiagnosticsStatusNotification = 'DiagnosticsStatusNotification',
+ FirmwareStatusNotification = 'FirmwareStatusNotification',
+ Heartbeat = 'Heartbeat',
+ MeterValues = 'MeterValues',
+ StatusNotification = 'StatusNotification',
+}
+
+export enum OCPP16RegistrationStatus {
+ ACCEPTED = 'Accepted',
+ PENDING = 'Pending',
+ REJECTED = 'Rejected',
+}
+
+export enum OCPP16RequestCommand {
+ AUTHORIZE = 'Authorize',
+ BOOT_NOTIFICATION = 'BootNotification',
+ DIAGNOSTICS_STATUS_NOTIFICATION = 'DiagnosticsStatusNotification',
+ HEARTBEAT = 'Heartbeat',
+ METER_VALUES = 'MeterValues',
+ START_TRANSACTION = 'StartTransaction',
+ STATUS_NOTIFICATION = 'StatusNotification',
+ STOP_TRANSACTION = 'StopTransaction',
+}
+
+export enum OCPPProtocol {
+ JSON = 'json',
+}
+
+export enum OCPPVersion {
+ VERSION_16 = '1.6',
+ VERSION_20 = '2.0',
+ VERSION_201 = '2.0.1',
+}
+
+export enum Voltage {
+ VOLTAGE_110 = 110,
+ VOLTAGE_230 = 230,
+ VOLTAGE_400 = 400,
+ VOLTAGE_800 = 800,
}
export interface AutomaticTransactionGeneratorConfiguration extends JsonObject {
enable: boolean
- minDuration: number
+ idTagDistribution?: IdTagDistribution
+ maxDelayBetweenTwoTransactions: number
maxDuration: number
minDelayBetweenTwoTransactions: number
- maxDelayBetweenTwoTransactions: number
+ minDuration: number
probabilityOfStart: number
- stopAfterHours: number
- stopAbsoluteDuration: boolean
requireAuthorize?: boolean
- idTagDistribution?: IdTagDistribution
+ stopAbsoluteDuration: boolean
+ stopAfterHours: number
}
+export type AvailabilityType = OCPP16AvailabilityType
+
+export type BootNotificationResponse = OCPP16BootNotificationResponse
+
+export type ChargePointStatus = OCPP16ChargePointStatus
+
export interface ChargingStationAutomaticTransactionGeneratorConfiguration extends JsonObject {
automaticTransactionGenerator?: AutomaticTransactionGeneratorConfiguration
automaticTransactionGeneratorStatuses?: Status[]
}
export interface ChargingStationData extends JsonObject {
- started: boolean
- stationInfo: ChargingStationInfo
+ automaticTransactionGenerator?: ChargingStationAutomaticTransactionGeneratorConfiguration
+ bootNotificationResponse?: BootNotificationResponse
connectors: ConnectorStatus[]
evses: EvseStatus[]
ocppConfiguration: ChargingStationOcppConfiguration
+ started: boolean
+ stationInfo: ChargingStationInfo
supervisionUrl: string
wsState?:
+ | typeof WebSocket.CLOSED
+ | typeof WebSocket.CLOSING
| typeof WebSocket.CONNECTING
| typeof WebSocket.OPEN
- | typeof WebSocket.CLOSING
- | typeof WebSocket.CLOSED
- bootNotificationResponse?: BootNotificationResponse
- automaticTransactionGenerator?: ChargingStationAutomaticTransactionGeneratorConfiguration
-}
-
-export enum OCPP16FirmwareStatus {
- Downloaded = 'Downloaded',
- DownloadFailed = 'DownloadFailed',
- Downloading = 'Downloading',
- Idle = 'Idle',
- InstallationFailed = 'InstallationFailed',
- Installing = 'Installing',
- Installed = 'Installed'
-}
-
-export interface FirmwareUpgrade extends JsonObject {
- versionUpgrade?: {
- patternGroup?: number
- step?: number
- }
- reset?: boolean
- failureStatus?: FirmwareStatus
-}
-
-export const FirmwareStatus = {
- ...OCPP16FirmwareStatus
-} as const
-export type FirmwareStatus = OCPP16FirmwareStatus
-
-export interface ChargingStationOptions extends JsonObject {
- supervisionUrls?: string | string[]
- persistentConfiguration?: boolean
- autoStart?: boolean
- autoRegister?: boolean
- enableStatistics?: boolean
- ocppStrictCompliance?: boolean
- stopTransactionsOnStopped?: boolean
}
export interface ChargingStationInfo extends JsonObject {
- hashId: string
- templateIndex: number
- templateName: string
- chargingStationId: string
- chargeBoxSerialNumber?: string
- chargePointSerialNumber?: string
- meterSerialNumber?: string
- maximumPower?: number // Always in Watt
- maximumAmperage?: number // Always in Ampere
- firmwareStatus?: FirmwareStatus
- templateHash?: string
- supervisionUrls?: string | string[]
- supervisionUrlOcppConfiguration?: boolean
- supervisionUrlOcppKey?: string
- supervisionUser?: string
- supervisionPassword?: string
- autoStart?: boolean
- ocppVersion?: OCPPVersion
- ocppProtocol?: OCPPProtocol
- ocppStrictCompliance?: boolean
- ocppPersistentConfiguration?: boolean
- stationInfoPersistentConfiguration?: boolean
+ amperageLimitationOcppKey?: string
+ amperageLimitationUnit?: AmpereUnits
automaticTransactionGeneratorPersistentConfiguration?: boolean
- idTagsFile?: string
+ autoReconnectMaxRetries?: number
+ autoRegister?: boolean
+ autoStart?: boolean
baseName: string
- nameSuffix?: string
- fixedName?: boolean
+ beginEndMeterValues?: boolean
+ chargeBoxSerialNumber?: string
chargePointModel: string
+ chargePointSerialNumber?: string
chargePointVendor: string
- firmwareVersionPattern?: string
- firmwareVersion?: string
+ chargingStationId: string
+ commandsSupport?: CommandsSupport
+ currentOutType?: CurrentType
+ customValueLimitationMeterValues?: boolean
+ enableStatistics?: boolean
+ firmwareStatus?: FirmwareStatus
firmwareUpgrade?: FirmwareUpgrade
+ firmwareVersion?: string
+ firmwareVersionPattern?: string
+ fixedName?: boolean
+ hashId: string
iccid?: string
+ idTagsFile?: string
imsi?: string
+ mainVoltageMeterValues?: boolean
+ maximumAmperage?: number // Always in Ampere
+ maximumPower?: number // Always in Watt
+ messageTriggerSupport?: Record<MessageTrigger, boolean>
+ meteringPerTransaction?: boolean
+ meterSerialNumber?: string
meterType?: string
- powerSharedByConnectors?: boolean
- currentOutType?: CurrentType
- voltageOut?: Voltage
+ nameSuffix?: string
numberOfPhases?: number
- useConnectorId0?: boolean
+ ocppPersistentConfiguration?: boolean
+ ocppProtocol?: OCPPProtocol
+ ocppStrictCompliance?: boolean
+ ocppVersion?: OCPPVersion
+ outOfOrderEndMeterValues?: boolean
+ phaseLineToLineVoltageMeterValues?: boolean
+ powerSharedByConnectors?: boolean
randomConnectors?: boolean
- resetTime?: number
- autoRegister?: boolean
- autoReconnectMaxRetries?: number
reconnectExponentialDelay?: boolean
registrationMaxRetries?: number
- enableStatistics?: boolean
remoteAuthorization?: boolean
- amperageLimitationOcppKey?: string
- amperageLimitationUnit?: AmpereUnits
- beginEndMeterValues?: boolean
- outOfOrderEndMeterValues?: boolean
- meteringPerTransaction?: boolean
- transactionDataMeterValues?: boolean
+ resetTime?: number
+ stationInfoPersistentConfiguration?: boolean
stopTransactionsOnStopped?: boolean
- mainVoltageMeterValues?: boolean
- phaseLineToLineVoltageMeterValues?: boolean
- customValueLimitationMeterValues?: boolean
- commandsSupport?: CommandsSupport
- messageTriggerSupport?: Record<MessageTrigger, boolean>
+ supervisionPassword?: string
+ supervisionUrlOcppConfiguration?: boolean
+ supervisionUrlOcppKey?: string
+ supervisionUrls?: string | string[]
+ supervisionUser?: string
+ templateHash?: string
+ templateIndex: number
+ templateName: string
+ transactionDataMeterValues?: boolean
+ useConnectorId0?: boolean
+ voltageOut?: Voltage
}
export interface ChargingStationOcppConfiguration extends JsonObject {
configurationKey?: ConfigurationKey[]
}
+export interface ChargingStationOptions extends JsonObject {
+ autoRegister?: boolean
+ autoStart?: boolean
+ enableStatistics?: boolean
+ ocppStrictCompliance?: boolean
+ persistentConfiguration?: boolean
+ stopTransactionsOnStopped?: boolean
+ supervisionUrls?: string | string[]
+}
+
export interface ConfigurationKey extends OCPPConfigurationKey {
- visible?: boolean
reboot?: boolean
+ visible?: boolean
}
-export interface OCPPConfigurationKey extends JsonObject {
- key: string
- readonly: boolean
- value?: string
+export interface ConnectorStatus extends JsonObject {
+ authorizeIdTag?: string
+ availability: AvailabilityType
+ bootStatus?: ChargePointStatus
+ energyActiveImportRegisterValue?: number // In Wh
+ idTagAuthorized?: boolean
+ idTagLocalAuthorized?: boolean
+ localAuthorizeIdTag?: string
+ status?: ChargePointStatus
+ transactionEnergyActiveImportRegisterValue?: number // In Wh
+ transactionId?: number
+ transactionIdTag?: string
+ transactionRemoteStarted?: boolean
+ transactionStarted?: boolean
}
-export enum OCPP16IncomingRequestCommand {
- RESET = 'Reset',
- CLEAR_CACHE = 'ClearCache',
- CHANGE_AVAILABILITY = 'ChangeAvailability',
- UNLOCK_CONNECTOR = 'UnlockConnector',
- GET_CONFIGURATION = 'GetConfiguration',
- CHANGE_CONFIGURATION = 'ChangeConfiguration',
- SET_CHARGING_PROFILE = 'SetChargingProfile',
- CLEAR_CHARGING_PROFILE = 'ClearChargingProfile',
- REMOTE_START_TRANSACTION = 'RemoteStartTransaction',
- REMOTE_STOP_TRANSACTION = 'RemoteStopTransaction',
- GET_DIAGNOSTICS = 'GetDiagnostics',
- TRIGGER_MESSAGE = 'TriggerMessage'
+export interface EvseStatus extends JsonObject {
+ availability: AvailabilityType
+ connectors?: ConnectorStatus[]
}
-export const IncomingRequestCommand = {
- ...OCPP16IncomingRequestCommand
+export const FirmwareStatus = {
+ ...OCPP16FirmwareStatus,
} as const
-export type IncomingRequestCommand = OCPP16IncomingRequestCommand
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type FirmwareStatus = OCPP16FirmwareStatus
-export enum OCPP16RequestCommand {
- BOOT_NOTIFICATION = 'BootNotification',
- HEARTBEAT = 'Heartbeat',
- STATUS_NOTIFICATION = 'StatusNotification',
- AUTHORIZE = 'Authorize',
- START_TRANSACTION = 'StartTransaction',
- STOP_TRANSACTION = 'StopTransaction',
- METER_VALUES = 'MeterValues',
- DIAGNOSTICS_STATUS_NOTIFICATION = 'DiagnosticsStatusNotification'
+export interface FirmwareUpgrade extends JsonObject {
+ failureStatus?: FirmwareStatus
+ reset?: boolean
+ versionUpgrade?: {
+ patternGroup?: number
+ step?: number
+ }
}
-export const RequestCommand = {
- ...OCPP16RequestCommand
+export const IncomingRequestCommand = {
+ ...OCPP16IncomingRequestCommand,
} as const
-export type RequestCommand = OCPP16RequestCommand
-
-export type BootNotificationResponse = OCPP16BootNotificationResponse
-
-export enum OCPP16RegistrationStatus {
- ACCEPTED = 'Accepted',
- PENDING = 'Pending',
- REJECTED = 'Rejected'
-}
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type IncomingRequestCommand = OCPP16IncomingRequestCommand
export interface OCPP16BootNotificationResponse extends JsonObject {
- status: OCPP16RegistrationStatus
currentTime: Date
interval: number
+ status: OCPP16RegistrationStatus
}
-export enum OCPP16MessageTrigger {
- BootNotification = 'BootNotification',
- DiagnosticsStatusNotification = 'DiagnosticsStatusNotification',
- FirmwareStatusNotification = 'FirmwareStatusNotification',
- Heartbeat = 'Heartbeat',
- MeterValues = 'MeterValues',
- StatusNotification = 'StatusNotification'
+export interface OCPPConfigurationKey extends JsonObject {
+ key: string
+ readonly: boolean
+ value?: string
}
export const MessageTrigger = {
- ...OCPP16MessageTrigger
+ ...OCPP16MessageTrigger,
} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
export type MessageTrigger = OCPP16MessageTrigger
-interface CommandsSupport extends JsonObject {
- incomingCommands: Record<IncomingRequestCommand, boolean>
- outgoingCommands?: Record<RequestCommand, boolean>
-}
-
-export enum OCPPVersion {
- VERSION_16 = '1.6',
- VERSION_20 = '2.0',
- VERSION_201 = '2.0.1'
-}
-
-export enum OCPPProtocol {
- JSON = 'json'
-}
-
-export enum CurrentType {
- AC = 'AC',
- DC = 'DC'
-}
-
-export enum Voltage {
- VOLTAGE_110 = 110,
- VOLTAGE_230 = 230,
- VOLTAGE_400 = 400,
- VOLTAGE_800 = 800
-}
-
-export enum AmpereUnits {
- MILLI_AMPERE = 'mA',
- CENTI_AMPERE = 'cA',
- DECI_AMPERE = 'dA',
- AMPERE = 'A'
-}
-
-export interface ConnectorStatus extends JsonObject {
- availability: AvailabilityType
- bootStatus?: ChargePointStatus
- status?: ChargePointStatus
- authorizeIdTag?: string
- idTagAuthorized?: boolean
- localAuthorizeIdTag?: string
- idTagLocalAuthorized?: boolean
- transactionRemoteStarted?: boolean
- transactionStarted?: boolean
- transactionId?: number
- transactionIdTag?: string
- energyActiveImportRegisterValue?: number // In Wh
- transactionEnergyActiveImportRegisterValue?: number // In Wh
-}
-
-export interface EvseStatus extends JsonObject {
- availability: AvailabilityType
- connectors?: ConnectorStatus[]
-}
-
-export enum OCPP16AvailabilityType {
- INOPERATIVE = 'Inoperative',
- OPERATIVE = 'Operative'
-}
-export type AvailabilityType = OCPP16AvailabilityType
-
-export enum OCPP16ChargePointStatus {
- AVAILABLE = 'Available',
- PREPARING = 'Preparing',
- CHARGING = 'Charging',
- OCCUPIED = 'Occupied',
- SUSPENDED_EVSE = 'SuspendedEVSE',
- SUSPENDED_EV = 'SuspendedEV',
- FINISHING = 'Finishing',
- RESERVED = 'Reserved',
- UNAVAILABLE = 'Unavailable',
- FAULTED = 'Faulted'
-}
-export type ChargePointStatus = OCPP16ChargePointStatus
+export const RequestCommand = {
+ ...OCPP16RequestCommand,
+} as const
+// eslint-disable-next-line @typescript-eslint/no-redeclare
+export type RequestCommand = OCPP16RequestCommand
export interface Status extends JsonObject {
- start?: boolean
- startDate?: Date
- lastRunDate?: Date
- stopDate?: Date
- stoppedDate?: Date
- authorizeRequests?: number
acceptedAuthorizeRequests?: number
- rejectedAuthorizeRequests?: number
- startTransactionRequests?: number
acceptedStartTransactionRequests?: number
- rejectedStartTransactionRequests?: number
- stopTransactionRequests?: number
acceptedStopTransactionRequests?: number
+ authorizeRequests?: number
+ lastRunDate?: Date
+ rejectedAuthorizeRequests?: number
+ rejectedStartTransactionRequests?: number
rejectedStopTransactionRequests?: number
skippedConsecutiveTransactions?: number
skippedTransactions?: number
+ start?: boolean
+ startDate?: Date
+ startTransactionRequests?: number
+ stopDate?: Date
+ stoppedDate?: Date
+ stopTransactionRequests?: number
+}
+
+interface CommandsSupport extends JsonObject {
+ incomingCommands: Record<IncomingRequestCommand, boolean>
+ outgoingCommands?: Record<RequestCommand, boolean>
}
}
export interface UIServerConfigurationSection {
- name?: string
- host: string
- port: number
- secure?: boolean
- protocol: Protocol
- version: ProtocolVersion
authentication?: {
enabled: boolean
+ password?: string
type: AuthenticationType
username?: string
- password?: string
}
+ host: string
+ name?: string
+ port: number
+ protocol: Protocol
+ secure?: boolean
+ version: ProtocolVersion
}
-type JsonPrimitive = string | number | boolean | Date | null
export type JsonObject = { [key in string]?: JsonType }
-export type JsonType = JsonPrimitive | JsonType[] | JsonObject
+export type JsonType = JsonObject | JsonPrimitive | JsonType[]
+type JsonPrimitive = boolean | Date | null | number | string
import type { JsonObject } from './JsonType'
-export enum Protocol {
- UI = 'ui'
-}
-
export enum ApplicationProtocol {
WS = 'ws',
- WSS = 'wss'
-}
-
-export enum ProtocolVersion {
- '0.0.1' = '0.0.1'
+ WSS = 'wss',
}
export enum AuthenticationType {
- PROTOCOL_BASIC_AUTH = 'protocol-basic-auth'
+ PROTOCOL_BASIC_AUTH = 'protocol-basic-auth',
}
-export type ProtocolRequest = [
- `${string}-${string}-${string}-${string}-${string}`,
- ProcedureName,
- RequestPayload
-]
-export type ProtocolResponse = [
- `${string}-${string}-${string}-${string}-${string}`,
- ResponsePayload
-]
-
-export type ProtocolRequestHandler = (
- payload: RequestPayload
-) => ResponsePayload | Promise<ResponsePayload>
-
export enum ProcedureName {
- SIMULATOR_STATE = 'simulatorState',
- START_SIMULATOR = 'startSimulator',
- STOP_SIMULATOR = 'stopSimulator',
- LIST_TEMPLATES = 'listTemplates',
- LIST_CHARGING_STATIONS = 'listChargingStations',
ADD_CHARGING_STATIONS = 'addChargingStations',
+ CLOSE_CONNECTION = 'closeConnection',
DELETE_CHARGING_STATIONS = 'deleteChargingStations',
- SET_SUPERVISION_URL = 'setSupervisionUrl',
- START_CHARGING_STATION = 'startChargingStation',
- STOP_CHARGING_STATION = 'stopChargingStation',
+ LIST_CHARGING_STATIONS = 'listChargingStations',
+ LIST_TEMPLATES = 'listTemplates',
OPEN_CONNECTION = 'openConnection',
- CLOSE_CONNECTION = 'closeConnection',
+ SET_SUPERVISION_URL = 'setSupervisionUrl',
+ SIMULATOR_STATE = 'simulatorState',
START_AUTOMATIC_TRANSACTION_GENERATOR = 'startAutomaticTransactionGenerator',
- STOP_AUTOMATIC_TRANSACTION_GENERATOR = 'stopAutomaticTransactionGenerator',
+ START_CHARGING_STATION = 'startChargingStation',
+ START_SIMULATOR = 'startSimulator',
START_TRANSACTION = 'startTransaction',
- STOP_TRANSACTION = 'stopTransaction'
+ STOP_AUTOMATIC_TRANSACTION_GENERATOR = 'stopAutomaticTransactionGenerator',
+ STOP_CHARGING_STATION = 'stopChargingStation',
+ STOP_SIMULATOR = 'stopSimulator',
+ STOP_TRANSACTION = 'stopTransaction',
}
-export interface RequestPayload extends JsonObject {
- hashIds?: string[]
- connectorIds?: number[]
+export enum Protocol {
+ UI = 'ui',
}
+export enum ProtocolVersion {
+ '0.0.1' = '0.0.1',
+}
export enum ResponseStatus {
+ FAILURE = 'failure',
SUCCESS = 'success',
- FAILURE = 'failure'
}
-export interface ResponsePayload extends JsonObject {
- status: ResponseStatus
+export type ProtocolRequest = [
+ `${string}-${string}-${string}-${string}-${string}`,
+ ProcedureName,
+ RequestPayload
+]
+
+export type ProtocolRequestHandler = (
+ payload: RequestPayload
+) => Promise<ResponsePayload> | ResponsePayload
+
+export type ProtocolResponse = [
+ `${string}-${string}-${string}-${string}-${string}`,
+ ResponsePayload
+]
+
+export interface RequestPayload extends JsonObject {
+ connectorIds?: number[]
hashIds?: string[]
}
-interface TemplateStatistics extends JsonObject {
- configured: number
- added: number
- started: number
- indexes: number[]
+export interface ResponsePayload extends JsonObject {
+ hashIds?: string[]
+ status: ResponseStatus
}
export interface SimulatorState extends JsonObject {
- version: string
started: boolean
templateStatistics: Record<string, TemplateStatistics>
+ version: string
+}
+
+interface TemplateStatistics extends JsonObject {
+ added: number
+ configured: number
+ indexes: number[]
+ started: number
}
ChargingStationInfo,
ChargingStationOptions,
ConnectorStatus,
- Status
+ Status,
} from './ChargingStationType'
export type { ConfigurationData, UIServerConfigurationSection } from './ConfigurationType'
export {
type RequestPayload,
type ResponsePayload,
ResponseStatus,
- type SimulatorState
+ type SimulatorState,
} from './UIProtocol'
if (
getFromLocalStorage<number>('uiServerConfigurationIndex', 0) !== state.uiServerIndex
) {
- $uiClient.setConfiguration(
- ($configuration.value.uiServer as UIServerConfigurationSection[])[
+ $uiClient?.setConfiguration(
+ ($configuration!.value.uiServer as UIServerConfigurationSection[])[
state.uiServerIndex
]
)
registerWSEventListeners()
- $uiClient.registerWSEventListener(
+ $uiClient?.registerWSEventListener(
'open',
() => {
setToLocalStorage<number>('uiServerConfigurationIndex', state.uiServerIndex)
clearToggleButtons()
+ refresh()
$route.name !== 'charging-stations' &&
$router.push({ name: 'charging-stations' })
},
{ once: true }
)
- $uiClient.registerWSEventListener(
+ $uiClient?.registerWSEventListener(
'error',
() => {
state.uiServerIndex = getFromLocalStorage<number>(
'uiServerConfigurationIndex',
0
)
- $uiClient.setConfiguration(
- ($configuration.value.uiServer as UIServerConfigurationSection[])[
+ $uiClient?.setConfiguration(
+ ($configuration!.value.uiServer as UIServerConfigurationSection[])[
getFromLocalStorage<number>('uiServerConfigurationIndex', 0)
]
)
<ToggleButton
:id="'simulator'"
:key="state.renderSimulator"
- :status="simulatorState?.started"
- :on="() => startSimulator()"
- :off="() => stopSimulator()"
:class="simulatorButtonClass"
+ :off="() => stopSimulator()"
+ :on="() => startSimulator()"
+ :status="simulatorState?.started"
>
{{ simulatorButtonMessage }}
</ToggleButton>
<ToggleButton
:id="'add-charging-stations'"
:key="state.renderAddChargingStations"
- :shared="true"
- :on="
+ :off="
() => {
- $router.push({ name: 'add-charging-stations' })
+ $router.push({ name: 'charging-stations' })
}
"
- :off="
+ :on="
() => {
- $router.push({ name: 'charging-stations' })
+ $router.push({ name: 'add-charging-stations' })
}
"
+ :shared="true"
@clicked="
() => {
state.renderChargingStations = randomUUID()
/>
</Container>
<CSTable
- v-show="Array.isArray($chargingStations.value) && $chargingStations.value.length > 0"
+ v-show="Array.isArray($chargingStations?.value) && $chargingStations.value.length > 0"
:key="state.renderChargingStations"
- :charging-stations="$chargingStations.value"
+ :charging-stations="$chargingStations!.value"
@need-refresh="
() => {
state.renderAddChargingStations = randomUUID()
import { computed, getCurrentInstance, onMounted, onUnmounted, ref, watch } from 'vue'
import { useToast } from 'vue-toast-notification'
+import type {
+ ChargingStationData,
+ ResponsePayload,
+ SimulatorState,
+ UIServerConfigurationSection,
+} from '@/types'
+
import ReloadButton from '@/components/buttons/ReloadButton.vue'
import ToggleButton from '@/components/buttons/ToggleButton.vue'
import CSTable from '@/components/charging-stations/CSTable.vue'
getLocalStorage,
randomUUID,
setToLocalStorage,
- useUIClient
+ useUIClient,
} from '@/composables'
-import type {
- ChargingStationData,
- ResponsePayload,
- SimulatorState,
- UIServerConfigurationSection
-} from '@/types'
const simulatorState = ref<SimulatorState | undefined>(undefined)
)
const simulatorButtonMessage = computed<string>(
() =>
- `${simulatorState.value?.started === true ? 'Stop' : 'Start'} Simulator${simulatorState.value?.version != null ? ` (${simulatorState.value.version})` : ''}`
+ `${simulatorState.value?.started === true ? 'Stop' : 'Start'} Simulator${
+ simulatorState.value?.version != null ? ` (${simulatorState.value.version})` : ''
+ }`
)
const state = ref<{
- renderSimulator: `${string}-${string}-${string}-${string}-${string}`
- renderAddChargingStations: `${string}-${string}-${string}-${string}-${string}`
- renderChargingStations: `${string}-${string}-${string}-${string}-${string}`
+ gettingChargingStations: boolean
gettingSimulatorState: boolean
gettingTemplates: boolean
- gettingChargingStations: boolean
+ renderAddChargingStations: `${string}-${string}-${string}-${string}-${string}`
+ renderChargingStations: `${string}-${string}-${string}-${string}-${string}`
+ renderSimulator: `${string}-${string}-${string}-${string}-${string}`
uiServerIndex: number
}>({
- renderSimulator: randomUUID(),
- renderAddChargingStations: randomUUID(),
- renderChargingStations: randomUUID(),
+ gettingChargingStations: false,
gettingSimulatorState: false,
gettingTemplates: false,
- gettingChargingStations: false,
- uiServerIndex: getFromLocalStorage<number>('uiServerConfigurationIndex', 0)
+ renderAddChargingStations: randomUUID(),
+ renderChargingStations: randomUUID(),
+ renderSimulator: randomUUID(),
+ uiServerIndex: getFromLocalStorage<number>('uiServerConfigurationIndex', 0),
})
+const refresh = (): void => {
+ state.value.renderChargingStations = randomUUID()
+ state.value.renderAddChargingStations = randomUUID()
+}
+
const clearToggleButtons = (): void => {
for (const key in getLocalStorage()) {
if (key.includes('toggle-button')) {
deleteFromLocalStorage(key)
}
}
- state.value.renderChargingStations = randomUUID()
- state.value.renderAddChargingStations = randomUUID()
}
const app = getCurrentInstance()
-watch(app!.appContext.config.globalProperties.$chargingStations, () => {
+watch(app!.appContext.config.globalProperties!.$chargingStations, () => {
state.value.renderChargingStations = randomUUID()
})
const clearTemplates = (): void => {
if (app != null) {
- app.appContext.config.globalProperties.$templates.value = []
+ app.appContext.config.globalProperties.$templates!.value = []
}
}
const clearChargingStations = (): void => {
if (app != null) {
- app.appContext.config.globalProperties.$chargingStations.value = []
+ app.appContext.config.globalProperties.$chargingStations!.value = []
}
}
.simulatorState()
.then((response: ResponsePayload) => {
simulatorState.value = response.state as SimulatorState
+ return undefined
+ })
+ .finally(() => {
+ state.value.gettingSimulatorState = false
})
.catch((error: Error) => {
$toast.error('Error at fetching simulator state')
console.error('Error at fetching simulator state:', error)
})
- .finally(() => {
- state.value.gettingSimulatorState = false
- })
}
}
.listTemplates()
.then((response: ResponsePayload) => {
if (app != null) {
- app.appContext.config.globalProperties.$templates.value = response.templates as string[]
+ app.appContext.config.globalProperties.$templates!.value = response.templates as string[]
}
+ return undefined
+ })
+ .finally(() => {
+ state.value.gettingTemplates = false
})
.catch((error: Error) => {
clearTemplates()
$toast.error('Error at fetching charging station templates')
console.error('Error at fetching charging station templates:', error)
})
- .finally(() => {
- state.value.gettingTemplates = false
- })
}
}
.listChargingStations()
.then((response: ResponsePayload) => {
if (app != null) {
- app.appContext.config.globalProperties.$chargingStations.value =
+ app.appContext.config.globalProperties.$chargingStations!.value =
response.chargingStations as ChargingStationData[]
}
+ return undefined
+ })
+ .finally(() => {
+ state.value.gettingChargingStations = false
})
.catch((error: Error) => {
clearChargingStations()
$toast.error('Error at fetching charging stations')
console.error('Error at fetching charging stations:', error)
})
- .finally(() => {
- state.value.gettingChargingStations = false
- })
}
}
unregisterWSEventListeners()
})
-const uiServerConfigurations: { index: number; configuration: UIServerConfigurationSection }[] = (
- app?.appContext.config.globalProperties.$configuration.value
+const uiServerConfigurations: {
+ configuration: UIServerConfigurationSection
+ index: number
+}[] = (
+ app!.appContext.config.globalProperties.$configuration!.value
.uiServer as UIServerConfigurationSection[]
).map((configuration: UIServerConfigurationSection, index: number) => ({
+ configuration,
index,
- configuration
}))
const startSimulator = (): void => {
uiClient
.startSimulator()
.then(() => {
- $toast.success('Simulator successfully started')
+ return $toast.success('Simulator successfully started')
+ })
+ .finally(() => {
+ getSimulatorState()
})
.catch((error: Error) => {
$toast.error('Error at starting simulator')
console.error('Error at starting simulator:', error)
})
- .finally(() => {
- getSimulatorState()
- })
}
const stopSimulator = (): void => {
uiClient
.stopSimulator()
.then(() => {
clearChargingStations()
- $toast.success('Simulator successfully stopped')
+ return $toast.success('Simulator successfully stopped')
+ })
+ .finally(() => {
+ getSimulatorState()
})
.catch((error: Error) => {
$toast.error('Error at stopping simulator')
console.error('Error at stopping simulator:', error)
})
- .finally(() => {
- getSimulatorState()
- })
}
</script>
-<template><Container id="not-found">404 - Not found</Container></template>
+<template>
+ <Container id="not-found">
+ 404 - Not found
+ </Container>
+</template>
<script setup lang="ts">
import Container from '@/components/Container.vue'
+import finalhandler from 'finalhandler'
import { createServer } from 'node:http'
import { dirname, join } from 'node:path'
import { env } from 'node:process'
import { fileURLToPath } from 'node:url'
-
-import finalhandler from 'finalhandler'
import serveStatic from 'serve-static'
const isCFEnvironment = env.VCAP_APPLICATION != null
-const PORT = isCFEnvironment ? parseInt(env.PORT) : 3030
+const PORT = isCFEnvironment ? Number.parseInt(env.PORT) : 3030
const uiPath = join(dirname(fileURLToPath(import.meta.url)), './dist')
const serve = serveStatic(uiPath)
import { shallowMount } from '@vue/test-utils'
import { expect, test } from 'vitest'
-import CSTable from '@/components/charging-stations/CSTable.vue'
import type { ChargingStationData } from '@/types'
+import CSTable from '@/components/charging-stations/CSTable.vue'
+
test('renders CS table columns name', () => {
const chargingStations: ChargingStationData[] = []
const wrapper = shallowMount(CSTable, {
- props: { chargingStations, idTag: '0' }
+ props: { chargingStations, idTag: '0' },
})
expect(wrapper.text()).to.include('Name')
expect(wrapper.text()).to.include('Started')
{
"$schema": "https://json.schemastore.org/tsconfig",
- "extends": ["@tsconfig/node20/tsconfig.json", "@vue/tsconfig/tsconfig.dom.json"],
+ "extends": ["@tsconfig/node22/tsconfig.json", "@vue/tsconfig/tsconfig.dom.json"],
"compilerOptions": {
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
+ "noImplicitOverride": true,
"sourceMap": true,
"composite": true,
"baseUrl": "./",
"@/*": ["./src/*"]
}
},
- "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", "tests/**/*.tsx"],
- "exclude": ["node_modules"]
+ "include": ["*.ts", "src/**/*.ts", "src/**/*.vue", "tests/**/*.ts"]
}
-import { fileURLToPath, URL } from 'node:url'
-
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
+import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [vue(), vueJsx()],
resolve: {
alias: {
- '@': fileURLToPath(new URL('./src', import.meta.url))
- }
- }
+ '@': fileURLToPath(new URL('./src', import.meta.url)),
+ },
+ },
})
import { fileURLToPath } from 'node:url'
-
import { mergeConfig } from 'vite'
import { configDefaults, defineConfig } from 'vitest/config'
viteConfig,
defineConfig({
test: {
+ coverage: {
+ provider: 'v8',
+ reporter: ['text', 'lcov'],
+ },
environment: 'jsdom',
exclude: [...configDefaults.exclude, 'e2e/*'],
root: fileURLToPath(new URL('./', import.meta.url)),
- coverage: {
- provider: 'v8',
- reporter: ['text', 'lcov']
- }
- }
+ },
})
)